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
Buttons.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 #ifndef BUTTONS_H_
18 #define BUTTONS_H_
19 
20 #include <iomanip>
21 #include <gtk/gtk.h>
22 #include <mffm/LinkList.H>
23 
24 #ifdef _MSC_VER
25 #pragma warning( disable : 4005 4554)
26 #endif
27 
31 public:
32 #ifdef WIN32 // visual C++ doesn't support compound literals
33  labelFuncData(void){str=NULL; func=NULL; data=NULL;}
34  labelFuncData(char *s, void (*f)(void *, void *), gpointer d){str=s; func=f; data=d;}
35 #endif
36  char *str;
37  void (*func)(void *arg1, void *arg2);
38  gpointer data;
39 };
40 #define BUTTONLABELSTRUCT(s,f,d) (labelFuncData){s,f,d}
41 #ifdef WIN32 // visual C++ doesn't support compound literals
42 #define BUTTONLABELSTRUCT(s,f,d) labelFuncData(s,f,d)
43 #endif
44 
46 #define GDKPIXMAPCREATE(win, ref) gdk_pixmap_colormap_create_from_xpm_d(win->window,gtk_widget_get_colormap(win),NULL,NULL,ref)
47 
48 #define GTKPIXMAPCREATE(pixGdk) (GtkPixmap*)gtk_image_new_from_pixmap(pixGdk, NULL)
49 
52 public:
53 #ifdef WIN32 // visual C++ doesn't support compound literals
54  pixmapFuncData(const char **p, void (*f)(void *, void *), gpointer d){pixGtk=p; func=f; data=d;}
55 #endif
56  const char **pixGtk;
57  void (*func)(void *arg1, void *arg2);
58  gpointer data;
59 };
60 #define BUTTONPIXMAPSTRUCT(p,f,d) (pixmapFuncData){p,f,d}
61 #ifdef WIN32 // visual C++ doesn't support compound literals
62 #define BUTTONPIXMAPSTRUCT(p,f,d) pixmapFuncData(p,f,d)
63 #endif
64 
68 public:
69 #ifdef WIN32 // visual C++ doesn't support compound literals
70  pixmapFuncDataTransparent(const char **i, void (*f)(void *, void *), gpointer d){imageXPM=i; func=f; data=d;}
71 #endif
72  const char **imageXPM;
73  void (*func)(void *arg1, void *arg2);
74  gpointer data;
75 };
76 #define BUTTONPIXMAPSTRUCTTRANSPARENT(i,f,d) (pixmapFuncDataTransparent){i,f,d}
77 #ifdef WIN32 // visual C++ doesn't support compound literals
78 #define BUTTONPIXMAPSTRUCTTRANSPARENT(i,f,d) pixmapFuncDataTransparent(i,f,d)
79 #endif
80 
84 public:
85 #ifdef WIN32 // visual C++ doesn't support compound literals
86  toggleFuncData(char *s, void (*f)(void *, void *), gpointer d){str=s; func=f; data=d;}
87 #endif
88  char *str;
89  void (*func)(void *arg1, void *arg2);
90  gpointer data;
91 };
92 #define BUTTONTOGGLESTRUCT(s,f,d) (toggleFuncData){s,f,d}
93 #ifdef WIN32 // visual C++ doesn't support compound literals
94 #define BUTTONTOGGLESTRUCT(s,f,d) toggleFuncData(s,f,d)
95 #endif
96 
100 public:
101 #ifdef WIN32 // visual C++ doesn't support compound literals
102  arrowFuncData(void){func=NULL; data=NULL; whichArrow=0; whichShadow=0;}
103  arrowFuncData(void (*f)(void *, void *), gpointer d, GtkArrowType at, GtkShadowType sh, GtkWidget *a){func=f; data=d; whichArrow=at; whichShadow=sh;}
104 #endif
105  void (*func)(void *arg1, void *arg2);
106  gpointer data;
107  GtkArrowType whichArrow;
108  GtkShadowType whichShadow;
109 };
110 #define BUTTONARROWSTRUCT(f, d, a, sh) (arrowFuncData){f,d, a, sh}
111 #ifdef WIN32 // visual C++ doesn't support compound literals
112 #define BUTTONARROWSTRUCT(f,d,a,sh) arrowFuncData(f,d,a,sh)
113 #endif
114 
118 public:
119 #ifdef WIN32 // visual C++ doesn't support compound literals
120  radioFuncData(char *s, void (*f)(void *, void *), gpointer d){str=s; func=f; data=d;}
121 #endif
122  char *str;
123  void (*func)(void *arg1, void *arg2);
124  gpointer data;
125 };
126 #define BUTTONRADIOSTRUCT(s,f,d) (radioFuncData){s,f,d}
127 #ifdef WIN32 // visual C++ doesn't support compound literals
128 #define BUTTONRADIOSTRUCT(s,f,d) radioFuncData(s,f,d)
129 #endif
130 
148 class Buttons : public LinkList<GtkWidget *> {
149 public:
150 
153  Buttons(void) {
154  gdk_colormap_new(gdk_visual_get_best(),1);
155  }
156 
162  void setAlignment(float xAlign, float yAlign){
163  gtk_button_set_alignment(GTK_BUTTON(current()), xAlign, yAlign);
164  gtk_widget_queue_draw(current());
165  }
166 
173  void getAlignment(float *xAlign, float *yAlign){
174  gtk_button_get_alignment(GTK_BUTTON(current()), xAlign, yAlign);
175  }
176 
177 // /** \brief Destructor
178 // */
179 // ~Buttons(void){
180 // for (int i=1; i<=getCount(); i++)
181 // if (g_object_is_floating(current()))
182 // delete remove();
183 // }
184 //
189  if (nf.func)
190  g_signal_connect_after(GTK_OBJECT((GtkButton*)current()), "released",GTK_SIGNAL_FUNC(nf.func), nf.data);
191  }
192 
198  if (nfOld.func)
199  g_signal_handlers_disconnect_by_func(GTK_OBJECT((GtkButton*)current()), (void *)(nfOld.func), nfOld.data);
200  if (nfNew.func)
201  g_signal_connect(GTK_OBJECT((GtkButton*)current()), "released",GTK_SIGNAL_FUNC(nfNew.func), nfNew.data);
202  }
203 
204 
210  if (nfOld.func){
211  g_signal_handlers_disconnect_by_func(GTK_OBJECT((GtkButton*)current()), (void *)(nfOld.func), nfOld.data);
212  }
213  }
214 
220  if (nf.str)
221  LinkList<GtkWidget *>::add(gtk_button_new_with_label(nf.str));
222  else
223  LinkList<GtkWidget *>::add(gtk_button_new());
224 
225  if (nf.func)
226  g_signal_connect(GTK_OBJECT((GtkButton*)current()), "released",GTK_SIGNAL_FUNC(nf.func), nf.data);
227  gtk_widget_show(current());
228  return *this;
229  }
230 
236 // GdkPixbuf * pixBuf=gdk_pixbuf_new_from_xpm_data(nf.pixGtk);
237  LinkList<GtkWidget *>::add(gtk_button_new());
238 // gtk_widget_set_size_request(current(), gdk_pixbuf_get_width(pixBuf), gdk_pixbuf_get_height(pixBuf)); // resize the button to match the pixmap
239 // cairo_t *cr=gdk_cairo_create(current()->window); // get a cairo context for rendering
240 // gdk_cairo_set_source_pixbuf(cr, pixBuf, current()->allocation.x, current()->allocation.y); // set the source to the pixbuf at the correct location
241 // cairo_paint(cr); // paint it to the cairo context
242 // cairo_destroy(cr); // destroy the context
243  g_signal_connect_after(current(), "expose-event", G_CALLBACK(exposePixmap), (gpointer)nf.pixGtk);
244 
245  if (nf.func)
246  gtk_signal_connect(GTK_OBJECT(current()), "released",GTK_SIGNAL_FUNC(nf.func), nf.data);
247  gtk_widget_show(current());
248  return *this;
249  }
250 
256  LinkList<GtkWidget *>::add(gtk_toggle_button_new_with_label(nf.str));
257  if (nf.func)
258  gtk_signal_connect(GTK_OBJECT((GtkButton*)current()), "released",GTK_SIGNAL_FUNC(nf.func), nf.data);
259  gtk_widget_show(current());
260  return *this;
261  }
262 
268  LinkList<GtkWidget *>::add(gtk_button_new());
269 
270  g_signal_connect_after(current(), "expose-event", G_CALLBACK(exposePixmap), (gpointer)pfdt.imageXPM);
271 
272  if (pfdt.func)
273  g_signal_connect(GTK_OBJECT(current()), "released",GTK_SIGNAL_FUNC(pfdt.func), pfdt.data);
274  gtk_widget_show(current());
275  return *this;
276  }
277 
285  LinkList<GtkWidget *>::add(gtk_button_new());
286  GtkWidget *arrow=gtk_arrow_new(af.whichArrow,af.whichShadow);
287  gtk_container_add (GTK_CONTAINER (current()), arrow);
288  gtk_widget_show(arrow);
289 
290  if (af.func)
291  gtk_signal_connect(GTK_OBJECT((GtkButton*)current()), "released",GTK_SIGNAL_FUNC(af.func), af.data);
292  gtk_widget_show_all(current());
293  return *this;
294  }
295 
302  if (!LinkList<GtkWidget *>::getCount()) // this is the first
303  LinkList<GtkWidget *>::add(gtk_radio_button_new_with_label(NULL,nf.str));
304  else
305  LinkList<GtkWidget *>::add(gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON (current()), nf.str));
306  if (nf.func)
307  gtk_signal_connect(GTK_OBJECT((GtkButton*)current()), "released",GTK_SIGNAL_FUNC(nf.func), nf.data);
308  gtk_widget_show(current());
309  return *this;
310  }
311 
320  static gboolean exposePixmap(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
321  GdkPixbuf *tipGDKPixBuf = gdk_pixbuf_new_from_xpm_data(static_cast<const char**>(data)); // get the pixbuf
322  int width = gdk_pixbuf_get_width(tipGDKPixBuf), height = gdk_pixbuf_get_height(tipGDKPixBuf);
323  if ((widget->allocation.width<width) | (widget->allocation.height<height))
324  gtk_widget_set_size_request(widget, width, height); // resize the button to match the pixmap
325  else {
326  cairo_t *cr=gdk_cairo_create(widget->window); // get a cairo context for rendering
327 
328  // use alignment to draw appropriately
329  float xAlign, yAlign;
330  gtk_button_get_alignment(GTK_BUTTON(widget), &xAlign, &yAlign);
331  int xOffset=(int)((float)(widget->allocation.width-width-1)*xAlign); if (xOffset<0) xOffset=0;
332  int yOffset=(int)((float)(widget->allocation.height-height-1)*yAlign); if (yOffset<0) yOffset=0;
333 
334  gdk_cairo_set_source_pixbuf(cr, tipGDKPixBuf, widget->allocation.x+xOffset, widget->allocation.y+yOffset); // set the source to the pixbuf at the correct location
335  cairo_paint(cr); // paint it to the cairo context
336  cairo_destroy(cr); // destroy the context
337  }
338  return FALSE;
339  }
340 
352  void setLabelsFont(PangoFontDescription *pangoFontDescription){
353  if (pangoFontDescription){
354  GtkWidget *child=gtk_bin_get_child(GTK_BIN(current()));
355  if (child)
356  gtk_widget_modify_font(child,pangoFontDescription);
357  }
358  }
359 
364  int findIndex(GtkWidget* widget){
365  int ret=0;
366  if (getCount()){
367  GtkWidget *c=current(); // remember our current location
368  grab(1); prev(); // we are at the last on the list
369  for (int i=1;i<=getCount();i++){
370  if (next()==widget){
371  ret=i;
372  break;
373  }
374  }
375  while (next()!=c) ; // return to the original button
376  }
377  //std::cout<<"Buttons::findIndex = "<<ret<<std::endl;
378  return ret;
379  }
380 
385  GtkWidget *findWidget(int index){
386  GtkWidget *retVal=NULL;
387  if (index<getCount() && index>0)
388  retVal=grab(index);
389  return retVal;
390  }
391 };
392 #endif //BUTTONS_H_
393