GTK+ IOStream  Beta
<< GTK+ >> add C++ IOStream operators to GTK+. Now with extra abilities ... like network serialisation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Selection.H
Go to the documentation of this file.
1 /* Copyright 2000-2013 Matt Flax <flatmax@flatmax.org>
2  This file is part of GTK+ IOStream class set
3 
4  GTK+ IOStream is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  GTK+ IOStream is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You have received a copy of the GNU General Public License
15  along with GTK+ IOStream
16  */
17 
18 #ifndef SELECTION_H_
19 #define SELECTION_H_
20 
21 
22 #include <iomanip>
23 #include <utility>
24 #include <gtk/gtk.h>
25 
26 #include <string.h>
27 
28 #include "mffm/LinkList.H"
29 
30 using namespace std;
31 
37 class SelectionColumn : public LinkList<pair<string *, GType> *> {
38  GtkTreeViewColumn *column;
39  int number;
40 public:
45  SelectionColumn(const char*title, int number_) {
46  number=number_;
47  column=gtk_tree_view_column_new();
48  gtk_tree_view_column_set_title (column, title);
49  setTitleAlignment(0.5);
50  }
51 
54  virtual ~SelectionColumn(void) {
55  while (getCount()) { // free up the string pointers in the inherited LinkList<string*>
56  pair<string *, GType> *deleteMe=remove();
57  delete deleteMe->first;
58  delete deleteMe;
59  }
60  }
61 
65  void setTitleAlignment(float align) {
66  gtk_tree_view_column_set_alignment(column, align);
67  }
68 
74  void setAlignment(float xAlign, float yAlign) {
75  GList*renderers=gtk_tree_view_column_get_cell_renderers(column);
76  for (uint i=0;i<g_list_length(renderers);i++)
77  //g_object_set(GTK_CELL_RENDERER(g_list_nth_data(renderers,i)), "align-set", 1, "xalign", xAlign, "yalign", yAlign, NULL);
78  gtk_cell_renderer_set_alignment(GTK_CELL_RENDERER(g_list_nth_data(renderers,i)), xAlign, yAlign);
79  }
80 
81 // /** \brief Set the justification of the text column contents
82 // Justify the text renderer contents with respect to the edges of the column.
83 // \param justification The justification 0.0 for left and 1.0 for right, (0.5 center).
84 // */
85 // void setJustification(float justification){
86 // GList*renderers=gtk_tree_view_column_get_cell_renderers(column);
87 // cout<<"flatmax : setJustification : g_list_length(renderers) "<<g_list_length(renderers)<<endl;
88 // for (uint i=0;i<g_list_length(renderers);i++){
89 // cout<<"flatmax "<<i<<endl;
90 // g_object_set(GTK_CELL_RENDERER(g_list_nth_data(renderers,i)), "align-set", 1, "alignment", justification, NULL);
91 // //g_object_set(GTK_CELL_RENDERER(g_list_nth_data(renderers,i)), "xalign", justification, NULL);
92 // }
93 // }
94 
95 // /** \brief Set the justification of the text column contents
96 // Justify the text renderer contents with respect to the edges of the column.
97 // \param justification The justification PangoAlignment = {PANGO_ALIGN_LEFT, PANGO_ALIGN_CENTER, PANGO_ALIGN_RIGHT};
98 // */
99 // void setJustification(PangoAlignment justification){
100 // GList*renderers=gtk_tree_view_column_get_cell_renderers(column);
101 // cout<<"flatmax : setJustification : g_list_length(renderers) "<<g_list_length(renderers)<<endl;
102 // for (uint i=0;i<g_list_length(renderers);i++){
103 // cout<<"flatmax "<<i<<endl;
104 // g_object_set(GTK_CELL_RENDERER_TEXT(g_list_nth_data(renderers,i)), "align-set", 1, "alignment", justification, NULL);
105 // ////g_object_set(GTK_CELL_RENDERER(g_list_nth_data(renderers,i)), "alignment", justification, NULL);
106 // }
107 // }
108 //
116  SelectionColumn &add(string *name, GType whichType, GtkCellRenderer *renderer, int source, gboolean expand=true) {
117  gtk_cell_renderer_set_alignment(renderer, 0.5,0.5); // place in the middle
118  LinkList<pair<string*,GType> *>::add(new pair<string*,GType>(name, whichType));
119  gtk_tree_view_column_pack_start (column, renderer, expand);
120  gtk_tree_view_column_add_attribute (column, renderer, name->c_str(), source);
121  return *this;
122  }
123 
124 // /** Add a renderer to the column.
125 // This operator uses this column as the source, and doesn't expand during render
126 // \param detail get<0>(detail) is the name, get<1>(detail) is the renderer, get<2>(detail) is the source, get<3>(detail) is the expansion
127 // */
128 // SelectionColumn &operator<<(tuple<string*, GtkCellRenderer*, int, gboolean> detail){
129 // return add(get<0>(detail),get<1>(detail),get<2>(detail),get<3>(detail));
130 // }
131 //
132 // /** Add a renderer to the column.
133 // This operator uses this column as the source, and doesn't expand during render
134 // \param detail get<0>(detail) is the name, get<1>(detail) is the renderer, get<2>(detail) is the source
135 // */
136 // SelectionColumn &operator<<(tuple<string*, GtkCellRenderer*, int> detail){
137 // return add(get<0>(detail),get<1>(detail),get<2>(detail));
138 // }
139 
144  SelectionColumn &operator<<(pair<string*, GtkCellRendererText*> detail) {
145  return add(detail.first,G_TYPE_STRING,(GtkCellRenderer *)detail.second, number);
146  }
147 
152  SelectionColumn &operator<<(pair<string*, GtkCellRendererPixbuf*> detail) {
153  return add(detail.first,GDK_TYPE_PIXBUF,(GtkCellRenderer *)detail.second, number);
154  }
155 
159  GtkTreeViewColumn *getColumn(void) {
160  return column;
161  }
162 
166  int getNumber(void) {
167  return number;
168  }
169 
180  void setSizing(GtkTreeViewColumnSizing sz){
181  gtk_tree_view_column_set_sizing(column,sz);
182  }
183 
188  GtkTreeViewColumnSizing getSizing(void){
189  return gtk_tree_view_column_get_sizing(column);
190  }
191 
192 };
193 
194 
233 class Selection : public LinkList<SelectionColumn *> {
234 
237  void init(void) {
238  tree = gtk_tree_view_new();
239  }
240 
241 // GtkTreeIter* getLastIter(void){
242 // GtkTreeIter *iter=new GtkTreeIter;
243 // GtkTreeStore *store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree)));
244 //
245 // GtkTreeIter last;
246 // if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), iter)){
247 // cout<<"n children "<<gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), iter)<<endl;
248 // while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &last))
249 // (*iter)=last;
250 // } else{
251 // delete iter;
252 // return NULL;
253 // }
254 // return iter;
255 // }
256 
261  GtkTreeIter* getLastIter(GtkTreeStore *store=NULL) {
262  if (store==NULL) // get the local tree store
263  store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree)));
264  GtkTreeIter* iter = new GtkTreeIter;
265  if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), iter, NULL,gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL)-1))
266  return iter;
267  else
268  return NULL;
269  }
270 
276  GtkTreeIter* appendRow(GtkTreeStore *store=NULL) {
277  if (store==NULL) // get the local tree store
278  store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree)));
279  GtkTreeIter* iter=NULL;
280  if (store) {
281  iter=new GtkTreeIter;
282  if (iter)
283  gtk_tree_store_append(store, iter, NULL);
284  }
285  return iter;
286  }
287 
293  GtkTreeIter* appendNewIter(GtkTreeStore *store, gboolean sameRow, gboolean sameColumn) {
294  GtkTreeIter* iter=NULL;
295  if (!sameColumn)
296  next();
297  if (sameRow) { // find the correct column and add to the same row
298  iter=getLastIter(store);
299  }
300 
301  if (iter==NULL)
302  iter=appendRow(store);
303  return iter;
304  }
305 
306 protected:
307  GtkWidget *tree;
308  GtkTreeSelection *selection;
309 
314  SelectionColumn *currentCol=current(); // remember the current column number
315  grab(1);
316  prev(); // get the last column
317  int which=0;
318  while (next()!=currentCol) // keep getting the next unitl it is the same as the original state
319  which++;
320  return which; // return the column number, starting from zero, the LinkList's state is as it was upon entry
321  }
322 public:
323 
326  Selection(void) {
327  init();
328  }
329 
333  Selection(const char *listName, GCallback callback=NULL) {
334  init();
335 
336  SelectionColumn *sc= new SelectionColumn(listName, getCount()); // create the new column
337  // gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree), FALSE); // use this to hide the headers
338 
339  *sc<<pair<string*, GtkCellRendererText*>(new string("text"), GTK_CELL_RENDERER_TEXT(gtk_cell_renderer_text_new()));
340 
341  add(sc);
342 
343  if (callback)
344  setSelectionCallback(callback);
345  }
346 
350  void setSelectionCallback(GCallback callback) {
351  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
352  setSelectionCallback("changed", callback, this);
353  }
354 
360  void setSelectionCallback(const char *event, GCallback callback, gpointer data) {
361  g_signal_connect(selection, event, callback, data);
362  }
363 
373  void setTreeCallback(const char *event, GCallback callback, gpointer data) {
374  g_signal_connect(tree, event, G_CALLBACK(callback), data);
375  }
376 
379  void add(SelectionColumn *newCol) {
380  LinkList<SelectionColumn *>::add(newCol); // add to the list of columns
381 
382  gtk_tree_view_append_column(GTK_TREE_VIEW(tree), current()->getColumn());
383 
384  // find the types and create a new store, then attach to the current treeview
385  // find the total number of renderers.
386 // int rendCnt=0; // in the future support one column with many renderers
387 // for (int i=0;i<getCount();i++)
388 // rendCnt+=next()->getCount();
389 // GType types[rendCnt]; // create the type holder
390 // grab(1); prev(); // get the last column and iterate from there
391 // int index=0;
392 // for (int i=0;i<getCount();i++){
393 // for (int j=0; j<current()->getCount();j++){
394 // types[index++]=current()->next()->second;
395 // }
396 // next();
397 // }
398 
399  GType types[getCount()]; // create the type holder
400  grab(1);
401  prev(); // get the last column and iterate from there
402  for (int i=0; i<getCount(); i++) {
403  types[i]=next()->current()->second;
404  }
405 
406  while (next()!=newCol) ; // get the linklist back to its original location
407 
408  GtkTreeStore *store = gtk_tree_store_newv(getCount(), types); // get the column type
409  gtk_tree_view_set_model(GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store));
410  g_object_unref(store);
411  }
412 
417  void setCallbackAfter(GCallback callback, void *data) {
418  g_signal_connect_after(selection, "changed", G_CALLBACK(callback), data);
419  }
420 
423  GtkWidget *getWidget(void) {
424  return tree;
425  }
426 
429  void show(void) {
430  gtk_widget_show_all(tree);
431  }
432 
435  void hide(void) {
436  gtk_widget_hide(tree);
437  }
438 
442  void getSelection(char *value) {
443  GtkTreeIter iter;
444  GtkTreeModel *model;
445  char *val;
446 
447  int colNum=currentColumnNumber();
448  if (gtk_tree_selection_get_selected(GTK_TREE_SELECTION(selection), &model, &iter)) {
449  gtk_tree_model_get(model, &iter, colNum, &val, -1);
450  if (val)
451  strcpy(value,val);
452  else
453  value[0]='\0';
454  g_free(val);
455  }
456  }
457 
466  void add(const char *text, gboolean sameRow=false, gboolean sameColumn=true) {
467  GtkTreeStore *store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree)));
468  GtkTreeIter* iter=appendNewIter(store, sameRow, sameColumn);
469 
470  int whichColumn=currentColumnNumber();
471  if (iter) {
472  gtk_tree_store_set(store, iter, whichColumn, text, -1);
473  delete iter;
474  }
475  }
476 
485  void add(GdkPixbuf *pixbuf, gboolean sameRow=false, gboolean sameColumn=true) {
486  GtkTreeStore *store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree)));
487  GtkTreeIter* iter=appendNewIter(store, sameRow, sameColumn);
488 
489  int whichColumn=currentColumnNumber();
490  if (iter) {
491  gtk_tree_store_set(store, iter, whichColumn, pixbuf, -1);
492  delete iter;
493  }
494  }
495 
498  void clear(void) {
499  //GtkTreeStore *store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (tree)));
500  GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree));
501  GtkTreeIter iter;
502 
503  if (gtk_tree_model_get_iter_first(model, &iter) == FALSE)
504  return;
505  gtk_tree_store_clear(GTK_TREE_STORE(model));
506  }
507 // /** add a pixbuf item to the selection column
508 // if you want to add to a different column, shift the inherited LinkList<SelectionColumn *> to the correct one.
509 // For example use one of these to locate the desired column prior to adding : LinkList<SelectionColumn *>::grab, LinkList<SelectionColumn *>::next, LinkList<SelectionColumn *>::prev
510 // \param firstColumn, which column to start with, 1 for the first column
511 // \return This Selection object
512 // */
513 // void addRow(int firstColumn, ...) {
514 // GtkTreeStore *store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree)));
515 // GtkTreeIter* iter=appendNewIter(store, false, false);
516 // grab(firstColumn);
517 // va_list var_args;
518 // va_start (var_args, firstColumn);
519 // gtk_tree_store_set_valist (store, iter, var_args);
520 // va_end (var_args);
521 // }
522 
523 // /** add a list of items to the same row in each column - starting from the first column
524 // \param ll the LinkList of items to add to the list on the current row
525 // \return This Selection object
526 // */
527 // void add(LinkList<GValue> &ll) {
528 // // int whichColumn=currentColumnNumber(); // restore current column at the end
529 // GtkTreeIter iter;
530 // GtkTreeStore *store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree)));
531 // int cols[ll.getCount()];
532 // GValue values[ll.getCount()];
533 //
534 // ll.grab(1); ll.prev(); // get the last element on the linked list
535 // for (int i=0;i<ll.getCount();i++){
536 // cols[i]=i;
537 // g_value_init (&values[i], next()->current->second); // setup the current type
538 // =ll.next();
539 // }
540 //
541 // gtk_tree_store_append(store, &iter, NULL);
542 // gtk_tree_store_set_valuesv(store, &iter, cols, values, ll.getCount());
544 // }
545 
552  Selection & operator<<(const char *text) {
553  add(text);
554  return *this;
555  }
556 
563  Selection & operator<<(GdkPixbuf *pixbuf) {
564  add(pixbuf);
565  return *this;
566  }
567 
568 // /** add a row with multiple items
569 // starts from row 0
570 // \param ll the LinkList of items to add
571 // \return This Selection object
572 // */
573 // Selection & operator<<(LinkList<void*> &ll) {
574 // add(ll);
575 // return *this;
576 // }
577 
583  add(newCol);
584  return *this;
585  }
586 
596  void selectRow(char *path){
597  GtkTreePath *pathLocal = gtk_tree_path_new_from_string (path);
598  //gtk_tree_view_row_activated(GTK_TREE_VIEW(tree), pathLocal, current()->getColumn());
599  gtk_tree_selection_select_path(selection, pathLocal);
600  }
601 };
602 #endif //SELECTION_H_