r3768: Updated years.
[rox-filer.git] / ROX-Filer / src / toolbar.c
blob7154fefdb6ca20494b15bb4cf36a7e825cb6d2bd
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2005, the ROX-Filer team.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 /* toolbar.c - for the button bars that go along the tops of windows */
24 #include "config.h"
26 #include <string.h>
28 #include "global.h"
30 #include "toolbar.h"
31 #include "options.h"
32 #include "support.h"
33 #include "main.h"
34 #include "menu.h"
35 #include "dnd.h"
36 #include "filer.h"
37 #include "display.h"
38 #include "pixmaps.h"
39 #include "bind.h"
40 #include "type.h"
41 #include "dir.h"
42 #include "diritem.h"
43 #include "view_iface.h"
44 #include "bookmarks.h"
45 #include "gui_support.h"
47 typedef struct _Tool Tool;
49 typedef enum {DROP_NONE, DROP_TO_PARENT, DROP_TO_HOME, DROP_BOOKMARK} DropDest;
51 struct _Tool {
52 const gchar *label;
53 const gchar *name;
54 const gchar *tip; /* Tooltip */
55 void (*clicked)(GtkWidget *w, FilerWindow *filer_window);
56 DropDest drop_action;
57 gboolean enabled;
58 gboolean menu; /* Activate on button-press */
61 Option o_toolbar, o_toolbar_info, o_toolbar_disable;
62 Option o_toolbar_min_width;
64 static GtkTooltips *tooltips = NULL;
65 static FilerWindow *filer_window_being_counted;
67 /* TRUE if the button presses (or released) should open a new window,
68 * rather than reusing the existing one.
70 #define NEW_WIN_BUTTON(button_event) \
71 (o_new_button_1.int_value \
72 ? ((GdkEventButton *) button_event)->button == 1 \
73 : ((GdkEventButton *) button_event)->button != 1)
75 /* Static prototypes */
76 static void toolbar_close_clicked(GtkWidget *widget, FilerWindow *filer_window);
77 static void toolbar_up_clicked(GtkWidget *widget, FilerWindow *filer_window);
78 static void toolbar_home_clicked(GtkWidget *widget, FilerWindow *filer_window);
79 static void toolbar_bookmarks_clicked(GtkWidget *widget,
80 FilerWindow *filer_window);
81 static void toolbar_help_clicked(GtkWidget *widget, FilerWindow *filer_window);
82 static void toolbar_refresh_clicked(GtkWidget *widget,
83 FilerWindow *filer_window);
84 static void toolbar_size_clicked(GtkWidget *widget, FilerWindow *filer_window);
85 static void toolbar_autosize_clicked(GtkWidget *widget, FilerWindow *filer_window);
86 static void toolbar_details_clicked(GtkWidget *widget,
87 FilerWindow *filer_window);
88 static void toolbar_hidden_clicked(GtkWidget *widget,
89 FilerWindow *filer_window);
90 static void toolbar_select_clicked(GtkWidget *widget,
91 FilerWindow *filer_window);
92 static void toolbar_sort_clicked(GtkWidget *widget,
93 FilerWindow *filer_window);
94 static GtkWidget *add_button(GtkWidget *bar, Tool *tool,
95 FilerWindow *filer_window);
96 static GtkWidget *create_toolbar(FilerWindow *filer_window);
97 static gboolean drag_motion(GtkWidget *widget,
98 GdkDragContext *context,
99 gint x,
100 gint y,
101 guint time,
102 FilerWindow *filer_window);
103 static void drag_leave(GtkWidget *widget,
104 GdkDragContext *context,
105 guint32 time,
106 FilerWindow *filer_window);
107 static void handle_drops(FilerWindow *filer_window,
108 GtkWidget *button,
109 DropDest dest);
110 static void toggle_selected(GtkToggleButton *widget, gpointer data);
111 static void option_notify(void);
112 static GList *build_tool_options(Option *option, xmlNode *node, guchar *label);
113 static void tally_items(gpointer key, gpointer value, gpointer data);
115 static Tool all_tools[] = {
116 {N_("Close"), GTK_STOCK_CLOSE, N_("Close filer window"),
117 toolbar_close_clicked, DROP_NONE, FALSE,
118 FALSE},
120 {N_("Up"), GTK_STOCK_GO_UP, N_("Change to parent directory"),
121 toolbar_up_clicked, DROP_TO_PARENT, TRUE,
122 FALSE},
124 {N_("Home"), GTK_STOCK_HOME, N_("Change to home directory"),
125 toolbar_home_clicked, DROP_TO_HOME, TRUE,
126 FALSE},
128 {N_("Bookmarks"), ROX_STOCK_BOOKMARKS, N_("Bookmarks menu"),
129 toolbar_bookmarks_clicked, DROP_BOOKMARK, FALSE,
130 TRUE},
132 {N_("Scan"), GTK_STOCK_REFRESH, N_("Rescan directory contents"),
133 toolbar_refresh_clicked, DROP_NONE, TRUE,
134 FALSE},
136 {N_("Size"), GTK_STOCK_ZOOM_IN, N_("Change icon size"),
137 toolbar_size_clicked, DROP_NONE, TRUE,
138 FALSE},
140 {N_("Size"), GTK_STOCK_ZOOM_FIT, N_("Automatic size mode"),
141 toolbar_autosize_clicked, DROP_NONE, TRUE,
142 FALSE},
144 {N_("Details"), ROX_STOCK_SHOW_DETAILS, N_("Show extra details"),
145 toolbar_details_clicked, DROP_NONE, TRUE,
146 FALSE},
148 {N_("Sort"), GTK_STOCK_SORT_ASCENDING, N_("Change sort criteria"),
149 toolbar_sort_clicked, DROP_NONE, FALSE,
150 FALSE},
152 {N_("Hidden"), ROX_STOCK_SHOW_HIDDEN, N_("Show/hide hidden files"),
153 toolbar_hidden_clicked, DROP_NONE, TRUE,
154 FALSE},
156 {N_("Select"), ROX_STOCK_SELECT, N_("Select all/invert selection"),
157 toolbar_select_clicked, DROP_NONE, FALSE,
158 FALSE},
160 {N_("Help"), GTK_STOCK_HELP, N_("Show ROX-Filer help"),
161 toolbar_help_clicked, DROP_NONE, TRUE,
162 FALSE},
166 /****************************************************************
167 * EXTERNAL INTERFACE *
168 ****************************************************************/
170 void toolbar_init(void)
172 option_add_int(&o_toolbar, "toolbar_type", TOOLBAR_NORMAL);
173 option_add_int(&o_toolbar_info, "toolbar_show_info", 1);
174 option_add_string(&o_toolbar_disable, "toolbar_disable",
175 GTK_STOCK_CLOSE);
176 option_add_int(&o_toolbar_min_width, "toolbar_min_width", 1);
177 option_add_notify(option_notify);
179 tooltips = gtk_tooltips_new();
181 option_register_widget("tool-options", build_tool_options);
184 void toolbar_update_info(FilerWindow *filer_window)
186 gchar *label;
187 ViewIface *view;
188 int n_selected;
190 if (o_toolbar.int_value == TOOLBAR_NONE || !o_toolbar_info.int_value)
191 return; /* Not showing info */
193 if (filer_window->target_cb)
194 return;
196 view = filer_window->view;
198 n_selected = view_count_selected(view);
200 if (n_selected == 0)
202 gchar *s = NULL;
203 int n_items;
205 if (filer_window->scanning)
207 gtk_label_set_text(
208 GTK_LABEL(filer_window->toolbar_text), "");
209 return;
212 if (!(filer_window->show_hidden ||
213 filer_window->temp_show_hidden) ||
214 filer_window->filter!=FILER_SHOW_ALL)
216 GHashTable *hash = filer_window->directory->known_items;
217 int tally = 0;
219 filer_window_being_counted=filer_window;
220 g_hash_table_foreach(hash, tally_items, &tally);
222 if (tally)
223 s = g_strdup_printf(_(" (%u hidden)"), tally);
226 n_items = view_count_items(view);
228 if (n_items)
229 label = g_strdup_printf("%d %s%s",
230 n_items,
231 n_items != 1 ? _("items") : _("item"),
232 s ? s : "");
233 else /* (French plurals work differently for zero) */
234 label = g_strdup_printf(_("No items%s"),
235 s ? s : "");
236 g_free(s);
238 else
240 double size = 0;
241 ViewIter iter;
242 DirItem *item;
244 view_get_iter(filer_window->view, &iter, VIEW_ITER_SELECTED);
246 while ((item = iter.next(&iter)))
248 if (item->base_type != TYPE_DIRECTORY &&
249 item->base_type != TYPE_UNKNOWN)
250 size += (double) item->size;
253 label = g_strdup_printf(_("%u selected (%s)"),
254 n_selected, format_double_size(size));
257 gtk_label_set_text(GTK_LABEL(filer_window->toolbar_text), label);
258 g_free(label);
261 /* Create, destroy or recreate toolbar for this window so that it
262 * matches the option setting.
264 void toolbar_update_toolbar(FilerWindow *filer_window)
266 g_return_if_fail(filer_window != NULL);
268 if (filer_window->toolbar)
270 gtk_widget_destroy(filer_window->toolbar);
271 filer_window->toolbar = NULL;
272 filer_window->toolbar_text = NULL;
275 if (o_toolbar.int_value != TOOLBAR_NONE)
277 filer_window->toolbar = create_toolbar(filer_window);
278 gtk_box_pack_start(filer_window->toplevel_vbox,
279 filer_window->toolbar, FALSE, TRUE, 0);
280 gtk_box_reorder_child(filer_window->toplevel_vbox,
281 filer_window->toolbar, 0);
282 gtk_widget_show_all(filer_window->toolbar);
285 filer_target_mode(filer_window, NULL, NULL, NULL);
286 toolbar_update_info(filer_window);
289 /****************************************************************
290 * INTERNAL FUNCTIONS *
291 ****************************************************************/
293 static void toolbar_help_clicked(GtkWidget *widget, FilerWindow *filer_window)
295 GdkEvent *event;
297 event = gtk_get_current_event();
298 if (event->type == GDK_BUTTON_RELEASE &&
299 ((GdkEventButton *) event)->button != 1)
300 menu_rox_help(NULL, HELP_MANUAL, NULL);
301 else
302 filer_opendir(make_path(app_dir, "Help"), NULL, NULL);
305 static void toolbar_refresh_clicked(GtkWidget *widget,
306 FilerWindow *filer_window)
308 GdkEvent *event;
310 event = gtk_get_current_event();
311 if (event->type == GDK_BUTTON_RELEASE &&
312 ((GdkEventButton *) event)->button != 1)
314 filer_opendir(filer_window->sym_path, filer_window, NULL);
316 else
317 filer_refresh(filer_window);
320 static void toolbar_home_clicked(GtkWidget *widget, FilerWindow *filer_window)
322 GdkEvent *event;
324 event = gtk_get_current_event();
325 if (event->type == GDK_BUTTON_RELEASE && NEW_WIN_BUTTON(event))
327 filer_opendir(home_dir, filer_window, NULL);
329 else
330 filer_change_to(filer_window, home_dir, NULL);
333 static void toolbar_bookmarks_clicked(GtkWidget *widget,
334 FilerWindow *filer_window)
336 GdkEvent *event;
338 g_return_if_fail(filer_window != NULL);
340 event = gtk_get_current_event();
341 if (event->type == GDK_BUTTON_PRESS &&
342 ((GdkEventButton *) event)->button == 1)
344 bookmarks_show_menu(filer_window);
346 else if (event->type == GDK_BUTTON_RELEASE &&
347 ((GdkEventButton *) event)->button != 1)
349 bookmarks_edit();
353 static void toolbar_close_clicked(GtkWidget *widget, FilerWindow *filer_window)
355 GdkEvent *event;
357 g_return_if_fail(filer_window != NULL);
359 event = gtk_get_current_event();
360 if (event->type == GDK_BUTTON_RELEASE &&
361 ((GdkEventButton *) event)->button != 1)
363 filer_opendir(filer_window->sym_path, filer_window, NULL);
365 else if (!filer_window_delete(filer_window->window, NULL, filer_window))
366 gtk_widget_destroy(filer_window->window);
369 static void toolbar_up_clicked(GtkWidget *widget, FilerWindow *filer_window)
371 GdkEvent *event;
373 event = gtk_get_current_event();
374 if (event->type == GDK_BUTTON_RELEASE && NEW_WIN_BUTTON(event))
376 filer_open_parent(filer_window);
378 else
379 change_to_parent(filer_window);
382 static void toolbar_autosize_clicked(GtkWidget *widget, FilerWindow *filer_window)
384 GdkEventButton *bev;
386 bev = (GdkEventButton *) gtk_get_current_event();
387 if (bev->type != GDK_BUTTON_RELEASE)
388 return;
390 display_set_layout(filer_window, AUTO_SIZE_ICONS, filer_window->details_type,
391 TRUE);
394 static void toolbar_size_clicked(GtkWidget *widget, FilerWindow *filer_window)
396 GdkEventButton *bev;
398 bev = (GdkEventButton *) gtk_get_current_event();
399 if (bev->type != GDK_BUTTON_RELEASE)
400 return;
402 display_change_size(filer_window, bev->button == 1);
405 static void toolbar_sort_clicked(GtkWidget *widget,
406 FilerWindow *filer_window)
408 GdkEventButton *bev;
409 int i, current, next, next_wrapped;
410 gboolean adjust;
411 GtkSortType dir;
412 gchar *tip;
414 static const SortType sorts[]={
415 SORT_NAME, SORT_TYPE, SORT_DATE, SORT_SIZE,
416 SORT_OWNER, SORT_GROUP,
418 static const char *sort_names[] = {
419 N_("Sort by name"), N_("Sort by type"), N_("Sort by date"),
420 N_("Sort by size"), N_("Sort by owner"), N_("Sort by group"),
423 bev = (GdkEventButton *) gtk_get_current_event();
424 adjust = (bev->button != 1) && bev->type == GDK_BUTTON_RELEASE;
426 current = -1;
427 dir = filer_window->sort_order;
428 for (i=0; i < G_N_ELEMENTS(sort_names); i++)
430 if (filer_window->sort_type == sorts[i])
432 current = i;
433 break;
437 if (current == -1)
438 next = 0;
439 else if (adjust)
440 next = current - 1;
441 else
442 next = current + 1;
444 next_wrapped = next % G_N_ELEMENTS(sorts);
446 if (next_wrapped != next)
447 dir = (dir == GTK_SORT_ASCENDING)
448 ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING;
450 display_set_sort_type(filer_window, sorts[next_wrapped], dir);
451 tip = g_strconcat(_(sort_names[next_wrapped]), ", ",
452 dir == GTK_SORT_ASCENDING
453 ? _("ascending") : _("descending"),
454 NULL);
455 tooltip_show(tip);
456 g_free(tip);
459 static void toolbar_details_clicked(GtkWidget *widget,
460 FilerWindow *filer_window)
462 if (filer_window->view_type == VIEW_TYPE_DETAILS)
463 filer_set_view_type(filer_window, VIEW_TYPE_COLLECTION);
464 else
465 filer_set_view_type(filer_window, VIEW_TYPE_DETAILS);
468 static void toolbar_hidden_clicked(GtkWidget *widget,
469 FilerWindow *filer_window)
471 display_set_hidden(filer_window, !filer_window->show_hidden);
474 static gboolean invert_cb(ViewIter *iter, gpointer data)
476 return !view_get_selected((ViewIface *) data, iter);
479 static void toolbar_select_clicked(GtkWidget *widget, FilerWindow *filer_window)
481 GdkEvent *event;
483 event = gtk_get_current_event();
484 if (event->type == GDK_BUTTON_RELEASE)
486 if (((GdkEventButton *) event)->button == 1)
487 view_select_all(filer_window->view);
488 else
489 view_select_if(filer_window->view, invert_cb,
490 filer_window->view);
492 filer_window->temp_item_selected = FALSE;
495 /* If filer_window is NULL, the toolbar is for the options window */
496 static GtkWidget *create_toolbar(FilerWindow *filer_window)
498 GtkWidget *bar;
499 GtkWidget *b;
500 int i;
501 int width;
503 bar = gtk_toolbar_new();
505 if (o_toolbar.int_value == TOOLBAR_NORMAL || !filer_window)
506 gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_ICONS);
507 else if (o_toolbar.int_value == TOOLBAR_HORIZONTAL)
508 gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_BOTH_HORIZ);
509 else
510 gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_BOTH);
512 width=0;
513 for (i = 0; i < sizeof(all_tools) / sizeof(*all_tools); i++)
515 Tool *tool = &all_tools[i];
516 GtkRequisition req;
518 if (filer_window && !tool->enabled)
519 continue;
521 b = add_button(bar, tool, filer_window);
523 gtk_widget_size_request(b, &req);
524 width+=req.width;
526 if (filer_window && tool->drop_action != DROP_NONE)
527 handle_drops(filer_window, b, tool->drop_action);
530 if (filer_window)
532 if(o_toolbar_min_width.int_value)
534 /* Make the toolbar wide enough for all icons to be
535 seen, plus a little for the (start of the) text
536 label */
537 gtk_widget_set_size_request(bar, width+32, -1);
538 } else {
539 gtk_widget_set_size_request(bar, 100, -1);
542 filer_window->toolbar_text = gtk_label_new("");
543 gtk_misc_set_alignment(GTK_MISC(filer_window->toolbar_text),
544 0, 0.5);
545 gtk_toolbar_append_widget(GTK_TOOLBAR(bar),
546 filer_window->toolbar_text, NULL, NULL);
549 return bar;
552 /* This is used to simulate a click when button 3 is used (GtkButton
553 * normally ignores this).
555 static gint toolbar_other_button = 0;
556 static gint toolbar_button_pressed(GtkButton *button,
557 GdkEventButton *event,
558 FilerWindow *filer_window)
560 gint b = event->button;
561 Tool *tool;
563 tool = g_object_get_data(G_OBJECT(button), "rox-tool");
564 g_return_val_if_fail(tool != NULL, TRUE);
566 if (tool->menu && b == 1)
568 tool->clicked((GtkWidget *) button, filer_window);
569 return TRUE;
572 if ((b == 2 || b == 3) && toolbar_other_button == 0)
574 toolbar_other_button = event->button;
575 gtk_grab_add(GTK_WIDGET(button));
576 gtk_button_pressed(button);
578 return TRUE;
581 return FALSE;
584 static gint toolbar_button_released(GtkButton *button,
585 GdkEventButton *event,
586 FilerWindow *filer_window)
588 if (event->button == toolbar_other_button)
590 toolbar_other_button = 0;
591 gtk_grab_remove(GTK_WIDGET(button));
592 gtk_button_released(button);
594 return TRUE;
597 return FALSE;
600 /* If filer_window is NULL, the toolbar is for the options window */
601 static GtkWidget *add_button(GtkWidget *bar, Tool *tool,
602 FilerWindow *filer_window)
604 GtkWidget *button, *icon_widget;
606 icon_widget = gtk_image_new_from_stock(tool->name,
607 GTK_ICON_SIZE_LARGE_TOOLBAR);
609 button = gtk_toolbar_insert_element(GTK_TOOLBAR(bar),
610 filer_window ? GTK_TOOLBAR_CHILD_BUTTON
611 : GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
612 NULL,
613 _(tool->label),
614 _(tool->tip), NULL,
615 icon_widget,
616 NULL, NULL, /* CB, userdata */
617 GTK_TOOLBAR(bar)->num_children);
618 GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS);
620 if (o_toolbar.int_value == TOOLBAR_HORIZONTAL)
622 GtkWidget *hbox, *label;
623 GList *kids;
624 hbox = GTK_BIN(button)->child;
625 kids = gtk_container_get_children(GTK_CONTAINER(hbox));
626 label = g_list_nth_data(kids, 1);
627 g_list_free(kids);
629 if (label)
631 gtk_box_set_child_packing(GTK_BOX(hbox), label,
632 TRUE, TRUE, 0, GTK_PACK_END);
633 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
637 g_object_set_data(G_OBJECT(button), "rox-tool", tool);
639 if (filer_window)
641 g_signal_connect(button, "clicked",
642 G_CALLBACK(tool->clicked), filer_window);
643 g_signal_connect(button, "button_press_event",
644 G_CALLBACK(toolbar_button_pressed), filer_window);
645 g_signal_connect(button, "button_release_event",
646 G_CALLBACK(toolbar_button_released), filer_window);
648 else
650 g_signal_connect(button, "clicked",
651 G_CALLBACK(toggle_selected), NULL);
652 g_object_set_data(G_OBJECT(button), "tool_name",
653 (gpointer) tool->name);
656 return button;
659 static void toggle_selected(GtkToggleButton *widget, gpointer data)
661 option_check_widget(&o_toolbar_disable);
664 /* Called during the drag when the mouse is in a widget registered
665 * as a drop target. Returns TRUE if we can accept the drop.
667 static gboolean drag_motion(GtkWidget *widget,
668 GdkDragContext *context,
669 gint x,
670 gint y,
671 guint time,
672 FilerWindow *filer_window)
674 GdkDragAction action = context->suggested_action;
675 DropDest dest;
676 gpointer type = (gpointer) drop_dest_dir;
678 dest = (DropDest) g_object_get_data(G_OBJECT(widget), "toolbar_dest");
680 if ((context->actions & GDK_ACTION_ASK) && o_dnd_left_menu.int_value &&
681 dest != DROP_BOOKMARK)
683 guint state;
684 gdk_window_get_pointer(NULL, NULL, NULL, &state);
685 if (state & GDK_BUTTON1_MASK)
686 action = GDK_ACTION_ASK;
689 if (dest == DROP_TO_HOME)
690 g_dataset_set_data(context, "drop_dest_path",
691 (gchar *) home_dir);
692 else if (dest == DROP_BOOKMARK)
693 type = (gpointer) drop_dest_bookmark;
694 else
695 g_dataset_set_data_full(context, "drop_dest_path",
696 g_path_get_dirname(filer_window->sym_path),
697 g_free);
699 g_dataset_set_data(context, "drop_dest_type", type);
700 gdk_drag_status(context, action, time);
702 dnd_spring_load(context, filer_window);
703 gtk_button_set_relief(GTK_BUTTON(widget), GTK_RELIEF_NORMAL);
705 return TRUE;
708 static void drag_leave(GtkWidget *widget,
709 GdkDragContext *context,
710 guint32 time,
711 FilerWindow *filer_window)
713 gtk_button_set_relief(GTK_BUTTON(widget), GTK_RELIEF_NONE);
714 dnd_spring_abort();
717 static void handle_drops(FilerWindow *filer_window,
718 GtkWidget *button,
719 DropDest dest)
721 make_drop_target(button, 0);
722 g_signal_connect(button, "drag_motion",
723 G_CALLBACK(drag_motion), filer_window);
724 g_signal_connect(button, "drag_leave",
725 G_CALLBACK(drag_leave), filer_window);
726 g_object_set_data(G_OBJECT(button), "toolbar_dest", (gpointer) dest);
729 static void tally_items(gpointer key, gpointer value, gpointer data)
731 guchar *leafname = (guchar *) key;
732 int *tally = (int *) data;
734 if (!filer_match_filter(filer_window_being_counted, leafname))
735 (*tally)++;
738 static void option_notify(void)
740 int i;
741 gboolean changed = FALSE;
742 guchar *list = o_toolbar_disable.value;
744 for (i = 0; i < sizeof(all_tools) / sizeof(*all_tools); i++)
746 Tool *tool = &all_tools[i];
747 gboolean old = tool->enabled;
749 tool->enabled = !in_list(tool->name, list);
751 if (old != tool->enabled)
752 changed = TRUE;
755 if (changed || o_toolbar.has_changed || o_toolbar_info.has_changed)
757 GList *next;
759 for (next = all_filer_windows; next; next = next->next)
761 FilerWindow *filer_window = (FilerWindow *) next->data;
763 toolbar_update_toolbar(filer_window);
768 static void update_tools(Option *option)
770 GList *next, *kids;
772 kids = gtk_container_get_children(GTK_CONTAINER(option->widget));
774 for (next = kids; next; next = next->next)
776 GtkToggleButton *kid = (GtkToggleButton *) next->data;
777 guchar *name;
779 name = g_object_get_data(G_OBJECT(kid), "tool_name");
781 g_return_if_fail(name != NULL);
783 gtk_toggle_button_set_active(kid,
784 !in_list(name, option->value));
787 g_list_free(kids);
790 static guchar *read_tools(Option *option)
792 GList *next, *kids;
793 GString *list;
794 guchar *retval;
796 list = g_string_new(NULL);
798 kids = gtk_container_get_children(GTK_CONTAINER(option->widget));
800 for (next = kids; next; next = next->next)
802 GtkToggleButton *kid = (GtkToggleButton *) next->data;
803 guchar *name;
805 if (!gtk_toggle_button_get_active(kid))
807 name = g_object_get_data(G_OBJECT(kid), "tool_name");
808 g_return_val_if_fail(name != NULL, list->str);
810 if (list->len)
811 g_string_append(list, ", ");
812 g_string_append(list, name);
816 g_list_free(kids);
817 retval = list->str;
818 g_string_free(list, FALSE);
820 return retval;
823 static GList *build_tool_options(Option *option, xmlNode *node, guchar *label)
825 GtkWidget *bar;
827 g_return_val_if_fail(option != NULL, NULL);
829 bar = create_toolbar(NULL);
831 option->update_widget = update_tools;
832 option->read_widget = read_tools;
833 option->widget = bar;
835 return g_list_append(NULL, bar);