1 /* menus_n_tools.c - menus and toolbar constructors / destructors
2 * One application = a menu / tool bar + a list of documents
3 *
4 * Copyright (C) 2001 Patrice St-Gelais
5 * patrstg@users.sourceforge.net
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 #include <stdlib.h>
23 #include <gtk/gtk.h>
24 #include "utils.h"
25 #include "x_alloc.h"
26 #include "menus_n_tools.h"
27 // #define _(x) pr(x)
28
pr(gchar * x)29 gchar *pr(gchar *x) {
30 printf(x);
31 return (gchar *) gettext(x);
32 }
33
submenu_new(gint ndx,gchar * label,GtkWidget * bar)34 submenu_struct *submenu_new (gint ndx, gchar *label, GtkWidget *bar) {
35
36 // Creates and shows a submenu (to be inserted in a menu bar)
37 // ndx is the index in ((command_item_struct *)tools) of the first item in the submenu
38 submenu_struct *subm_buf;
39 // printf("SUBMENU_NEW: Adding label: %s\n",label);
40 if (NULL == (subm_buf = (submenu_struct *) x_malloc(sizeof(submenu_struct), "submenu_struct")))
41 my_msg("Allocation: submenu_struct ???\n",ABORT);
42 subm_buf->itemndx = (GList *)NULL;
43 subm_buf->itemndx = g_list_append(subm_buf->itemndx, (gpointer) ndx);
44 subm_buf->sm_item = gtk_menu_item_new_with_label(label);
45 gtk_menu_bar_append (GTK_MENU_BAR (bar), subm_buf->sm_item);
46 gtk_widget_show(subm_buf->sm_item);
47 subm_buf->sm_menu = gtk_menu_new();
48 gtk_menu_item_set_submenu (GTK_MENU_ITEM (subm_buf->sm_item), subm_buf->sm_menu);
49 // printf("Added label: %s\n",label);
50 return subm_buf;
51 }
52
menu_new(gint nbitems,command_item_struct * items,GtkAccelGroup * accel_grp,gpointer callback_data)53 menu_struct *menu_new(gint nbitems, command_item_struct *items,
54 GtkAccelGroup *accel_grp,
55 gpointer callback_data) {
56
57 // Initializes a menu bar and submenus from a command_item_struct table
58 // Initializes substructures in menu
59
60 gint i=0;
61 gchar *cur_group = "*";
62 menu_struct *menu;
63 GtkWidget *item_buf;
64 // printf("MENU_NEW\n");
65
66 if (NULL == (menu = (menu_struct *)x_malloc(sizeof(menu_struct), "menu_struct")))
67 my_msg("Allocation: menu ???\n",ABORT);
68
69 menu->nbtools = nbitems;
70 menu->tools = items;
71 menu->submenus = (GList *) NULL;
72 menu->bar = gtk_menu_bar_new();
73 gtk_widget_show(menu->bar);
74
75 for (i=0; i<nbitems; i++) {
76
77 // printf ("Current group: %d - %s / %s, label: %s, tooltip: %s, \n",
78 // i, cur_group, (items+i)->group, (items+i)->label, (items+i)->tooltip);
79
80 if ( strcmp(cur_group,(items+i)->group)) {
81 // Add an item (submenu) to the menu bar when the label changes
82 cur_group = (items+i)->group;
83 menu->submenus =
84 g_list_append(menu->submenus,
85 (gpointer) submenu_new(i, _(cur_group), menu->bar) );
86
87 // printf("Longueur liste: %d; noeud courant: %d \n",g_list_length(menu->submenus), menu->submenus);
88 }
89
90 // Add submenu item to the current submenu
91 if ( ! (items+i)->label) {
92 // Add a separator
93 item_buf = gtk_menu_item_new();
94 }
95 else {
96 if ((items+i)->iftoggle) {
97 item_buf = gtk_check_menu_item_new_with_label(_((items+i)->label));
98 }
99 else {
100 item_buf = gtk_menu_item_new_with_label(_((items+i)->label));
101 }
102 gtk_signal_connect (GTK_OBJECT (item_buf), "activate",
103 GTK_SIGNAL_FUNC((items+i)->command_callb),callback_data);
104 }
105 gtk_menu_append (GTK_MENU ( ((submenu_struct*) g_list_last(menu->submenus)->data)->sm_menu),
106 item_buf);
107 // Keep the indexes for future use (?)
108 ((submenu_struct *) g_list_last(menu->submenus)->data)->itemndx =
109 g_list_append( ((submenu_struct *) g_list_last(menu->submenus)->data)->itemndx , (gpointer) i);
110 (items+i)->menu_item = item_buf; // For future use (ex. freeing the widget)
111 if ((items+i)->accel)
112 gtk_widget_add_accelerator (item_buf, "activate", accel_grp,
113 (items+i)->accel, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
114
115 gtk_widget_show (item_buf);
116
117 }
118 return menu;
119 }
120
set_toolbar_button_from_label(GtkWidget * tb,gchar * label,gboolean value)121 void set_toolbar_button_from_label (GtkWidget *tb, gchar *label, gboolean value) {
122 GtkToolbarChild *child;
123 GList *node, *list;
124 gchar *lbl;
125 for (node = (GList *)GTK_TOOLBAR(tb)->children; node; node = node->next) {
126 child = (GtkToolbarChild *) node->data;
127 for (list = gtk_container_children(GTK_CONTAINER(GTK_BIN(child->widget)->child));
128 list ; list = list->next) {
129 if (GTK_IS_LABEL(GTK_OBJECT(list->data)))
130 gtk_label_get(GTK_LABEL(list->data), &lbl);
131 }
132 // printf("LABEL: %s; LBL: %s\n",_(label),lbl);
133 if (!strcmp(_(label),lbl)) {
134 // gtk_widget_activate(GTK_WIDGET(child->widget));
135 // printf("Setting %s to %d\n",lbl,value);
136 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON( child->widget), value);
137 return;
138 }
139 }
140 }
141
set_toolbar_button_from_order(GtkWidget * tb,gint order,gboolean value)142 void set_toolbar_button_from_order (GtkWidget *tb, gint order, gboolean value) {
143 // "order" starts at 0
144 GtkToolbarChild *child;
145 child = (GtkToolbarChild *) g_list_nth_data(GTK_TOOLBAR(tb)->children,order);
146 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON( child->widget), value);
147 }
148
standard_toolbar_new(gint nbitems,command_item_struct * items,GtkTooltips * tooltips,GtkWidget * window,gpointer callback_data,GtkOrientation tborient,GtkToolbarStyle tbstyle,gboolean ifradio)149 GtkWidget *standard_toolbar_new (gint nbitems, command_item_struct *items,
150 GtkTooltips *tooltips, GtkWidget *window, gpointer callback_data,
151 GtkOrientation tborient, GtkToolbarStyle tbstyle, gboolean ifradio) {
152 // 2004-01-16 Variation on toolbar_new
153 // More generic
154 // Returns a simple GtkWidget - no specialized struct here
155
156 gint i, index_toggled = 0;
157 gchar *cur_group;
158 GtkWidget *lastitem=NULL, *toolbar;
159
160 cur_group = items->group;
161 toolbar = gtk_toolbar_new ();
162 gtk_toolbar_set_orientation(GTK_TOOLBAR(toolbar),tborient);
163 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar),tbstyle);
164 gtk_widget_show (toolbar);
165
166 // printf("TOOLBAR_NEW avant boucle; nbitems: %d\n",nbitems);
167 for (i=0; i<nbitems; i++) {
168
169 // printf ("Current group: %s ;", cur_group);
170
171 if ( strcmp(cur_group,(items+i)->group)) {
172 // Add double space when menu item in menu bar changes
173 gtk_toolbar_append_space (GTK_TOOLBAR(toolbar));
174 gtk_toolbar_append_space (GTK_TOOLBAR(toolbar));
175 cur_group = (items+i)->group;
176 }
177 // printf("i: %d\n",i);
178 // Add submenu item to the current submenu
179 if ( ! (items+i)->label) {
180 // Add space as separator
181 gtk_toolbar_append_space (GTK_TOOLBAR(toolbar));
182 }
183 else {
184 if (ifradio) {
185 // printf("IFRADIO\nlabel: %s\ntooltip: %s\nwindow: %d\ncommand_callb: %d\ncallb_data: %d\nicon: %d\n",
186 // (items+i)->label, (items+i)->tooltip,window, (items+i)->command_callb, callback_data, (items+i)->icon);
187 (items+i)->toolbar_item = gtk_toolbar_append_element (
188 GTK_TOOLBAR(toolbar),
189 GTK_TOOLBAR_CHILD_RADIOBUTTON,
190 lastitem,
191 _((items+i)->label),
192 _((items+i)->tooltip),
193 NULL,
194 create_widget_from_xpm(window,(items+i)->icon),
195 GTK_SIGNAL_FUNC((items+i)->command_callb),
196 callback_data);
197 // printf("IFRADIO fin\n");
198 lastitem = (items+i)->toolbar_item;
199 if ((items+i)->iftoggle )
200 index_toggled = i;
201 } // if (ifradio)
202 else {
203 (items+i)->toolbar_item = gtk_toolbar_append_element (
204 GTK_TOOLBAR(toolbar),
205 (items+i)->iftoggle?GTK_TOOLBAR_CHILD_TOGGLEBUTTON :
206 GTK_TOOLBAR_CHILD_BUTTON,
207 NULL,
208 _((items+i)->label),
209 _((items+i)->tooltip),
210 NULL,
211 create_widget_from_xpm(window,(items+i)->icon),
212 GTK_SIGNAL_FUNC((items+i)->command_callb),
213 callback_data);
214 } // else (ifradio)
215 } // else (! (items+i)->label)
216 } // for
217 // Seg fault with some toolbars, probably because
218 // of a callback trying to process a NULL pointer
219 // if (ifradio)
220 // set_toolbar_button_from_order(toolbar->toolbarwdg, index_toggled, TRUE);
221
222 return toolbar ;
223 }
224
toolbar_new(gint nbitems,command_item_struct * items,GtkTooltips * tooltips,GtkWidget * window,gpointer callback_data,GtkOrientation tborient,GtkToolbarStyle tbstyle,gboolean ifradio)225 toolbar_struct *toolbar_new( gint nbitems, command_item_struct *items,
226 GtkTooltips *tooltips, GtkWidget *window, gpointer callback_data,
227 GtkOrientation tborient, GtkToolbarStyle tbstyle, gboolean ifradio) {
228
229 gint i, index_toggled = 0;
230 gchar *cur_group;
231 GtkWidget *lastitem=NULL;
232
233 toolbar_struct *toolbar;
234 if (NULL == (toolbar = (toolbar_struct *) x_malloc(sizeof(toolbar_struct), "toolbar_struct")))
235 my_msg("Allocation: toolbar ???\n",ABORT);
236
237 cur_group = items->group;
238 toolbar->tborient = tborient;
239 toolbar->tbstyle = tbstyle;
240 toolbar->ifradio = ifradio;
241 toolbar->toolbarwdg = gtk_toolbar_new ();
242 gtk_toolbar_set_orientation(GTK_TOOLBAR(toolbar->toolbarwdg),tborient);
243 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar->toolbarwdg),tbstyle);
244 gtk_widget_show (toolbar->toolbarwdg);
245
246 // printf("TOOLBAR_NEW avant boucle; nbitems: %d\n",nbitems);
247 for (i=0; i<nbitems; i++) {
248
249 // printf ("Current group: %s ;", cur_group);
250
251 if ( strcmp(cur_group,(items+i)->group)) {
252 // Add double space when menu item in menu bar changes
253 gtk_toolbar_append_space (GTK_TOOLBAR(toolbar->toolbarwdg));
254 gtk_toolbar_append_space (GTK_TOOLBAR(toolbar->toolbarwdg));
255 cur_group = (items+i)->group;
256 }
257 // printf("i: %d\n",i);
258 // Add submenu item to the current submenu
259 if ( ! (items+i)->label) {
260 // Add space as separator
261 gtk_toolbar_append_space (GTK_TOOLBAR(toolbar->toolbarwdg));
262 }
263 else {
264 if (ifradio) {
265 // printf("IFRADIO\nlabel: %s\ntooltip: %s\nwindow: %d\ncommand_callb: %d\ncallb_data: %d\nicon: %d\n",
266 // (items+i)->label, (items+i)->tooltip,window, (items+i)->command_callb, callback_data, (items+i)->icon);
267 (items+i)->toolbar_item = gtk_toolbar_append_element (
268 GTK_TOOLBAR(toolbar->toolbarwdg),
269 GTK_TOOLBAR_CHILD_RADIOBUTTON,
270 lastitem,
271 _((items+i)->label),
272 _((items+i)->tooltip),
273 NULL,
274 create_widget_from_xpm(window,(items+i)->icon),
275 GTK_SIGNAL_FUNC((items+i)->command_callb),
276 callback_data);
277 // printf("IFRADIO fin\n");
278 lastitem = (items+i)->toolbar_item;
279 if ((items+i)->iftoggle )
280 index_toggled = i;
281 }
282 else
283 (items+i)->toolbar_item = gtk_toolbar_append_element (
284 GTK_TOOLBAR(toolbar->toolbarwdg),
285 (items+i)->iftoggle?GTK_TOOLBAR_CHILD_TOGGLEBUTTON :
286 GTK_TOOLBAR_CHILD_BUTTON,
287 NULL,
288 _((items+i)->label),
289 _((items+i)->tooltip),
290 NULL,
291 create_widget_from_xpm(window,(items+i)->icon),
292 GTK_SIGNAL_FUNC((items+i)->command_callb),
293 callback_data);
294 }
295 }
296 // Seg fault with some toolbars, probably because
297 // of a callback trying to process a NULL pointer
298 // if (ifradio)
299 // set_toolbar_button_from_order(toolbar->toolbarwdg, index_toggled, TRUE);
300
301 return toolbar ;
302 }
303
multi_toolbar_new(gint nbitems,command_item_struct * items,GtkTooltips * tooltips,GtkWidget * window,gpointer callback_data,GtkOrientation tborient,GtkToolbarStyle tbstyle,gboolean ifradio)304 toolbar_struct *multi_toolbar_new( gint nbitems, command_item_struct *items,
305 GtkTooltips *tooltips, GtkWidget *window, gpointer callback_data,
306 GtkOrientation tborient, GtkToolbarStyle tbstyle, gboolean ifradio) {
307
308 // Builds a toolbar OR a box of toolbars,
309 // depending on the separators in command_item
310 // (we create a new line / column each time we encounter a separator)
311 gint i, nbbars=0;
312 gchar *cur_group;
313 GtkWidget *lastitem=NULL, *tb=NULL, *box=NULL;
314
315 toolbar_struct *toolbar;
316 if (NULL == (toolbar = (toolbar_struct *) x_malloc(sizeof(toolbar_struct), "toolbar_struct")))
317 my_msg("Allocation: toolbar ???\n",ABORT);
318
319 cur_group = items->group;
320 toolbar->tborient = tborient;
321 toolbar->tbstyle = tbstyle;
322 toolbar->ifradio = ifradio;
323 tb = gtk_toolbar_new ();
324 gtk_toolbar_set_orientation(GTK_TOOLBAR(tb),tborient);
325 gtk_toolbar_set_style(GTK_TOOLBAR(tb),tbstyle);
326 gtk_widget_show(tb);
327 box = tb;
328
329 // printf("TOOLBAR_NEW avant boucle; nbitems: %d\n",nbitems);
330 for (i=0; i<nbitems; i++) {
331
332 // printf ("Current group: %s ;", cur_group);
333
334 if ( strcmp(cur_group,(items+i)->group)) {
335 // Add double space when menu item in menu bar changes
336 gtk_toolbar_append_space (GTK_TOOLBAR(toolbar->toolbarwdg));
337 gtk_toolbar_append_space (GTK_TOOLBAR(toolbar->toolbarwdg));
338 cur_group = (items+i)->group;
339 }
340 // printf("i: %d\n",i);
341 // Add submenu item to the current submenu
342 if ( ! (items+i)->label) {
343 // Add space as separator
344 // ... 2002.04.14 - Create a new line / column!
345 // gtk_toolbar_append_space (GTK_TOOLBAR(toolbar->toolbarwdg));
346 if (!nbbars) {
347 if (tborient == GTK_ORIENTATION_HORIZONTAL)
348 box = gtk_vbox_new(FALSE,0);
349 else
350 box = gtk_hbox_new(FALSE,0);
351 gtk_widget_show(GTK_WIDGET(box));
352 }
353 nbbars++;
354 gtk_box_pack_start(GTK_BOX(box),tb,FALSE,FALSE,0);
355 tb = gtk_toolbar_new ();
356 gtk_toolbar_set_orientation(GTK_TOOLBAR(tb),tborient);
357 gtk_toolbar_set_style(GTK_TOOLBAR(tb),tbstyle);
358 gtk_widget_show(tb);
359 }
360 else {
361 if (ifradio) {
362 // printf("IFRADIO\nlabel: %s\ntooltip: %s\nwindow: %d\ncommand_callb: %d\ncallb_data: %d\nicon: %d\n",
363 // (items+i)->label, (items+i)->tooltip,window, (items+i)->command_callb, callback_data, (items+i)->icon);
364 (items+i)->toolbar_item = gtk_toolbar_append_element (
365 GTK_TOOLBAR(tb),
366 GTK_TOOLBAR_CHILD_RADIOBUTTON,
367 lastitem,
368 _((items+i)->label),
369 _((items+i)->tooltip),
370 NULL,
371 create_widget_from_xpm(window,(items+i)->icon),
372 GTK_SIGNAL_FUNC((items+i)->command_callb),
373 callback_data);
374 // printf("IFRADIO fin\n");
375 lastitem = (items+i)->toolbar_item;
376 }
377 else
378 (items+i)->toolbar_item = gtk_toolbar_append_element (
379 GTK_TOOLBAR(tb),
380 (items+i)->iftoggle?GTK_TOOLBAR_CHILD_TOGGLEBUTTON :
381 GTK_TOOLBAR_CHILD_BUTTON,
382 NULL,
383 _((items+i)->label),
384 _((items+i)->tooltip),
385 NULL,
386 create_widget_from_xpm(window,(items+i)->icon),
387 GTK_SIGNAL_FUNC((items+i)->command_callb),
388 callback_data);
389 }
390 }
391 if (!nbbars)
392 toolbar->toolbarwdg = tb;
393 else {
394 gtk_box_pack_start(GTK_BOX(box),tb,FALSE,FALSE,0);
395 toolbar->toolbarwdg = box;
396 }
397 return toolbar ;
398 }
399
400
menu_free(menu_struct * menu)401 void menu_free(menu_struct *menu) {
402
403 gint i;
404 GList *node;
405 // We free the menuitem widgets in the commands table (probably not necessary...)
406 for (i=0; i<menu->nbtools; i++) {
407 if ((menu->tools+i)->menu_item)
408 gtk_widget_destroy((menu->tools+i)->menu_item);
409 }
410
411 // We free the menu bar struct
412
413 for (node = g_list_nth (menu->submenus,1); node; node = node->next) {
414 g_list_free(((submenu_struct*)node->data)->itemndx);
415 gtk_widget_destroy( ((submenu_struct*)node->data)->sm_item);
416 gtk_widget_destroy( ((submenu_struct*)node->data)->sm_menu);
417 }
418 g_list_free(menu->submenus);
419
420 // We free the whole structure
421 x_free(menu);
422 }
423
toolbar_free(toolbar_struct * toolbar)424 void toolbar_free(toolbar_struct *toolbar) {
425 gint i;
426 // We free the menuitem widgets in the commands table
427 for (i=0; i<toolbar->nbtools; i++) {
428 if ((toolbar->tools+i)->toolbar_item)
429 gtk_widget_destroy((toolbar->tools+i)->toolbar_item);
430 }
431
432 // Freeing the whole structure
433 gtk_widget_destroy(toolbar->toolbarwdg);
434 x_free(toolbar);
435 }
436
437
438