1 /*
2 * $Id: toolBar.c,v 1.13 2005/02/22 23:16:10 baum Exp $
3 *
4 * This file implements the toolbar widget
5 *
6 * Copyright (c) 2001 - 2005 Peter G. Baum http://www.dr-baum.net
7 *
8 * See the file "license.terms" for information on usage and redistribution
9 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10 *
11 */
12
13 /*
14 History:
15 2013-07: added commands options, commands
16 cget -style now works
17 2013-06: configure/cget -orientation now works
18 added flip -an expiremental feature
19 2013-05: added parent
20 2012-05: toolbar cget -data now works
21 2011-04: added -tooltips
22 nItems
23 re-wrote the code to use updated Toolbar API
24 2010-09: added button, toggle, menu & radio as synonyms for item,
25 checkItem, menuButton & radioItem objects. Began updating this
26 code to remove deprecated Gtk+ function calls.
27 2009-11: renamed static buttonFunc to non-static toolButtonFunc to
28 enable use in parsing glade files
29 2008-10: added command, class
30 2007-12: propose addition of MenuToolButton
31 http://www.gtk.org/api/2.6/gtk/GtkMenuToolButton.html
32 change of term 'item' to button
33 use command menuButton
34
35 2004-02: added -data for radio and check item
36 2003-09: changed -value to -onValue for radio item
37 added cget to radio and check item
38 12: switched from GnoclWidgetOptions to GnoclOption
39 05: updates for gtk 2.0
40 2002-02: percent subst. in command
41 added STD_OPTIONS
42 12: icon text qualified by "%#" or "%/"
43 2001-03: Begin of developement
44 */
45
46 /**
47 \page page_toolBar gnocl::toolBar
48 \htmlinclude toolBar.html
49 **/
50
51 #include "gnocl.h"
52 #include "gnoclparams.h"
53
54 /* static function declarations */
55 static int optOrientation ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret );
56 static int optVisibility ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret );
57 static int optStyle ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret );
58
59 /**
60 \brief Set the menu to display when menuButton downarrow clicked.
61 **/
gnoclOptMenu(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)62 static int gnoclOptMenu ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
63 {
64
65 GtkWidget *menu;
66
67 menu = gnoclGetWidgetFromName ( Tcl_GetString ( opt->val.obj ), interp );
68
69 gtk_menu_tool_button_set_menu ( GTK_MENU_TOOL_BUTTON ( obj ), menu );
70
71 return TCL_OK;
72 }
73
74 /* referenced in addButton */
75 static const int SpaceIdx = 0;
76 static const int WidgetIdx = 1;
77 static const int ItemIdx = 2;
78 static const int MenuButtonIdx = 3;
79 static const int CheckButtonIdx = 4;
80 static const int RadioItemIdx = 5;
81 static const int ToggleIdx = 6;
82 static const int ButtonIdx = 7;
83 static const int MenuIdx = 8;
84 static const int RadioIdx = 9;
85
86
87 /* */
88 static const int dataIdx = 0;
89 static const int orientationIdx = 1;
90 static const int tooolbarStyleIdx = 2;
91 static const int reliefIdx = 3;
92
93 /* toolBar options */
94 static GnoclOption toolBarOptions[] =
95 {
96 { "-data", GNOCL_OBJ, "", gnoclOptData }, /* 0 */
97 { "-orientation", GNOCL_STRING, NULL},
98 { "-style", GNOCL_OBJ, "toolbar-style", optStyle },
99 //{ "-relief", GNOCL_OBJ, "button-relief", gnoclOptButtonRelief },
100
101 /* widget specific options */
102 { "-iconSize", GNOCL_INT, "icon-size"},
103 { "-iconSizeSet", GNOCL_BOOL, "icon-size-set"},
104 { "-showArrow", GNOCL_BOOL, "show-arrow"},
105
106 { "-tooltips", GNOCL_BOOL, "tooltips" },
107
108 /* inherited container properties */
109 { "-borderWidth", GNOCL_OBJ, "border-width", gnoclOptPadding }, /* 6 */
110
111 /* general options */
112 { "-visible", GNOCL_BOOL, "visible" },
113 { "-sensitive", GNOCL_BOOL, "sensitive" },
114 { "-name", GNOCL_STRING, "name" },
115
116
117 /* drag and drop functionality */
118 /*
119 { "-dropTargets", GNOCL_LIST, "t", gnoclOptDnDTargets },
120 { "-dragTargets", GNOCL_LIST, "s", gnoclOptDnDTargets },
121 { "-onDropData", GNOCL_OBJ, "", gnoclOptOnDropData },
122 { "-onDragData", GNOCL_OBJ, "", gnoclOptOnDragData },
123 */
124 { NULL, 0, 0 }
125 };
126
127
128 /* menuButton options */
129 static const int menuButtonTextIdx = 0;
130 static const int menuButtonIconIdx = 1;
131 static const int menuButtonIconWidgetIdx = 2;
132 static const int menuButtonMenuIdx = 3;
133
134 //static const int menuButtonArrowClickedIdx = 4;
135 GnoclOption menuButtonOptions[] =
136 {
137 { "-text", GNOCL_OBJ, NULL },
138 { "-icon", GNOCL_OBJ, NULL},
139 { "-iconWidget", GNOCL_STRING, NULL },
140 { "-menu", GNOCL_OBJ, "", gnoclOptMenu },
141
142 // { "-onArrowClicked", GNOCL_STRING, NULL }, /* 4 */
143
144 /* object signals */
145 { "-onShowMenu", GNOCL_OBJ, "show-menu", gnoclOptCommand },
146 { "-onClicked", GNOCL_OBJ, "clicked", gnoclOptOnClicked },
147
148 /* inherited options */
149 { "-visible", GNOCL_BOOL, "visible" },
150 { "-sensitive", GNOCL_BOOL, "sensitive" },
151 { "-tooltip", GNOCL_OBJ, "", gnoclOptTooltip },
152 { "-arrowTooltip", GNOCL_OBJ, "", gnoclOptArrowTooltip },
153 { "-onShowHelp", GNOCL_OBJ, "", gnoclOptOnShowHelp },
154 { "-name", GNOCL_STRING, "name" },
155
156 { NULL, 0, 0 }
157 };
158
159
160 /* button options */
161 static const int buttonTextIdx = 0;
162 static const int buttonIconIdx = 1;
163 static const int buttonOnClickedIdx = 2;
164
165 GnoclOption buttonOptions[] =
166 {
167 /* gnocl specific options */
168 { "-text", GNOCL_OBJ, NULL },
169 { "-icon", GNOCL_OBJ, NULL },
170
171 {"-labelWidget", GNOCL_OBJ, "", gnoclOptToolButtonLabelWidget}, /* useful for bonobo text */
172 {"-iconWidget", GNOCL_OBJ, "", gnoclOptToolButtonIconWidget}, /* odd option, use with caution */
173
174 { "-important", GNOCL_BOOL, "is-important" },
175
176 /* widget properties */
177 /* signal handling */
178 /* general options */
179
180 { "-onClicked", GNOCL_OBJ, "clicked", gnoclOptCommand },
181 { "-visibility", GNOCL_OBJ, "", optVisibility },
182
183 { "-sensitive", GNOCL_BOOL, "sensitive" },
184 { "-tooltip", GNOCL_OBJ, "", gnoclOptTooltip },
185 { "-onShowHelp", GNOCL_OBJ, "", gnoclOptOnShowHelp },
186
187 { "-name", GNOCL_STRING, "name" },
188 { "-label", GNOCL_STRING, "label" },
189
190 /* menu button option */
191 { "-menu", GNOCL_OBJ, "", gnoclOptMenu },
192
193 { NULL, 0, 0 }
194 };
195
196 /* Checkbutton Options */
197 static const int checkTextIdx = 0;
198 static const int checkIconIdx = 1;
199 static const int checkOnToggledIdx = 2;
200 static const int checkOnValueIdx = 3;
201 static const int checkOffValueIdx = 4;
202 static const int checkVariableIdx = 5;
203 static const int checkActiveIdx = 6;
204 static const int checkValueIdx = 7;
205
206 static GnoclOption checkOptions[] =
207 {
208 { "-text", GNOCL_OBJ, NULL }, /* 0 */
209 { "-icon", GNOCL_OBJ, NULL }, /* 1 */
210 { "-onToggled", GNOCL_STRING, NULL }, /* 2 the order is important! */
211 { "-onValue", GNOCL_OBJ, NULL }, /* 3 */
212 { "-offValue", GNOCL_OBJ, NULL }, /* 4 */
213 { "-variable", GNOCL_STRING, NULL }, /* 5 */
214 { "-active", GNOCL_BOOL, NULL }, /* 6 */
215 { "-value", GNOCL_OBJ, NULL }, /* 7 */
216 { "-data", GNOCL_OBJ, "", gnoclOptData },
217 { "-name", GNOCL_STRING, "name" },
218 { "-onButtonPress", GNOCL_OBJ, "P", gnoclOptOnButton },
219 { "-onButtonRelease", GNOCL_OBJ, "R", gnoclOptOnButton },
220 { "-onShowHelp", GNOCL_OBJ, "", gnoclOptOnShowHelp },
221 { "-sensitive", GNOCL_BOOL, "sensitive" },
222 { "-tooltip", GNOCL_OBJ, "", gnoclOptTooltip },
223 { "-visible", GNOCL_BOOL, "visible" },
224 { NULL, 0, 0 }
225 };
226
227 /* radioButton options */
228 static const int radioTextIdx = 0;
229 static const int radioIconIdx = 1;
230 static const int radioOnToggledIdx = 2;
231 static const int radioOnValueIdx = 3;
232 static const int radioOffValueIdx = 4;
233 static const int radioVariableIdx = 5;
234 static const int radioActiveIdx = 6;
235 static const int radioValueIdx = 7;
236
237 static GnoclOption radioOptions[] =
238 {
239 /* gnocl specific options */
240 { "-text", GNOCL_OBJ, NULL }, /* 0 */
241 { "-icon", GNOCL_OBJ, NULL }, /* 1 */
242 { "-onToggled", GNOCL_STRING, NULL }, /* 2 the order is important! */
243 { "-onValue", GNOCL_OBJ, NULL }, /* 3 */
244 { "-offValue", GNOCL_OBJ, NULL }, /* 4 */
245 { "-variable", GNOCL_STRING, NULL }, /* 5 */
246 { "-active", GNOCL_BOOL, NULL }, /* 6 */
247 { "-value", GNOCL_OBJ, NULL }, /* 7 */
248 { "-data", GNOCL_OBJ, "", gnoclOptData },
249 { "-name", GNOCL_STRING, "name" },
250 { "-onButtonPress", GNOCL_OBJ, "P", gnoclOptOnButton },
251 { "-onButtonRelease", GNOCL_OBJ, "R", gnoclOptOnButton },
252 { "-onShowHelp", GNOCL_OBJ, "", gnoclOptOnShowHelp },
253 { "-sensitive", GNOCL_BOOL, "sensitive" },
254 { "-tooltip", GNOCL_OBJ, "", gnoclOptTooltip },
255 { "-visible", GNOCL_BOOL, "visible" },
256 { NULL, 0, 0 }
257 };
258
259
260
261
262 /* moved to gnocl.h */
263 /*
264 typedef struct
265 {
266 GtkWidget *item;
267 char *name;
268 char *onClicked;
269 Tcl_Interp *interp;
270 } ToolButtonParams;
271 */
272
273 /**
274 \brief
275 **/
optOrientation(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)276 static int optOrientation ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
277 {
278 const char *txt[] = { "horizontal", "vertical", NULL };
279 const int types[] = { GTK_ORIENTATION_HORIZONTAL,
280 GTK_ORIENTATION_VERTICAL
281 };
282
283 assert ( sizeof ( GTK_ORIENTATION_VERTICAL ) == sizeof ( int ) );
284
285 return gnoclOptGeneric ( interp, opt, obj, "orientation", txt, types, ret );
286 }
287
288
289 /**
290 \brief
291 **/
optVisibility(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)292 static int optVisibility ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
293 {
294 #ifdef DEBUG_TOOLBAR
295 g_print ( "GNOCL MESSAGE: ToolBar option \"-visibility\" not yet implemented.\n", __FUNCTION__ );
296 #endif
297
298 return TCL_OK;
299 }
300
301 /**
302 \brief
303 **/
optStyle(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)304 static int optStyle ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
305 {
306 const char *txt[] =
307 {
308 "icons", "text", "both", "horizontal",
309 NULL
310 };
311 const int types[] =
312 {
313 GTK_TOOLBAR_ICONS, GTK_TOOLBAR_TEXT, GTK_TOOLBAR_BOTH, GTK_TOOLBAR_BOTH_HORIZ
314 };
315
316 assert ( sizeof ( GTK_TOOLBAR_ICONS ) == sizeof ( int ) );
317
318 return gnoclOptGeneric ( interp, opt, obj, "style", txt, types, ret );
319 }
320
321
322 /**
323 \brief Modified version of getTextAndIcon to allow for new Toolbar API
324 \param
325 Tcl_Interp *interp pointer to Tcl interpreter
326 GtkToolbar *toolbar pointer to toolbar object that will receive new item
327 GnoclOption *txtOpt pointer to item label ??
328 GnoclOption *iconOpt pointer to item icon ??
329 char **txt handle on text pointer
330 GtkWidget **icon handle on image widget pointer
331 int *isUnderline pointer to int
332
333 \note Either -text or -icon must be set.
334
335 **/
getTextAndIcon(Tcl_Interp * interp,GtkToolbar * toolbar,GnoclOption * txtOpt,GnoclOption * iconOpt,char ** txt,GtkWidget ** item,int * isUnderline)336 int getTextAndIcon ( Tcl_Interp *interp, GtkToolbar *toolbar,
337 GnoclOption *txtOpt, GnoclOption *iconOpt,
338 char **txt, GtkWidget **item, int *isUnderline )
339 {
340 *item = NULL;
341 *txt = NULL;
342 *isUnderline = 0;
343
344 GtkImage *image;
345 gchar *name;
346 Tcl_Obj *icon;
347 GnoclStringType type;
348
349 /* error check, must have an icon defined! */
350 if ( iconOpt->status != GNOCL_STATUS_CHANGED && txtOpt->status != GNOCL_STATUS_CHANGED )
351 {
352 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( "GNOCL ERROR! Either -icon and -text must be set.", -1 ) );
353 return TCL_ERROR;
354 }
355
356
357 /* if only text set, must check for percent string */
358 if ( txtOpt->status == GNOCL_STATUS_CHANGED )
359 {
360 /* assume text == icon */
361 name = gnoclGetStringFromObj ( txtOpt->val.obj, NULL );
362 icon = txtOpt->val.obj;
363 type = gnoclGetStringType ( txtOpt->val.obj );
364
365 }
366
367 /* icon only */
368 if ( iconOpt->status == GNOCL_STATUS_CHANGED )
369 {
370 icon = iconOpt->val.obj;
371
372 if ( txtOpt->status != GNOCL_STATUS_CHANGED )
373 {
374 name = gnoclGetStringFromObj ( iconOpt->val.obj, NULL );
375 }
376
377 }
378
379 type = gnoclGetStringType ( icon );
380
381 /* stock item */
382 if ( type & GNOCL_STR_STOCK )
383 {
384 #ifdef DEBUG_TOOLBAR
385 g_print ( "STOCK\n" );
386 #endif
387 GtkStockItem stockItem;
388 GtkIconSize sz;
389
390 if ( gnoclGetStockItem ( icon, interp, &stockItem ) != TCL_OK )
391 {
392 return TCL_ERROR;
393 }
394
395 sz = gtk_toolbar_get_icon_size ( toolbar );
396 image = gtk_image_new_from_stock ( stockItem.stock_id, sz );
397
398 }
399
400 /* file */
401 else if ( type & GNOCL_STR_FILE )
402 {
403 #ifdef DEBUG_TOOLBAR
404 g_print ( "FILE\n" );
405 #endif
406 GError *error = NULL;
407 GdkPixbuf *pixbuf = NULL;
408
409 pixbuf = gdk_pixbuf_new_from_file ( icon, NULL );
410 image = gtk_image_new_from_pixbuf ( pixbuf );
411
412 }
413
414 /* buffer */
415 else if ( type & GNOCL_STR_BUFFER )
416 {
417 #ifdef DEBUG_TOOLBAR
418 g_print ( "BUFFER\n" );
419 #endif
420 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( icon, NULL );
421 GtkWidget *image = gtk_image_new_from_pixbuf ( pixbuf );
422
423 }
424
425 /* get the text string */
426 else
427 {
428 GtkIconSize sz;
429
430 sz = gtk_toolbar_get_icon_size ( toolbar );
431 GtkWidget *image = gtk_image_new_from_stock ( GTK_STOCK_MISSING_IMAGE, sz );
432
433 }
434
435 /*
436 uncertain what's happening here
437 this isUnderline was
438 */
439 if ( type & GNOCL_STR_UNDERLINE )
440 {
441 if ( txt == NULL )
442 {
443 *isUnderline = 0;
444 }
445
446 else
447 {
448 *isUnderline = 1;
449 }
450 }
451
452 gtk_widget_show ( image );
453
454 *item = image;
455
456 *txt = g_strdup ( name );
457
458 *isUnderline = 1;
459
460 return TCL_OK;
461 }
462
463
464 /**
465 \brief
466 **/
setUnderline(GtkWidget * item)467 static void setUnderline ( GtkWidget *item )
468 {
469
470 /* FIXME: is there really only one label? */
471 GtkWidget *label = gnoclFindChild ( item, GTK_TYPE_LABEL );
472
473 //assert ( label );
474 if ( label != NULL )
475 {
476 gtk_label_set_use_underline ( GTK_LABEL ( label ), 1 );
477 }
478 }
479
480
481
482
483
484 /**
485 \brief
486 **/
configure(Tcl_Interp * interp,GtkWidget * widget,GnoclOption options[])487 static int configure ( Tcl_Interp *interp, GtkWidget *widget, GnoclOption options[] )
488 {
489
490 if ( options[orientationIdx].status == GNOCL_STATUS_CHANGED )
491 {
492 if ( strcmp ( options[orientationIdx].val.str, "horizontal" ) == 0 )
493 {
494
495 gtk_orientable_set_orientation ( GTK_ORIENTABLE ( widget ), GTK_ORIENTATION_HORIZONTAL );
496
497 }
498
499 else if ( strcmp ( options[orientationIdx].val.str, "vertical" ) == 0 )
500 {
501
502 gtk_orientable_set_orientation ( GTK_ORIENTABLE ( widget ), GTK_ORIENTATION_VERTICAL );
503 }
504
505 else
506 {
507 return TCL_ERROR;
508 }
509
510
511 }
512
513 return TCL_OK;
514 }
515
516
517 /**
518 \brief Obtain current -option values.
519 **/
toolBarCget(Tcl_Interp * interp,GtkWidget * widget,GnoclOption options[],int idx)520 static int toolBarCget ( Tcl_Interp *interp, GtkWidget *widget, GnoclOption options[], int idx )
521 {
522
523
524 Tcl_Obj *obj = NULL;
525
526 if ( idx == dataIdx )
527 {
528 obj = Tcl_NewStringObj ( g_object_get_data ( widget, "gnocl::data" ), -1 );
529 }
530
531
532 if ( idx == reliefIdx )
533 {
534 switch ( gtk_toolbar_get_relief_style ( widget ) )
535 {
536 case GTK_RELIEF_NORMAL:
537 {
538 obj = Tcl_NewStringObj ( "normal", -1 );
539 } break;
540 case GTK_RELIEF_HALF:
541 {
542 obj = Tcl_NewStringObj ( "half", -1 );
543 } break;
544 case GTK_RELIEF_NONE:
545 {
546 obj = Tcl_NewStringObj ( "none", -1 );
547 } break;
548 default:
549 {
550 return TCL_ERROR;
551 }
552 }
553 }
554
555 if ( idx == orientationIdx )
556 {
557
558 switch ( gtk_orientable_get_orientation ( widget ) )
559 {
560 case GTK_ORIENTATION_HORIZONTAL:
561 {
562 obj = Tcl_NewStringObj ( "horizontal", -1 );
563 } break;
564 case GTK_ORIENTATION_VERTICAL:
565 {
566 obj = Tcl_NewStringObj ( "vertical", -1 );
567 } break;
568 default:
569 {
570 return TCL_ERROR;
571 }
572 }
573 }
574
575 if ( idx == tooolbarStyleIdx )
576 {
577 switch ( gtk_toolbar_get_style ( widget ) )
578 {
579 case GTK_TOOLBAR_ICONS:
580 {
581 obj = Tcl_NewStringObj ( "icons", -1 );
582 } break;
583 case GTK_TOOLBAR_TEXT:
584 {
585 obj = Tcl_NewStringObj ( "text", -1 );
586 } break;
587 case GTK_TOOLBAR_BOTH:
588 {
589 obj = Tcl_NewStringObj ( "both", -1 );
590 } break;
591 case GTK_TOOLBAR_BOTH_HORIZ:
592 {
593 obj = Tcl_NewStringObj ( "horizontal", -1 );
594 } break;
595 default:
596 {
597 return TCL_ERROR;
598 }
599 }
600 }
601
602
603 if ( obj != NULL )
604 {
605 Tcl_SetObjResult ( interp, obj );
606 return TCL_OK;
607 }
608
609 return gnoclCgetNotImplemented ( interp, options + idx );
610 }
611
612
613
614 /**
615 \brief
616 **/
cgetText(GtkWidget * item)617 static Tcl_Obj *cgetText ( GtkWidget *item )
618 {
619
620 /* FIXME: is there really only one label? */
621 GtkWidget *label = gnoclFindChild ( item, GTK_TYPE_LABEL );
622
623 if ( label != NULL )
624 {
625 const char *txt = gtk_label_get_label ( GTK_LABEL ( label ) );
626
627 if ( txt != NULL )
628 {
629 Tcl_Obj *obj = Tcl_NewStringObj ( txt, -1 );
630 /* FIXME: that does not work
631 if( gtk_button_get_use_stock( GTK_BUTTON( item ) ) )
632 {
633 Tcl_Obj *old = obj;
634 obj = Tcl_NewStringObj( "%#", 2 );
635 Tcl_AppendObjToObj( obj, old );
636 }
637 else
638 */
639
640 if ( gtk_label_get_use_underline ( GTK_LABEL ( label ) ) )
641 {
642 Tcl_Obj *old = obj;
643 obj = Tcl_NewStringObj ( "%_", 2 );
644 Tcl_AppendObjToObj ( obj, old );
645 }
646
647 return obj;
648 }
649 }
650
651 return Tcl_NewStringObj ( "", 0 );;
652 }
653
654 /**
655 \brief
656 **/
657 /*
658 -------------- check functions ----------------------------
659 */
checkDestroyFunc(GtkWidget * widget,gpointer data)660 static void checkDestroyFunc ( GtkWidget *widget, gpointer data )
661 {
662 GnoclToolBarCheckParams *para = ( GnoclToolBarCheckParams * ) data;
663
664 gnoclAttachVariable ( NULL, ¶->variable,
665 "toggled", G_OBJECT ( para->item ),
666 G_CALLBACK ( gnoclCheckToggledFunc ),
667 para->interp, gnoclCheckTraceFunc, para );
668
669 gnoclForgetWidgetFromName ( para->name );
670 Tcl_DeleteCommand ( para->interp, para->name );
671 g_free ( para->name );
672
673 Tcl_DecrRefCount ( para->onValue );
674 Tcl_DecrRefCount ( para->offValue );
675 g_free ( para );
676 }
677
678 /**
679 \brief
680 **/
checkConfigure(Tcl_Interp * interp,GnoclToolBarCheckParams * para,GnoclOption options[])681 static int checkConfigure ( Tcl_Interp *interp, GnoclToolBarCheckParams *para,
682 GnoclOption options[] )
683 {
684 if ( options[checkOnValueIdx].status == GNOCL_STATUS_CHANGED )
685 {
686 GNOCL_MOVE_OBJ ( options[checkOnValueIdx].val.obj, para->onValue );
687 }
688
689 if ( options[checkOffValueIdx].status == GNOCL_STATUS_CHANGED )
690 {
691 GNOCL_MOVE_OBJ ( options[checkOffValueIdx].val.obj, para->offValue );
692 }
693
694 if ( options[checkOnToggledIdx].status == GNOCL_STATUS_CHANGED )
695 {
696 GNOCL_MOVE_STRING ( options[checkOnToggledIdx].val.str, para->onToggled );
697 }
698
699 gnoclAttachVariable ( &options[checkVariableIdx], ¶->variable,
700 "toggled", G_OBJECT ( para->item ),
701 G_CALLBACK ( gnoclCheckToggledFunc ), para->interp,
702 gnoclCheckTraceFunc, para );
703
704 if ( gnoclCheckSetActive ( para, &options[checkActiveIdx] ) == 0
705 && ( options[checkVariableIdx].status == GNOCL_STATUS_CHANGED
706 || options[checkOnValueIdx].status == GNOCL_STATUS_CHANGED
707 || options[checkOffValueIdx].status == GNOCL_STATUS_CHANGED ) )
708 {
709 gnoclCheckVariableValueChanged ( para );
710 }
711
712 if ( options[checkValueIdx].status == GNOCL_STATUS_CHANGED )
713 {
714 if ( gnoclCheckSetValue ( para, options[checkValueIdx].val.obj ) != TCL_OK )
715 return TCL_ERROR;
716 }
717
718 return TCL_OK;
719 }
720
721 /**
722 \brief
723 **/
checkCget(Tcl_Interp * interp,GnoclToolBarCheckParams * para,GnoclOption options[],int idx)724 static int checkCget ( Tcl_Interp *interp, GnoclToolBarCheckParams *para, GnoclOption options[], int idx )
725 {
726
727
728 Tcl_Obj *obj = NULL;
729
730 if ( idx == checkTextIdx )
731 {
732 obj = cgetText ( para->item );
733 }
734
735 else if ( idx == checkIconIdx )
736 {
737 ; /* TODO */
738 }
739
740 else if ( idx == checkOnToggledIdx )
741 {
742 obj = Tcl_NewStringObj ( para->onToggled ? para->onToggled : "", -1 );
743 }
744
745 else if ( idx == checkOnValueIdx )
746 {
747 obj = para->onValue;
748 }
749
750 else if ( idx == checkOffValueIdx )
751 {
752 obj = para->offValue;
753 }
754
755 else if ( idx == checkVariableIdx )
756 {
757 obj = Tcl_NewStringObj ( para->variable, -1 );
758 }
759
760 else if ( idx == checkActiveIdx )
761 {
762 gboolean on;
763 g_object_get ( G_OBJECT ( para->item ), "active", &on, NULL );
764 obj = Tcl_NewBooleanObj ( on );
765 }
766
767 else if ( idx == checkValueIdx )
768 {
769 gboolean on;
770 g_object_get ( G_OBJECT ( para->item ), "active", &on, NULL );
771 obj = on ? para->onValue : para->offValue;
772 }
773
774 if ( obj != NULL )
775 {
776 Tcl_SetObjResult ( interp, obj );
777 return TCL_OK;
778 }
779
780 return gnoclCgetNotImplemented ( interp, options + idx );
781 }
782
783 /**
784 \brief
785 **/
checktoolButtonFunc(ClientData data,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])786 static int checktoolButtonFunc ( ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[] )
787 {
788 static const char *cmds[] = { "delete", "configure", "cget", "onToggled", "class", NULL };
789 enum cmdIdx { DeleteIdx, ConfigureIdx, CgetIdx, OnToggledIdx, ClassIdx };
790 GnoclToolBarCheckParams *para = ( GnoclToolBarCheckParams * ) data;
791 int idx;
792
793 if ( objc < 2 )
794 {
795 Tcl_WrongNumArgs ( interp, 1, objv, "command" );
796 return TCL_ERROR;
797 }
798
799 if ( Tcl_GetIndexFromObj ( interp, objv[1], cmds, "command", TCL_EXACT, &idx ) != TCL_OK )
800 {
801 return TCL_ERROR;
802 }
803
804 switch ( idx )
805 {
806 case ClassIdx:
807 {
808 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( "toolBarCheckButton", -1 ) );
809 }
810 break;
811 case DeleteIdx:
812 {
813 return gnoclDelete ( interp, para->item, objc, objv );
814 }
815 case ConfigureIdx:
816 {
817 int ret = TCL_ERROR;
818
819 if ( gnoclParseAndSetOptions ( interp, objc - 1, objv + 1,
820 checkOptions, G_OBJECT ( para->item ) ) == TCL_OK )
821 {
822 int k;
823
824 for ( k = 0; k < checkOnToggledIdx; ++k )
825 {
826 if ( checkOptions[k].status == GNOCL_STATUS_CHANGED )
827 {
828 Tcl_AppendResult ( interp, "Option \"",
829 checkOptions[k].optName,
830 "\" cannot be set after widget creation.",
831 NULL );
832 gnoclClearOptions ( checkOptions );
833 return TCL_ERROR;
834 }
835 }
836
837 ret = checkConfigure ( interp, para, checkOptions );
838 }
839
840 gnoclClearOptions ( checkOptions );
841
842 return ret;
843 }
844
845 break;
846
847 case CgetIdx:
848 {
849 int idx;
850
851 switch ( gnoclCget ( interp, objc, objv, G_OBJECT ( para->item ),
852 checkOptions, &idx ) )
853 {
854 case GNOCL_CGET_ERROR:
855 return TCL_ERROR;
856 case GNOCL_CGET_HANDLED:
857 return TCL_OK;
858 case GNOCL_CGET_NOTHANDLED:
859 return checkCget ( interp, para, checkOptions, idx );
860 }
861 }
862
863 case OnToggledIdx:
864 return gnoclCheckOnToggled ( interp, objc, objv, para );
865 }
866
867 return TCL_OK;
868 }
869
870 /**
871 \brief
872 **/
873 /*
874 -------------- radio functions ----------------------------
875 */
radioConfigure(Tcl_Interp * interp,GnoclRadioParams * para,GnoclOption options[])876 static int radioConfigure ( Tcl_Interp *interp, GnoclRadioParams *para, GnoclOption options[] )
877 {
878 /* set an initial value for the radio button group */
879 if ( gnoclRadioSetValueActive ( para, &options[radioOnValueIdx],
880 &options[radioActiveIdx] ) != TCL_OK )
881 {
882 return TCL_ERROR;
883 }
884
885 /* when toggled */
886 if ( options[radioOnToggledIdx].status == GNOCL_STATUS_CHANGED )
887 {
888 GNOCL_MOVE_STRING ( options[radioOnToggledIdx].val.str, para->onToggled );
889 }
890
891 if ( options[radioValueIdx].status == GNOCL_STATUS_CHANGED )
892 {
893 if ( gnoclRadioSetValue ( para, options[radioValueIdx].val.obj ) != TCL_OK )
894 {
895 return TCL_ERROR;
896 }
897 }
898
899 gnoclAttachVariable (
900 &options[radioVariableIdx], ¶->group->variable,
901 "toggled", G_OBJECT ( para->widget ),
902 G_CALLBACK ( gnoclRadioToggledFunc ), para->group->interp,
903 gnoclRadioTraceFunc, para );
904
905
906 /*
907 if ( gnoclRadioSetActive ( para, &options[radioActiveIdx] ) == 0
908 && ( options[radioVariableIdx].status == GNOCL_STATUS_CHANGED
909 || options[radioOnValueIdx].status == GNOCL_STATUS_CHANGED
910 || options[radioOffValueIdx].status == GNOCL_STATUS_CHANGED ) )
911 {
912 gnoclRadioVariableValueChanged ( para );
913 }
914 */
915
916 if ( options[radioValueIdx].status == GNOCL_STATUS_CHANGED )
917 {
918 if ( gnoclRadioSetValue ( para, options[radioValueIdx].val.obj ) != TCL_OK )
919 {
920 return TCL_ERROR;
921 }
922 }
923
924
925
926 return TCL_OK;
927 }
928
929 /**
930 \brief
931 **/
radioCget(Tcl_Interp * interp,GnoclRadioParams * para,GnoclOption options[],int idx)932 static int radioCget ( Tcl_Interp *interp, GnoclRadioParams *para, GnoclOption options[], int idx )
933 {
934
935
936 Tcl_Obj *obj = NULL;
937
938 if ( idx == radioTextIdx )
939 {
940 obj = cgetText ( para->widget );
941 }
942
943 else if ( idx == radioIconIdx )
944 {
945 ; /* TODO */
946 }
947
948 else if ( idx == radioOnToggledIdx )
949 {
950 obj = Tcl_NewStringObj ( para->onToggled ? para->onToggled : "", -1 );
951 }
952
953 else if ( idx == radioOnValueIdx )
954 {
955 GnoclRadioParams *p = gnoclRadioGetActivePara ( para->group );
956 obj = p->onValue;
957 }
958
959 else if ( idx == radioVariableIdx )
960 {
961 obj = Tcl_NewStringObj ( para->group->variable, -1 );
962 }
963
964 else if ( idx == radioActiveIdx )
965 {
966 gboolean on;
967 g_object_get ( G_OBJECT ( para->widget ), "active", &on, NULL );
968 obj = Tcl_NewBooleanObj ( on );
969 }
970
971 else if ( idx == radioValueIdx )
972 {
973 obj = gnoclRadioGetValue ( para );
974 }
975
976 if ( obj != NULL )
977 {
978 Tcl_SetObjResult ( interp, obj );
979 return TCL_OK;
980 }
981
982 return gnoclCgetNotImplemented ( interp, options + idx );
983 }
984
985 /**
986 \brief
987 **/
radiotoolButtonFunc(ClientData data,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])988 static int radiotoolButtonFunc ( ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[] )
989 {
990 static const char *cmds[] = { "delete", "configure", "cget", "onToggled", "class", NULL };
991 enum cmdIdx { DeleteIdx, ConfigureIdx, CgetIdx, OnToggledIdx, ClassIdx};
992 GnoclRadioParams *para = ( GnoclRadioParams * ) data;
993 int idx;
994
995 if ( objc < 2 )
996 {
997 Tcl_WrongNumArgs ( interp, 1, objv, "command" );
998 return TCL_ERROR;
999 }
1000
1001 if ( Tcl_GetIndexFromObj ( interp, objv[1], cmds, "command",
1002 TCL_EXACT, &idx ) != TCL_OK )
1003 return TCL_ERROR;
1004
1005 switch ( idx )
1006 {
1007 case ClassIdx:
1008 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( "toolBarRadioButton", -1 ) );
1009 break;
1010 case DeleteIdx:
1011 return gnoclDelete ( interp, para->widget, objc, objv );
1012
1013 case ConfigureIdx:
1014 {
1015 int ret = TCL_ERROR;
1016
1017 if ( gnoclParseAndSetOptions ( interp, objc - 1, objv + 1,
1018 radioOptions, G_OBJECT ( para->widget ) ) == TCL_OK )
1019 {
1020 int k;
1021
1022 for ( k = 0; k < radioActiveIdx; ++k )
1023 {
1024 if ( radioOptions[k].status == GNOCL_STATUS_CHANGED )
1025 {
1026 Tcl_AppendResult ( interp, "Option \"",
1027 radioOptions[k].optName,
1028 "\" cannot be set after widget creation.",
1029 NULL );
1030 gnoclClearOptions ( radioOptions );
1031 return TCL_ERROR;
1032 }
1033 }
1034
1035 ret = radioConfigure ( interp, para, radioOptions );
1036 }
1037
1038 gnoclClearOptions ( radioOptions );
1039
1040 return ret;
1041 }
1042
1043 break;
1044
1045 case CgetIdx:
1046 {
1047 int idx;
1048
1049 switch ( gnoclCget ( interp, objc, objv, G_OBJECT ( para->widget ), radioOptions, &idx ) )
1050 {
1051 case GNOCL_CGET_ERROR:
1052 return TCL_ERROR;
1053 case GNOCL_CGET_HANDLED:
1054 return TCL_OK;
1055 case GNOCL_CGET_NOTHANDLED:
1056 return radioCget ( interp, para, radioOptions, idx );
1057 }
1058 }
1059
1060 case OnToggledIdx:
1061 return gnoclRadioOnToggled ( interp, objc, objv, para );
1062 }
1063
1064 return TCL_OK;
1065 }
1066
1067 /**
1068 \brief Description yet to be added.
1069 \author Peter G Baum
1070 */
1071
1072 /*
1073 -------------- button functions ----------------------------
1074 */
1075
1076 /**
1077 \brief
1078 **/
menuButtonDoCommand(ToolButtonMenuParams * para,int background)1079 static int menuButtonDoCommand ( ToolButtonMenuParams *para, int background )
1080 {
1081 #ifdef DEBUG_TOOLBAR
1082 printf ( "%s\n", __FUNCTION__ );
1083 #endif
1084
1085 if ( para->onClicked )
1086 {
1087 GnoclPercSubst ps[] =
1088 {
1089 { 'w', GNOCL_STRING }, /* widget */
1090 { 0 }
1091 };
1092
1093
1094 ps[0].val.str = para->name;
1095
1096 return gnoclPercentSubstAndEval ( para->interp, ps, para->onClicked, background );
1097 }
1098
1099 return TCL_OK;
1100 }
1101
1102
1103 /**
1104 \brief
1105 **/
buttonDoCommand(ToolButtonParams * para,int background)1106 static int buttonDoCommand ( ToolButtonParams *para, int background )
1107 {
1108 #ifdef DEBUG_TOOLBAR
1109 printf ( "%s\n", __FUNCTION__ );
1110 #endif
1111
1112 if ( para->onClicked )
1113 {
1114 GnoclPercSubst ps[] =
1115 {
1116 { 'w', GNOCL_STRING }, /* widget */
1117 { 0 }
1118 };
1119
1120
1121 ps[0].val.str = para->name;
1122
1123 return gnoclPercentSubstAndEval ( para->interp, ps, para->onClicked, background );
1124 }
1125
1126 return TCL_OK;
1127 }
1128
1129
1130 /**
1131 \brief
1132 **/
radioButtonCallback(GtkWidget * widget,gpointer data)1133 static void radioButtonCallback ( GtkWidget *widget, gpointer data )
1134 {
1135 #ifdef DEBUG_TOOLBAR
1136 printf ( "%s\n", __FUNCTION__ );
1137 #endif
1138 ToolButtonParams *para = ( ToolButtonParams * ) data;
1139
1140
1141 //buttonDoCommand ( para, 1 );
1142 }
1143
1144 /**
1145 \brief
1146 **/
buttonCallback(GtkWidget * widget,gpointer data)1147 static void buttonCallback ( GtkWidget *widget, gpointer data )
1148 {
1149 #ifdef DEBUG_TOOLBAR
1150 printf ( "%s\n", __FUNCTION__ );
1151 #endif
1152 ToolButtonParams *para = ( ToolButtonParams * ) data;
1153
1154
1155 //buttonDoCommand ( para, 1 );
1156 }
1157
1158 /**
1159 \brief
1160 **/
menuButtonCallback(GtkWidget * widget,gpointer data)1161 static void menuButtonCallback ( GtkWidget *widget, gpointer data )
1162 {
1163 #ifdef DEBUG_TOOLBAR
1164 printf ( "%s\n", __FUNCTION__ );
1165 #endif
1166 ToolButtonMenuParams *para = ( ToolButtonMenuParams * ) data;
1167
1168
1169 menuButtonDoCommand ( para, 1 );
1170
1171 }
1172
1173
1174 /**
1175 \brief
1176 **/
buttonDestroyFunc(GtkWidget * widget,gpointer data)1177 static void buttonDestroyFunc ( GtkWidget *widget, gpointer data )
1178 {
1179 ToolButtonParams *p = ( ToolButtonParams * ) data;
1180
1181 gnoclForgetWidgetFromName ( p->name );
1182 Tcl_DeleteCommand ( p->interp, p->name );
1183
1184 g_free ( p->onClicked );
1185 g_free ( p->name );
1186 g_free ( p );
1187 }
1188
1189 /**
1190 \brief Configure the menubutton item object
1191 \note There are two ways of creating this object using either:
1192 1) a pre-exisiting widget, or
1193 2) a toolbar button with a stock item. (default)
1194 This is a 'one-time' choice has to be made during widget creation.
1195 Problems redisplaying toolitem widget icon after changing.
1196 Resolved using call to gtk_widget_show (icon) after changing the icon.
1197 **/
menuButtonConfigure(Tcl_Interp * interp,ToolButtonMenuParams * para,GnoclOption options[])1198 static int menuButtonConfigure ( Tcl_Interp *interp, ToolButtonMenuParams *para, GnoclOption options[] )
1199 {
1200
1201 #ifdef DEBUG_TOOLBAR
1202 g_print ( "menuButtonConfigure\n" );
1203 #endif
1204
1205 gchar *label = NULL;
1206 GtkWidget *icon_widget = NULL;
1207
1208
1209 /* step 1) create the menu button itself one of two methods: */
1210
1211 /* method 1) use a predefined button for the menu button itself */
1212
1213
1214 if ( options[menuButtonTextIdx].status == GNOCL_STATUS_CHANGED )
1215 {
1216 label = options[menuButtonTextIdx].val.str;
1217 }
1218
1219
1220 if ( options[menuButtonIconWidgetIdx].status == GNOCL_STATUS_CHANGED )
1221 {
1222 /* change the button clicked option */
1223
1224 icon_widget = gnoclGetWidgetFromName ( options[menuButtonIconWidgetIdx].val.str, interp );
1225
1226 }
1227
1228 else
1229 {
1230 // para->item = gtk_menu_tool_button_new ( NULL, NULL );
1231 para->item = gtk_menu_tool_button_new_from_stock ( GTK_STOCK_ABOUT );
1232
1233 }
1234
1235 para->item = gtk_menu_tool_button_new ( icon_widget, label );
1236
1237
1238 /* method 2) create a custom widget */
1239
1240 if ( options[menuButtonIconIdx].status == GNOCL_STATUS_CHANGED )
1241 {
1242
1243 para->item = gtk_menu_tool_button_new_from_stock ( GTK_STOCK_COPY );
1244 }
1245
1246 /*
1247 if ( options[menuButtonArrowClickedIdx].status == GNOCL_STATUS_CHANGED )
1248 {
1249 GNOCL_MOVE_STRING ( options[menuButtonArrowClickedIdx].val.str, para->onClicked );
1250 }
1251 */
1252
1253 /* step 2) attach a menu to this button */
1254 /*
1255 if ( options[menuButtonMenuIdx].status == GNOCL_STATUS_CHANGED )
1256 {
1257 #ifdef DEBUG_TOOLBAR
1258 g_print ( "menu = %s\n", options[menuButtonMenuIdx].val.str );
1259 #endif
1260 para->menu = gnoclGetWidgetFromName ( options[menuButtonMenuIdx].val.str, interp );
1261
1262 gtk_menu_tool_button_set_menu ( para->item, para->menu );
1263 }
1264 */
1265 return TCL_OK;
1266 }
1267
1268
1269 /**
1270 \brief
1271 **/
buttonConfigure(Tcl_Interp * interp,ToolButtonParams * para,GnoclOption options[])1272 static int buttonConfigure ( Tcl_Interp *interp, ToolButtonParams *para, GnoclOption options[] )
1273 {
1274 if ( options[buttonOnClickedIdx].status == GNOCL_STATUS_CHANGED )
1275 {
1276 GNOCL_MOVE_STRING ( options[buttonOnClickedIdx].val.str, para->onClicked );
1277 }
1278
1279 return TCL_OK;
1280 }
1281
1282 /**
1283 \brief
1284 **/
toolButtonFunc(ClientData data,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])1285 int toolButtonFunc ( ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[] )
1286 {
1287 static const char *cmds[] = { "delete", "configure", "onClicked", "class", "cget", NULL };
1288 enum cmdIdx { DeleteIdx, ConfigureIdx, OnClickedIdx, ClassIdx, CgetIdx };
1289 ToolButtonParams *para = ( ToolButtonParams * ) data;
1290 int idx;
1291
1292 if ( objc < 2 )
1293 {
1294 Tcl_WrongNumArgs ( interp, 1, objv, "command" );
1295 return TCL_ERROR;
1296 }
1297
1298 if ( Tcl_GetIndexFromObj ( interp, objv[1], cmds, "command",
1299 TCL_EXACT, &idx ) != TCL_OK )
1300 return TCL_ERROR;
1301
1302 switch ( idx )
1303 {
1304 case CgetIdx:
1305 {
1306
1307 }
1308 case ClassIdx:
1309 {
1310 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( "toolBarButton", -1 ) );
1311 break;
1312 }
1313 case DeleteIdx:
1314 {
1315 return gnoclDelete ( interp, GTK_WIDGET ( para->item ), objc, objv );
1316 }
1317 case ConfigureIdx:
1318 {
1319 #ifdef DEBUG_TOOLBAR
1320 printf ( "toolButtonFunc/configure\n" );
1321 #endif
1322 int ret = TCL_ERROR;
1323
1324 if ( gnoclParseAndSetOptions ( interp, objc - 1, objv + 1,
1325 buttonOptions, G_OBJECT ( para->item ) ) == TCL_OK )
1326 {
1327 ret = buttonConfigure ( interp, para, buttonOptions );
1328 }
1329
1330 gnoclClearOptions ( buttonOptions );
1331
1332 return ret;
1333 }
1334
1335 break;
1336 case OnClickedIdx:
1337 {
1338 if ( objc != 2 )
1339 {
1340 Tcl_WrongNumArgs ( interp, 2, objv, NULL );
1341 return TCL_ERROR;
1342 }
1343
1344 return buttonDoCommand ( para, 0 );
1345 }
1346 }
1347
1348 return TCL_OK;
1349 }
1350
1351 /*
1352 int gnoclRegisterWidget ( Tcl_Interp *interp, GtkWidget *widget, Tcl_ObjCmdProc *proc )
1353 {
1354 const char *name = gnoclGetAutoWidgetId();
1355 gnoclMemNameAndWidget ( name, widget );
1356
1357 g_signal_connect_after ( G_OBJECT ( widget ), "destroy", G_CALLBACK ( simpleDestroyFunc ), interp );
1358
1359 if ( proc != NULL )
1360 {
1361 Tcl_CreateObjCommand ( interp, ( char * ) name, proc, widget, NULL );
1362 }
1363
1364 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( name, -1 ) );
1365
1366 return TCL_OK;
1367 }
1368 */
1369
1370
1371
1372 /**
1373 \brief
1374 **/
addCheckButton(GtkToolbar * toolbar,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[],int atEnd)1375 static int addCheckButton ( GtkToolbar *toolbar, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[], int atEnd )
1376 {
1377
1378 int ret;
1379 GnoclToolBarCheckParams *para = NULL;
1380 char *txt = NULL;
1381 int isUnderline;
1382 GtkWidget *icon;
1383
1384 if ( gnoclParseOptions ( interp, objc - 2, objv + 2, checkOptions ) != TCL_OK )
1385 {
1386 gnoclClearOptions ( checkOptions );
1387 return TCL_ERROR;
1388 }
1389
1390
1391 if ( getTextAndIcon ( interp, toolbar,
1392 checkOptions + checkTextIdx, checkOptions + checkIconIdx,
1393 &txt, &icon, &isUnderline ) != TCL_OK )
1394 {
1395 return TCL_ERROR;
1396 }
1397
1398 para = g_new ( GnoclToolBarCheckParams, 1 );
1399
1400 para->onToggled = NULL;
1401
1402 para->interp = interp;
1403
1404 para->name = gnoclGetAutoWidgetId();
1405
1406 para->variable = NULL;
1407
1408 para->onValue = Tcl_NewIntObj ( 1 );
1409
1410 Tcl_IncrRefCount ( para->onValue );
1411
1412 para->offValue = Tcl_NewIntObj ( 0 );
1413
1414 Tcl_IncrRefCount ( para->offValue );
1415
1416 para->inSetVar = 0;
1417
1418 /* this is the requirement after Gtk+ 2.4 */
1419 //para->item = gtk_tool_button_new_from_stock ( GTK_STOCK_COPY );
1420 //para->widget = gtk_toggle_tool_button_new_from_stock ( GTK_STOCK_COPY );
1421
1422 //GtkToggleAction * gtk_toggle_action_new (const gchar *name, const gchar *label, const gchar *tooltip, const gchar *stock_id);
1423
1424 /* create base object then add icon and label widgets */
1425 para->item = gtk_toggle_tool_button_new ();
1426 gtk_tool_button_set_icon_widget ( para->item, icon );
1427 gtk_widget_show ( icon );
1428 gtk_tool_button_set_label ( para->item, txt );
1429
1430 //gtk_tool_button_set_label_widget (para->item, txt);
1431 //g_signal_connect ( para->item , "toggled", G_CALLBACK ( gnoclCheckToggledFunc ), para );
1432
1433 gtk_toolbar_insert ( GTK_TOOLBAR ( toolbar ), para->item, -1 );
1434 gtk_widget_show ( GTK_WIDGET ( para->item ) );
1435
1436 if ( isUnderline )
1437 {
1438 setUnderline ( para->item );
1439 }
1440
1441 ret = gnoclSetOptions ( interp, checkOptions, G_OBJECT ( para->item ), -1 );
1442
1443 if ( ret == TCL_OK )
1444 {
1445 ret = checkConfigure ( interp, para, checkOptions );
1446 }
1447
1448 if ( ret != TCL_OK )
1449 {
1450 g_free ( para );
1451 }
1452
1453 else
1454 {
1455 g_signal_connect_after ( G_OBJECT ( para->item ), "destroy", G_CALLBACK ( checkDestroyFunc ), para );
1456
1457 gnoclMemNameAndWidget ( para->name, para->item );
1458
1459 Tcl_CreateObjCommand ( interp, para->name, checktoolButtonFunc, para, NULL );
1460 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( para->name, -1 ) );
1461 }
1462
1463 gnoclClearOptions ( checkOptions );
1464
1465 return ret;
1466 }
1467
1468 /**
1469 \brief
1470 \note Using new Toolbar API. Gtk+ 2.16
1471 **/
addButton(gchar * type,GtkToolbar * toolbar,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[],int pos)1472 static int addButton ( gchar *type, GtkToolbar *toolbar, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[], int pos )
1473 {
1474 #ifdef DEBUG_TOOLBAR
1475 listParameters ( objc, objv, __FUNCTION__ );
1476 #endif
1477
1478 int ret;
1479 ToolButtonParams *para = NULL;
1480 char *txt = NULL;
1481 int isUnderline;
1482 GtkWidget *icon; /* image created by getTextAndIcon to hold icon graphic*/
1483
1484 if ( gnoclParseOptions ( interp, objc - 2, objv + 2, buttonOptions ) != TCL_OK )
1485 {
1486 gnoclClearOptions ( buttonOptions );
1487 return TCL_ERROR;
1488 }
1489
1490 gint i;
1491
1492 /* add label and icon widget */
1493 if ( getTextAndIcon (
1494 interp, toolbar,
1495 buttonOptions + buttonTextIdx,
1496 buttonOptions + buttonIconIdx,
1497 &txt, &icon, &isUnderline ) != TCL_OK )
1498 {
1499 return TCL_ERROR;
1500 }
1501
1502 para = g_new ( ToolButtonParams, 1 );
1503
1504 para->onClicked = NULL;
1505
1506 para->interp = interp;
1507
1508 para->name = gnoclGetAutoWidgetId();
1509
1510 para->item = gtk_tool_button_new ( icon, txt );
1511
1512 //g_signal_connect ( para->item , "clicked", G_CALLBACK ( buttonCallback ), para );
1513
1514 gtk_toolbar_insert ( GTK_TOOLBAR ( toolbar ), para->item, -1 );
1515
1516 gtk_widget_show ( GTK_WIDGET ( para->item ) );
1517
1518 if ( isUnderline )
1519 {
1520 setUnderline ( para->item );
1521 }
1522
1523 ret = gnoclSetOptions ( interp, buttonOptions, G_OBJECT ( para->item ), -1 );
1524
1525 if ( ret == TCL_OK )
1526 {
1527 ret = buttonConfigure ( interp, para, buttonOptions );
1528 }
1529
1530 if ( ret != TCL_OK )
1531 {
1532 g_free ( para );
1533 }
1534
1535 else
1536 {
1537 g_signal_connect_after ( G_OBJECT ( para->item ), "destroy", G_CALLBACK ( buttonDestroyFunc ), para );
1538
1539 gnoclMemNameAndWidget ( para->name, GTK_WIDGET ( para->item ) );
1540
1541 Tcl_CreateObjCommand ( interp, para->name, toolButtonFunc, para, NULL );
1542 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( para->name, -1 ) );
1543 }
1544
1545 gnoclClearOptions ( buttonOptions );
1546
1547 return ret;
1548 }
1549
1550
1551
1552 /**
1553 \brief
1554 **/
addRadioButton(GtkToolbar * toolbar,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[],int atEnd)1555 static int addRadioButton ( GtkToolbar *toolbar, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[], int atEnd )
1556 {
1557 int ret;
1558 GnoclRadioParams *para = NULL;
1559 char *txt = NULL;
1560 int isUnderline;
1561 GtkWidget *icon;
1562 GtkWidget *firstWidget = NULL;
1563
1564 GSList* list = NULL;
1565
1566
1567
1568 /* check options */
1569 if ( gnoclParseOptions ( interp, objc - 2, objv + 2, radioOptions ) != TCL_OK )
1570 {
1571 gnoclClearOptions ( radioOptions );
1572 return TCL_ERROR;
1573 }
1574
1575
1576
1577 /* Confirm that the mandatory -value or -variable options have been set. */
1578 if ( radioOptions[radioOnValueIdx].status != GNOCL_STATUS_CHANGED ||
1579 radioOptions[radioVariableIdx].status != GNOCL_STATUS_CHANGED )
1580 {
1581 gnoclClearOptions ( radioOptions );
1582 Tcl_SetResult ( interp, "Option \"-onValue\" and \"-variable\" are required.", TCL_STATIC );
1583 return TCL_ERROR;
1584 }
1585
1586
1587
1588 /* Create the toobutton item and assign text label and icon. */
1589 if ( getTextAndIcon (
1590 interp, toolbar,
1591 radioOptions + radioTextIdx,
1592 radioOptions + radioIconIdx,
1593 &txt, &icon, &isUnderline ) != TCL_OK )
1594 {
1595 return TCL_ERROR;
1596
1597 }
1598
1599
1600
1601 /* Initialize object parameters. */
1602 para = g_new ( GnoclRadioParams, 1 );
1603
1604 para->name = gnoclGetAutoWidgetId();
1605
1606 para->onToggled = NULL;
1607
1608 para->onValue = NULL;
1609
1610 para->group = gnoclRadioGetGroupFromVariable ( radioOptions[radioVariableIdx].val.str );
1611
1612
1613 /* create new group if necessary */
1614 if ( para->group == NULL )
1615 {
1616
1617 para->group = gnoclRadioGroupNewGroup ( radioOptions[radioVariableIdx].val.str, interp );
1618
1619 para->widget = gtk_radio_tool_button_new ( NULL );
1620
1621 }
1622
1623 else
1624 {
1625
1626 GnoclRadioParams *p = gnoclRadioGetParam ( para->group, 0 );
1627
1628 firstWidget = p->widget;
1629
1630 para->widget = gtk_radio_tool_button_new_from_widget ( firstWidget );
1631
1632 }
1633
1634
1635
1636 /* should this be moved elsewhere? */
1637 g_signal_connect ( para->widget , "toggled", G_CALLBACK ( gnoclRadioToggledFunc ), para );
1638
1639 /* use custom icon and label widgets */
1640 gtk_tool_button_set_icon_widget ( para->widget, icon );
1641 gtk_widget_show ( icon );
1642 gtk_tool_button_set_label ( para->widget, txt );
1643
1644 /* add widget to toolbar and display */
1645 gtk_toolbar_insert ( GTK_TOOLBAR ( toolbar ), para->widget, -1 );
1646 gtk_widget_show ( GTK_WIDGET ( para->widget ) );
1647
1648
1649 /*-----*/
1650
1651
1652 if ( isUnderline )
1653 {
1654 setUnderline ( para->widget );
1655 }
1656
1657 /* add widget to group */
1658 gnoclRadioGroupAddWidgetToGroup ( para->group, para );
1659
1660
1661 /* configure the radiobutton */
1662 if ( gnoclSetOptions ( interp, radioOptions, G_OBJECT ( para->widget ), -1 ) == TCL_OK )
1663 {
1664 ret = radioConfigure ( interp, para, radioOptions );
1665 }
1666
1667
1668
1669 if ( ret != TCL_OK )
1670 {
1671 g_free ( para );
1672 }
1673
1674 else
1675 {
1676 g_signal_connect_after ( G_OBJECT ( para->widget ), "destroy", G_CALLBACK ( gnoclRadioDestroyFunc ), para );
1677
1678 gnoclMemNameAndWidget ( para->name, para->widget );
1679
1680 Tcl_CreateObjCommand ( interp, para->name, radiotoolButtonFunc, para, NULL );
1681 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( para->name, -1 ) );
1682
1683 }
1684
1685 gnoclClearOptions ( radioOptions );
1686
1687 return ret;
1688 }
1689
1690 /**
1691 \brief
1692 \note Using new Toolbar API. Gtk+ 2.16
1693 **/
addMenuButton(GtkToolbar * toolbar,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[],int pos)1694 static int addMenuButton ( GtkToolbar *toolbar, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[], int pos )
1695 {
1696
1697 #ifdef DEBUG_TOOLBAR
1698 listParameters ( objc, objv, __FUNCTION__ );
1699 #endif
1700
1701
1702 int ret;
1703 ToolButtonParams *para = NULL;
1704 char *txt = NULL;
1705 int isUnderline;
1706 GtkWidget *icon; /* image created by getTextAndIcon to hold icon graphic*/
1707
1708 if ( gnoclParseOptions ( interp, objc - 2, objv + 2, menuButtonOptions ) != TCL_OK )
1709 {
1710 gnoclClearOptions ( menuButtonOptions );
1711 return TCL_ERROR;
1712 }
1713
1714 gint i;
1715
1716 /* add label and icon widget */
1717 if ( getTextAndIcon (
1718 interp, toolbar,
1719 menuButtonOptions + menuButtonTextIdx,
1720 menuButtonOptions + menuButtonIconIdx,
1721 &txt, &icon, &isUnderline ) != TCL_OK )
1722 {
1723 return TCL_ERROR;
1724 }
1725
1726 para = g_new ( ToolButtonParams, 1 );
1727
1728 para->onClicked = NULL;
1729
1730 para->interp = interp;
1731
1732 para->name = gnoclGetAutoWidgetId();
1733
1734 //para->item = gtk_tool_button_new ( icon, txt );
1735
1736 para->item = gtk_menu_tool_button_new ( icon, txt );
1737
1738 //g_signal_connect ( para->item , "clicked", G_CALLBACK ( buttonCallback ), para );
1739
1740 gtk_toolbar_insert ( GTK_TOOLBAR ( toolbar ), para->item, -1 );
1741 gtk_widget_show ( GTK_WIDGET ( para->item ) );
1742 /*-----*/
1743
1744 if ( isUnderline )
1745 {
1746 setUnderline ( para->item );
1747 }
1748
1749 ret = gnoclSetOptions ( interp, menuButtonOptions, G_OBJECT ( para->item ), -1 );
1750
1751 if ( ret == TCL_OK )
1752 {
1753 ret = menuButtonConfigure ( interp, para, menuButtonOptions );
1754 }
1755
1756 if ( ret != TCL_OK )
1757 {
1758 g_free ( para );
1759 }
1760
1761 else
1762 {
1763 g_signal_connect_after ( G_OBJECT ( para->item ), "destroy", G_CALLBACK ( buttonDestroyFunc ), para );
1764
1765 gnoclMemNameAndWidget ( para->name, GTK_WIDGET ( para->item ) );
1766
1767 Tcl_CreateObjCommand ( interp, para->name, toolButtonFunc, para, NULL );
1768 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( para->name, -1 ) );
1769 }
1770
1771 gnoclClearOptions ( menuButtonOptions );
1772
1773 return ret;
1774 }
1775
1776 /**
1777 \brief
1778 **/
1779 /* WJG added menuButton item 29/12/07 */
1780
addItem(GtkToolbar * toolbar,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[],int atEnd)1781 static int addItem ( GtkToolbar *toolbar, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[], int atEnd )
1782 {
1783
1784 const char *txt[] =
1785 {
1786
1787 "button", "item",
1788 "toggleButton", "checkItem",
1789 "radioButton", "radioItem",
1790 "separator", "space",
1791 "menuButton",
1792 "widget",
1793 NULL
1794 };
1795 enum typeIdx
1796 {
1797 ButtonIdx, ItemIdx,
1798 ToggleButtonIdx, CheckItemIdx,
1799 RadioButtonIdx, RadioItemIdx,
1800 SpaceIdx, SeparatorIdx,
1801 MenuButtonIdx,
1802 WidgetIdx,
1803 };
1804 int idx;
1805
1806 if ( objc < 3 )
1807 {
1808 Tcl_WrongNumArgs ( interp, 2, objv, "type ?option val ...?" );
1809 return TCL_ERROR;
1810 }
1811
1812 if ( Tcl_GetIndexFromObj ( interp, objv[2], txt, "type", TCL_EXACT, &idx ) != TCL_OK )
1813 {
1814 return TCL_ERROR;
1815 }
1816
1817 switch ( idx )
1818 {
1819 case SeparatorIdx:
1820 case SpaceIdx:
1821 {
1822 gint pos;
1823 gint n = -1;
1824
1825 GtkToolItem *item = NULL;
1826
1827 if ( objc < 3 )
1828 {
1829 Tcl_WrongNumArgs ( interp, 3, objv, NULL );
1830 return TCL_ERROR;
1831 }
1832
1833 item = gtk_separator_tool_item_new ();
1834
1835 gtk_widget_show ( item );
1836
1837 if ( objc == 5 )
1838 {
1839
1840 Tcl_GetIntFromObj ( NULL, objv[4], &pos );
1841
1842 n = gtk_toolbar_get_n_items ( toolbar );
1843
1844 gtk_toolbar_insert ( GTK_TOOLBAR ( toolbar ), item, n );
1845
1846 return TCL_OK;
1847
1848 }
1849
1850 if ( atEnd )
1851 {
1852 gtk_toolbar_insert ( GTK_TOOLBAR ( toolbar ), item, -1 );
1853 }
1854
1855 else
1856 {
1857 gtk_toolbar_insert ( GTK_TOOLBAR ( toolbar ), item, 0 );
1858 }
1859 }
1860
1861 break;
1862 case WidgetIdx:
1863 {
1864 GtkWidget *child;
1865
1866 if ( objc != 4 )
1867 {
1868 Tcl_WrongNumArgs ( interp, 3, objv, "widget-ID" );
1869 return TCL_ERROR;
1870 }
1871
1872 child = gnoclGetWidgetFromName ( Tcl_GetString ( objv[3] ), interp );
1873
1874 if ( child == NULL )
1875 {
1876 return TCL_ERROR;
1877 }
1878
1879 // GtkToolItems are widgets that can appear on a toolbar.
1880 // To create a toolbar item that contain something else than a button, use gtk_tool_item_new().
1881 // Use gtk_container_add() to add a child widget to the tool item.
1882
1883 GtkToolItem *item = gtk_tool_item_new ();
1884
1885 gtk_container_add ( item, child );
1886
1887
1888 if ( atEnd )
1889 {
1890 gtk_toolbar_insert ( toolbar, item, -1 );
1891 }
1892
1893 else
1894 {
1895 gtk_toolbar_insert ( toolbar, item, 0 );
1896 }
1897
1898 gtk_widget_show_all ( item );
1899
1900 Tcl_SetObjResult ( interp, objv[3] );
1901
1902 return TCL_OK;
1903 }
1904
1905 case ItemIdx:
1906 case ButtonIdx:
1907 {
1908 return addButton ( "button", toolbar, interp, objc, objv, atEnd );
1909 }
1910 case ToggleButtonIdx:
1911 case CheckItemIdx:
1912 {
1913 return addCheckButton ( toolbar, interp, objc, objv, atEnd );
1914 }
1915 case RadioButtonIdx:
1916 case RadioItemIdx:
1917 {
1918 return addRadioButton ( toolbar, interp, objc, objv, atEnd );
1919 }
1920 case MenuButtonIdx:
1921 {
1922 return addMenuButton ( toolbar, interp, objc, objv, atEnd );
1923 }
1924 }
1925
1926 return TCL_OK;
1927 }
1928
1929
1930 static const char *cmds[] =
1931 {
1932 "flip", "add", "addBegin", "addEnd",
1933 "class", "configure", "delete",
1934 "insert", "nItems", "cget",
1935 "parent",
1936 NULL
1937 };
1938
1939
1940 /**
1941 \brief
1942 \note Due to the deprecation of gtk_toolbar_prepend_item etc., the following command need to
1943 be recoded to reflect the use of gtk_toolbar_insert
1944
1945 "add", "addBegin", "addEnd"
1946
1947 **/
toolBarFunc(ClientData data,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])1948 int toolBarFunc ( ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[] )
1949 {
1950
1951 enum cmdIdx
1952 {
1953 FlipIdx, AddIdx, BeginIdx, EndIdx,
1954 ClassIdx, ConfigureIdx, DeleteIdx,
1955 InsertIdx, NitemsIdx, CgetIdx,
1956 ParentIdx
1957 };
1958
1959 GtkToolbar *toolBar = GTK_TOOLBAR ( data );
1960 int idx;
1961
1962 if ( objc < 2 )
1963 {
1964 Tcl_WrongNumArgs ( interp, 1, objv, "command" );
1965 return TCL_ERROR;
1966 }
1967
1968 if ( Tcl_GetIndexFromObj ( interp, objv[1], cmds, "command", TCL_EXACT, &idx ) != TCL_OK )
1969 {
1970 return TCL_ERROR;
1971 }
1972
1973 switch ( idx )
1974 {
1975
1976 case FlipIdx:
1977 {
1978
1979 if ( gtk_toolbar_get_orientation ( toolBar ) == GTK_ORIENTATION_HORIZONTAL )
1980 {
1981 gtk_orientable_set_orientation ( GTK_ORIENTABLE ( toolBar ), GTK_ORIENTATION_VERTICAL );
1982 }
1983
1984 else
1985 {
1986 gtk_orientable_set_orientation ( GTK_ORIENTABLE ( toolBar ), GTK_ORIENTATION_HORIZONTAL );
1987 }
1988 }
1989 break;
1990 case ParentIdx:
1991 {
1992
1993 GtkWidget * parent;
1994 Tcl_Obj *obj = NULL;
1995 parent = gtk_widget_get_parent ( GTK_WIDGET ( toolBar ) );
1996 obj = Tcl_NewStringObj ( gnoclGetNameFromWidget ( parent ), -1 );
1997 Tcl_SetObjResult ( interp, obj );
1998
1999 /* this function not working too well! */
2000 /* return gnoclGetParent ( interp, data ); */
2001 return TCL_OK;
2002 }
2003
2004 break;
2005 case CgetIdx:
2006 {
2007 int idx;
2008
2009 switch ( gnoclCget ( interp, objc, objv, G_OBJECT ( toolBar ), toolBarOptions, &idx ) )
2010 {
2011 case GNOCL_CGET_ERROR:
2012 {
2013 return TCL_ERROR;
2014 }
2015 case GNOCL_CGET_HANDLED:
2016 {
2017 return TCL_OK;
2018 }
2019 case GNOCL_CGET_NOTHANDLED:
2020 {
2021 return toolBarCget ( interp, toolBar, toolBarOptions, idx );
2022 }
2023 }
2024 }
2025 break;
2026 case NitemsIdx:
2027 {
2028
2029 gchar str[4];
2030 gint n;
2031
2032 n = gtk_toolbar_get_n_items ( toolBar );
2033
2034 sprintf ( str, "%d", n );
2035
2036 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( str, -1 ) );
2037 }
2038 break;
2039 case ClassIdx:
2040 {
2041 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( "toolBar", -1 ) );
2042 }
2043 break;
2044 case DeleteIdx:
2045 {
2046 return gnoclDelete ( interp, GTK_WIDGET ( toolBar ), objc, objv );
2047 }
2048 case ConfigureIdx:
2049 {
2050 //int ret = gnoclParseAndSetOptions ( interp, objc - 1, objv + 1, toolBarOptions, G_OBJECT ( toolBar ) );
2051 //gnoclClearOptions ( toolBarOptions );
2052 //return ret;
2053 int ret = TCL_ERROR;
2054
2055 if ( gnoclParseAndSetOptions ( interp, objc - 1, objv + 1, toolBarOptions, G_OBJECT ( toolBar ) ) == TCL_OK )
2056 {
2057 ret = configure ( interp, toolBar, toolBarOptions );
2058 }
2059
2060 gnoclClearOptions ( toolBarOptions );
2061
2062 return ret;
2063
2064
2065
2066 }
2067
2068 break;
2069
2070 case AddIdx: /* add is a shortcut for addEnd */
2071 case BeginIdx:
2072 case EndIdx:
2073 {
2074 return addItem ( toolBar, interp, objc, objv, idx != BeginIdx );
2075 }
2076 }
2077
2078 return TCL_OK;
2079 }
2080
2081 /**
2082 \brief Create an instance of a gnocl:toolBar widget.
2083 **/
gnoclToolBarCmd(ClientData data,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])2084 int gnoclToolBarCmd ( ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[] )
2085 {
2086
2087 if ( gnoclGetCmdsAndOpts ( interp, cmds, toolBarOptions, objv, objc ) == TCL_OK )
2088 {
2089 return TCL_OK;
2090 }
2091
2092
2093 int ret;
2094 GtkToolbar *toolBar;
2095
2096 if ( gnoclParseOptions ( interp, objc, objv, toolBarOptions ) != TCL_OK )
2097 {
2098 gnoclClearOptions ( toolBarOptions );
2099 return TCL_ERROR;
2100 }
2101
2102 toolBar = GTK_TOOLBAR ( gtk_toolbar_new() );
2103
2104 /* turn arrows off, this will prevent problems with toolbars in handleboxes */
2105 gtk_toolbar_set_show_arrow ( toolBar, 0 );
2106
2107 gtk_widget_show ( GTK_WIDGET ( toolBar ) );
2108
2109 ret = gnoclSetOptions ( interp, toolBarOptions, G_OBJECT ( toolBar ), -1 );
2110
2111 if ( ret == TCL_OK )
2112 {
2113 ret = configure ( interp, toolBar, toolBarOptions );
2114 }
2115
2116 gnoclClearOptions ( toolBarOptions );
2117
2118 if ( ret != TCL_OK )
2119 {
2120 gtk_widget_destroy ( GTK_WIDGET ( toolBar ) );
2121 return TCL_ERROR;
2122 }
2123
2124 return gnoclRegisterWidget ( interp, GTK_WIDGET ( toolBar ), toolBarFunc );
2125 }
2126
2127
2128