Converted README to markdown
[rox-filer.git] / ROX-Filer / src / toolbar.c
blob26c3436c06768491de4c7fbe0aef269488f0d0d7
1 /*
2 * ROX-Filer, filer for the ROX desktop project
3 * Copyright (C) 2006, Thomas Leonard and others (see changelog for details).
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place, Suite 330, Boston, MA 02111-1307 USA
20 /* toolbar.c - for the button bars that go along the tops of windows */
22 #include "config.h"
24 #include <string.h>
26 #include "global.h"
28 #include "toolbar.h"
29 #include "options.h"
30 #include "support.h"
31 #include "main.h"
32 #include "menu.h"
33 #include "dnd.h"
34 #include "filer.h"
35 #include "display.h"
36 #include "pixmaps.h"
37 #include "bind.h"
38 #include "type.h"
39 #include "dir.h"
40 #include "diritem.h"
41 #include "view_iface.h"
42 #include "bookmarks.h"
43 #include "gui_support.h"
45 typedef struct _Tool Tool;
47 typedef enum {DROP_NONE, DROP_TO_PARENT, DROP_TO_HOME, DROP_BOOKMARK} DropDest;
49 struct _Tool {
50 const gchar *label;
51 const gchar *name;
52 const gchar *tip; /* Tooltip */
53 void (*clicked)(GtkWidget *w, FilerWindow *filer_window);
54 DropDest drop_action;
55 gboolean enabled;
56 gboolean menu; /* Activate on button-press */
59 Option o_toolbar, o_toolbar_info, o_toolbar_disable;
60 Option o_toolbar_min_width;
62 static FilerWindow *filer_window_being_counted;
64 /* TRUE if the button presses (or released) should open a new window,
65 * rather than reusing the existing one.
67 #define NEW_WIN_BUTTON(button_event) \
68 (o_new_button_1.int_value \
69 ? ((GdkEventButton *) button_event)->button == 1 \
70 : ((GdkEventButton *) button_event)->button != 1)
72 /* Static prototypes */
73 static void toolbar_close_clicked(GtkWidget *widget, FilerWindow *filer_window);
74 static void toolbar_up_clicked(GtkWidget *widget, FilerWindow *filer_window);
75 static void toolbar_home_clicked(GtkWidget *widget, FilerWindow *filer_window);
76 static void toolbar_bookmarks_clicked(GtkWidget *widget,
77 FilerWindow *filer_window);
78 static void toolbar_help_clicked(GtkWidget *widget, FilerWindow *filer_window);
79 static void toolbar_refresh_clicked(GtkWidget *widget,
80 FilerWindow *filer_window);
81 static void toolbar_size_clicked(GtkWidget *widget, FilerWindow *filer_window);
82 static void toolbar_autosize_clicked(GtkWidget *widget, FilerWindow *filer_window);
83 static void toolbar_details_clicked(GtkWidget *widget,
84 FilerWindow *filer_window);
85 static void toolbar_hidden_clicked(GtkWidget *widget,
86 FilerWindow *filer_window);
87 static void toolbar_select_clicked(GtkWidget *widget,
88 FilerWindow *filer_window);
89 static void toolbar_sort_clicked(GtkWidget *widget,
90 FilerWindow *filer_window);
91 static GtkWidget *add_button(GtkWidget *bar, Tool *tool,
92 FilerWindow *filer_window);
93 static GtkWidget *create_toolbar(FilerWindow *filer_window);
94 static gboolean drag_motion(GtkWidget *widget,
95 GdkDragContext *context,
96 gint x,
97 gint y,
98 guint time,
99 FilerWindow *filer_window);
100 static void drag_leave(GtkWidget *widget,
101 GdkDragContext *context,
102 guint32 time,
103 FilerWindow *filer_window);
104 static void handle_drops(FilerWindow *filer_window,
105 GtkWidget *button,
106 DropDest dest);
107 static void toggle_selected(GtkToggleButton *widget, gpointer data);
108 static void option_notify(void);
109 static GList *build_tool_options(Option *option, xmlNode *node, guchar *label);
110 static void tally_items(gpointer key, gpointer value, gpointer data);
112 static Tool all_tools[] = {
113 {N_("Close"), GTK_STOCK_CLOSE, N_("Close filer window"),
114 toolbar_close_clicked, DROP_NONE, FALSE,
115 FALSE},
117 {N_("Up"), GTK_STOCK_GO_UP, N_("Change to parent directory"),
118 toolbar_up_clicked, DROP_TO_PARENT, TRUE,
119 FALSE},
121 {N_("Home"), GTK_STOCK_HOME, N_("Change to home directory"),
122 toolbar_home_clicked, DROP_TO_HOME, TRUE,
123 FALSE},
125 {N_("Bookmarks"), ROX_STOCK_BOOKMARKS, N_("Bookmarks menu"),
126 toolbar_bookmarks_clicked, DROP_BOOKMARK, FALSE,
127 TRUE},
129 {N_("Scan"), GTK_STOCK_REFRESH, N_("Rescan directory contents"),
130 toolbar_refresh_clicked, DROP_NONE, TRUE,
131 FALSE},
133 {N_("Size"), GTK_STOCK_ZOOM_IN, N_("Change icon size"),
134 toolbar_size_clicked, DROP_NONE, TRUE,
135 FALSE},
137 {N_("Size"), GTK_STOCK_ZOOM_FIT, N_("Automatic size mode"),
138 toolbar_autosize_clicked, DROP_NONE, TRUE,
139 FALSE},
141 {N_("Details"), ROX_STOCK_SHOW_DETAILS, N_("Show extra details"),
142 toolbar_details_clicked, DROP_NONE, TRUE,
143 FALSE},
145 {N_("Sort"), GTK_STOCK_SORT_ASCENDING, N_("Change sort criteria"),
146 toolbar_sort_clicked, DROP_NONE, FALSE,
147 FALSE},
149 {N_("Hidden"), ROX_STOCK_SHOW_HIDDEN, N_("Left: Show/hide hidden files\n"
150 "Right: Show/hide thumbnails"),
151 toolbar_hidden_clicked, DROP_NONE, TRUE,
152 FALSE},
154 {N_("Select"), ROX_STOCK_SELECT, N_("Select all/invert selection"),
155 toolbar_select_clicked, DROP_NONE, FALSE,
156 FALSE},
158 {N_("Help"), GTK_STOCK_HELP, N_("Show ROX-Filer help"),
159 toolbar_help_clicked, DROP_NONE, TRUE,
160 FALSE},
164 /****************************************************************
165 * EXTERNAL INTERFACE *
166 ****************************************************************/
168 void toolbar_init(void)
170 option_add_int(&o_toolbar, "toolbar_type", TOOLBAR_NORMAL);
171 option_add_int(&o_toolbar_info, "toolbar_show_info", 1);
172 option_add_string(&o_toolbar_disable, "toolbar_disable",
173 GTK_STOCK_CLOSE);
174 option_add_int(&o_toolbar_min_width, "toolbar_min_width", 1);
175 option_add_notify(option_notify);
177 option_register_widget("tool-options", build_tool_options);
180 void toolbar_update_info(FilerWindow *filer_window)
182 gchar *label;
183 ViewIface *view;
184 int n_selected;
186 g_return_if_fail(filer_window != NULL);
188 if (o_toolbar.int_value == TOOLBAR_NONE || !o_toolbar_info.int_value)
189 return; /* Not showing info */
191 if (filer_window->target_cb)
192 return;
194 view = filer_window->view;
196 n_selected = view_count_selected(view);
198 if (n_selected == 0)
200 gchar *s = NULL;
201 int n_items;
203 if (filer_window->scanning)
205 gtk_label_set_text(
206 GTK_LABEL(filer_window->toolbar_text), "");
207 return;
210 if (!(filer_window->show_hidden ||
211 filer_window->temp_show_hidden) ||
212 filer_window->filter!=FILER_SHOW_ALL)
214 GHashTable *hash = filer_window->directory->known_items;
215 int tally = 0;
217 filer_window_being_counted=filer_window;
218 g_hash_table_foreach(hash, tally_items, &tally);
220 if (tally)
221 s = g_strdup_printf(_(" (%u hidden)"), tally);
224 n_items = view_count_items(view);
226 if (n_items)
227 label = g_strdup_printf("%d %s%s",
228 n_items,
229 n_items != 1 ? _("items") : _("item"),
230 s ? s : "");
231 else /* (French plurals work differently for zero) */
232 label = g_strdup_printf(_("No items%s"),
233 s ? s : "");
234 g_free(s);
236 else
238 double size = 0;
239 ViewIter iter;
240 DirItem *item;
242 view_get_iter(filer_window->view, &iter, VIEW_ITER_SELECTED);
244 while ((item = iter.next(&iter)))
246 if (item->base_type != TYPE_DIRECTORY &&
247 item->base_type != TYPE_UNKNOWN)
248 size += (double) item->size;
251 label = g_strdup_printf(_("%u selected (%s)"),
252 n_selected, format_double_size(size));
255 gtk_label_set_text(GTK_LABEL(filer_window->toolbar_text), label);
256 g_free(label);
259 /* Create, destroy or recreate toolbar for this window so that it
260 * matches the option setting.
262 void toolbar_update_toolbar(FilerWindow *filer_window)
264 g_return_if_fail(filer_window != NULL);
266 if (filer_window->toolbar)
268 gtk_widget_destroy(filer_window->toolbar);
269 filer_window->toolbar = NULL;
270 filer_window->toolbar_text = NULL;
273 if (o_toolbar.int_value != TOOLBAR_NONE)
275 filer_window->toolbar = create_toolbar(filer_window);
276 gtk_box_pack_start(filer_window->toplevel_vbox,
277 filer_window->toolbar, FALSE, TRUE, 0);
278 gtk_box_reorder_child(filer_window->toplevel_vbox,
279 filer_window->toolbar, 0);
280 gtk_widget_show_all(filer_window->toolbar);
283 filer_target_mode(filer_window, NULL, NULL, NULL);
284 toolbar_update_info(filer_window);
287 /****************************************************************
288 * INTERNAL FUNCTIONS *
289 ****************************************************************/
291 /* Wrapper for gtk_get_current_event() which creates a fake release event
292 * if there is no current event. This is for ATK.
294 static GdkEvent *get_current_event(int default_type)
296 GdkEvent *event;
298 event = gtk_get_current_event();
300 if (event)
301 return event;
303 event = gdk_event_new(default_type);
304 if (default_type == GDK_BUTTON_PRESS || default_type == GDK_BUTTON_RELEASE)
306 GdkEventButton *bev;
307 bev = (GdkEventButton *) event;
308 bev->button = 1;
310 return event;
313 static void toolbar_help_clicked(GtkWidget *widget, FilerWindow *filer_window)
315 GdkEvent *event;
317 event = get_current_event(GDK_BUTTON_RELEASE);
318 if (event->type == GDK_BUTTON_RELEASE &&
319 ((GdkEventButton *) event)->button != 1)
320 menu_rox_help(NULL, HELP_MANUAL, NULL);
321 else
322 filer_opendir(make_path(app_dir, "Help"), NULL, NULL);
323 gdk_event_free(event);
326 static void toolbar_refresh_clicked(GtkWidget *widget,
327 FilerWindow *filer_window)
329 GdkEvent *event;
331 event = get_current_event(GDK_BUTTON_RELEASE);
332 if (event->type == GDK_BUTTON_RELEASE &&
333 ((GdkEventButton *) event)->button != 1)
335 filer_opendir(filer_window->sym_path, filer_window, NULL);
337 else
338 filer_refresh(filer_window);
339 gdk_event_free(event);
342 static void toolbar_home_clicked(GtkWidget *widget, FilerWindow *filer_window)
344 GdkEvent *event;
346 event = get_current_event(GDK_BUTTON_RELEASE);
347 if (event->type == GDK_BUTTON_RELEASE && NEW_WIN_BUTTON(event))
349 filer_opendir(home_dir, filer_window, NULL);
351 else
352 filer_change_to(filer_window, home_dir, NULL);
353 gdk_event_free(event);
356 static void toolbar_bookmarks_clicked(GtkWidget *widget,
357 FilerWindow *filer_window)
359 GdkEvent *event;
361 g_return_if_fail(filer_window != NULL);
363 event = get_current_event(GDK_BUTTON_PRESS);
364 if (event->type == GDK_BUTTON_PRESS &&
365 ((GdkEventButton *) event)->button == 1)
367 bookmarks_show_menu(filer_window);
369 else if (event->type == GDK_BUTTON_RELEASE &&
370 ((GdkEventButton *) event)->button != 1)
372 bookmarks_edit();
374 gdk_event_free(event);
377 static void toolbar_close_clicked(GtkWidget *widget, FilerWindow *filer_window)
379 GdkEvent *event;
381 g_return_if_fail(filer_window != NULL);
383 event = get_current_event(GDK_BUTTON_RELEASE);
384 if (event->type == GDK_BUTTON_RELEASE &&
385 ((GdkEventButton *) event)->button != 1)
387 filer_opendir(filer_window->sym_path, filer_window, NULL);
389 else if (!filer_window_delete(filer_window->window, NULL, filer_window))
390 gtk_widget_destroy(filer_window->window);
391 gdk_event_free(event);
394 static void toolbar_up_clicked(GtkWidget *widget, FilerWindow *filer_window)
396 GdkEvent *event;
398 event = get_current_event(GDK_BUTTON_RELEASE);
399 if (event->type == GDK_BUTTON_RELEASE && NEW_WIN_BUTTON(event))
401 filer_open_parent(filer_window);
403 else
404 change_to_parent(filer_window);
405 gdk_event_free(event);
408 static void toolbar_autosize_clicked(GtkWidget *widget, FilerWindow *filer_window)
410 GdkEventButton *bev;
412 bev = (GdkEventButton *) get_current_event(GDK_BUTTON_RELEASE);
413 if (bev->type == GDK_BUTTON_RELEASE)
415 display_set_layout(filer_window, AUTO_SIZE_ICONS, filer_window->details_type,
416 TRUE);
418 gdk_event_free((GdkEvent *) bev);
421 static void toolbar_size_clicked(GtkWidget *widget, FilerWindow *filer_window)
423 GdkEventButton *bev;
425 bev = (GdkEventButton *) get_current_event(GDK_BUTTON_RELEASE);
426 if (bev->type == GDK_BUTTON_RELEASE)
427 display_change_size(filer_window, bev->button == 1);
428 gdk_event_free((GdkEvent *) bev);
431 static void toolbar_sort_clicked(GtkWidget *widget,
432 FilerWindow *filer_window)
434 GdkEventButton *bev;
435 int i, current, next, next_wrapped;
436 gboolean adjust;
437 GtkSortType dir;
438 gchar *tip;
440 static const SortType sorts[]={
441 SORT_NAME, SORT_TYPE, SORT_DATE, SORT_SIZE,
442 SORT_OWNER, SORT_GROUP,
444 static const char *sort_names[] = {
445 N_("Sort by name"), N_("Sort by type"), N_("Sort by date"),
446 N_("Sort by size"), N_("Sort by owner"), N_("Sort by group"),
449 bev = (GdkEventButton *) get_current_event(GDK_BUTTON_RELEASE);
450 adjust = (bev->button != 1) && bev->type == GDK_BUTTON_RELEASE;
451 gdk_event_free((GdkEvent *) bev);
453 current = -1;
454 dir = filer_window->sort_order;
455 for (i=0; i < G_N_ELEMENTS(sort_names); i++)
457 if (filer_window->sort_type == sorts[i])
459 current = i;
460 break;
464 if (current == -1)
465 next = 0;
466 else if (adjust)
467 next = current - 1;
468 else
469 next = current + 1;
471 next_wrapped = next % G_N_ELEMENTS(sorts);
473 if (next_wrapped != next)
474 dir = (dir == GTK_SORT_ASCENDING)
475 ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING;
477 display_set_sort_type(filer_window, sorts[next_wrapped], dir);
478 tip = g_strconcat(_(sort_names[next_wrapped]), ", ",
479 dir == GTK_SORT_ASCENDING
480 ? _("ascending") : _("descending"),
481 NULL);
482 tooltip_show(tip);
483 g_free(tip);
486 static void toolbar_details_clicked(GtkWidget *widget,
487 FilerWindow *filer_window)
489 if (filer_window->view_type == VIEW_TYPE_DETAILS)
490 filer_set_view_type(filer_window, VIEW_TYPE_COLLECTION);
491 else
492 filer_set_view_type(filer_window, VIEW_TYPE_DETAILS);
495 static void toolbar_hidden_clicked(GtkWidget *widget,
496 FilerWindow *filer_window)
498 GdkEvent *event;
500 event = get_current_event(GDK_BUTTON_RELEASE);
501 if (event->type == GDK_BUTTON_RELEASE &&
502 ((GdkEventButton *) event)->button == 1)
504 display_set_hidden(filer_window, !filer_window->show_hidden);
506 else
508 display_set_thumbs(filer_window, !filer_window->show_thumbs);
512 static gboolean invert_cb(ViewIter *iter, gpointer data)
514 return !view_get_selected((ViewIface *) data, iter);
517 static void toolbar_select_clicked(GtkWidget *widget, FilerWindow *filer_window)
519 GdkEvent *event;
521 event = get_current_event(GDK_BUTTON_RELEASE);
522 if (event->type == GDK_BUTTON_RELEASE)
524 if (((GdkEventButton *) event)->button == 1)
525 view_select_all(filer_window->view);
526 else
527 view_select_if(filer_window->view, invert_cb,
528 filer_window->view);
530 filer_window->temp_item_selected = FALSE;
531 gdk_event_free(event);
534 /* If filer_window is NULL, the toolbar is for the options window */
535 static GtkWidget *create_toolbar(FilerWindow *filer_window)
537 GtkWidget *bar;
538 GtkWidget *b;
539 int i;
540 int width;
542 bar = gtk_toolbar_new();
544 if (o_toolbar.int_value == TOOLBAR_NORMAL || !filer_window)
545 gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_ICONS);
546 else if (o_toolbar.int_value == TOOLBAR_HORIZONTAL)
547 gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_BOTH_HORIZ);
548 else
549 gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_BOTH);
551 width=0;
552 for (i = 0; i < sizeof(all_tools) / sizeof(*all_tools); i++)
554 Tool *tool = &all_tools[i];
555 GtkRequisition req;
557 if (filer_window && !tool->enabled)
558 continue;
560 b = add_button(bar, tool, filer_window);
562 gtk_widget_size_request(b, &req);
563 width+=req.width;
565 if (filer_window && tool->drop_action != DROP_NONE)
566 handle_drops(filer_window, b, tool->drop_action);
569 if (filer_window)
571 if(o_toolbar_min_width.int_value)
573 /* Make the toolbar wide enough for all icons to be
574 seen, plus a little for the (start of the) text
575 label */
576 gtk_widget_set_size_request(bar, width+32, -1);
577 } else {
578 gtk_widget_set_size_request(bar, 100, -1);
581 filer_window->toolbar_text = gtk_label_new("");
582 gtk_misc_set_alignment(GTK_MISC(filer_window->toolbar_text),
583 0, 0.5);
584 gtk_toolbar_append_widget(GTK_TOOLBAR(bar),
585 filer_window->toolbar_text, NULL, NULL);
588 return bar;
591 /* This is used to simulate a click when button 3 is used (GtkButton
592 * normally ignores this).
594 static gint toolbar_other_button = 0;
595 static gint toolbar_button_pressed(GtkButton *button,
596 GdkEventButton *event,
597 FilerWindow *filer_window)
599 gint b = event->button;
600 Tool *tool;
602 tool = g_object_get_data(G_OBJECT(button), "rox-tool");
603 g_return_val_if_fail(tool != NULL, TRUE);
605 if (tool->menu && b == 1)
607 tool->clicked((GtkWidget *) button, filer_window);
608 return TRUE;
611 if ((b == 2 || b == 3) && toolbar_other_button == 0)
613 toolbar_other_button = event->button;
614 gtk_grab_add(GTK_WIDGET(button));
615 gtk_button_pressed(button);
617 return TRUE;
620 return FALSE;
623 static gint toolbar_button_released(GtkButton *button,
624 GdkEventButton *event,
625 FilerWindow *filer_window)
627 if (event->button == toolbar_other_button)
629 toolbar_other_button = 0;
630 gtk_grab_remove(GTK_WIDGET(button));
631 gtk_button_released(button);
633 return TRUE;
636 return FALSE;
639 /* If filer_window is NULL, the toolbar is for the options window */
640 static GtkWidget *add_button(GtkWidget *bar, Tool *tool,
641 FilerWindow *filer_window)
643 GtkWidget *button, *icon_widget;
645 icon_widget = gtk_image_new_from_stock(tool->name,
646 GTK_ICON_SIZE_LARGE_TOOLBAR);
648 button = gtk_toolbar_insert_element(GTK_TOOLBAR(bar),
649 filer_window ? GTK_TOOLBAR_CHILD_BUTTON
650 : GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
651 NULL,
652 _(tool->label),
653 _(tool->tip), NULL,
654 icon_widget,
655 NULL, NULL, /* CB, userdata */
656 GTK_TOOLBAR(bar)->num_children);
657 GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS);
659 if (o_toolbar.int_value == TOOLBAR_HORIZONTAL)
661 GtkWidget *hbox, *label;
662 GList *kids;
663 hbox = GTK_BIN(button)->child;
664 kids = gtk_container_get_children(GTK_CONTAINER(hbox));
665 label = g_list_nth_data(kids, 1);
666 g_list_free(kids);
668 if (label)
670 gtk_box_set_child_packing(GTK_BOX(hbox), label,
671 TRUE, TRUE, 0, GTK_PACK_END);
672 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
676 g_object_set_data(G_OBJECT(button), "rox-tool", tool);
678 if (filer_window)
680 g_signal_connect(button, "clicked",
681 G_CALLBACK(tool->clicked), filer_window);
682 g_signal_connect(button, "button_press_event",
683 G_CALLBACK(toolbar_button_pressed), filer_window);
684 g_signal_connect(button, "button_release_event",
685 G_CALLBACK(toolbar_button_released), filer_window);
687 else
689 g_signal_connect(button, "clicked",
690 G_CALLBACK(toggle_selected), NULL);
691 g_object_set_data(G_OBJECT(button), "tool_name",
692 (gpointer) tool->name);
695 return button;
698 static void toggle_selected(GtkToggleButton *widget, gpointer data)
700 option_check_widget(&o_toolbar_disable);
703 /* Called during the drag when the mouse is in a widget registered
704 * as a drop target. Returns TRUE if we can accept the drop.
706 static gboolean drag_motion(GtkWidget *widget,
707 GdkDragContext *context,
708 gint x,
709 gint y,
710 guint time,
711 FilerWindow *filer_window)
713 GdkDragAction action = context->suggested_action;
714 DropDest dest;
715 gpointer type = (gpointer) drop_dest_dir;
717 dest = (DropDest) g_object_get_data(G_OBJECT(widget), "toolbar_dest");
719 if ((context->actions & GDK_ACTION_ASK) && o_dnd_left_menu.int_value &&
720 dest != DROP_BOOKMARK)
722 guint state;
723 gdk_window_get_pointer(NULL, NULL, NULL, &state);
724 if (state & GDK_BUTTON1_MASK)
725 action = GDK_ACTION_ASK;
728 if (dest == DROP_TO_HOME)
729 g_dataset_set_data(context, "drop_dest_path",
730 (gchar *) home_dir);
731 else if (dest == DROP_BOOKMARK)
732 type = (gpointer) drop_dest_bookmark;
733 else
734 g_dataset_set_data_full(context, "drop_dest_path",
735 g_path_get_dirname(filer_window->sym_path),
736 g_free);
738 g_dataset_set_data(context, "drop_dest_type", type);
739 gdk_drag_status(context, action, time);
741 dnd_spring_load(context, filer_window);
742 gtk_button_set_relief(GTK_BUTTON(widget), GTK_RELIEF_NORMAL);
744 return TRUE;
747 static void drag_leave(GtkWidget *widget,
748 GdkDragContext *context,
749 guint32 time,
750 FilerWindow *filer_window)
752 gtk_button_set_relief(GTK_BUTTON(widget), GTK_RELIEF_NONE);
753 dnd_spring_abort();
756 static void handle_drops(FilerWindow *filer_window,
757 GtkWidget *button,
758 DropDest dest)
760 make_drop_target(button, 0);
761 g_signal_connect(button, "drag_motion",
762 G_CALLBACK(drag_motion), filer_window);
763 g_signal_connect(button, "drag_leave",
764 G_CALLBACK(drag_leave), filer_window);
765 g_object_set_data(G_OBJECT(button), "toolbar_dest", (gpointer) dest);
768 static void tally_items(gpointer key, gpointer value, gpointer data)
770 DirItem *item = (DirItem *) value;
771 int *tally = (int *) data;
773 if (!filer_match_filter(filer_window_being_counted, item))
774 (*tally)++;
777 static void option_notify(void)
779 int i;
780 gboolean changed = FALSE;
781 guchar *list = o_toolbar_disable.value;
783 for (i = 0; i < sizeof(all_tools) / sizeof(*all_tools); i++)
785 Tool *tool = &all_tools[i];
786 gboolean old = tool->enabled;
788 tool->enabled = !in_list(tool->name, list);
790 if (old != tool->enabled)
791 changed = TRUE;
794 if (changed || o_toolbar.has_changed || o_toolbar_info.has_changed)
796 GList *next;
798 for (next = all_filer_windows; next; next = next->next)
800 FilerWindow *filer_window = (FilerWindow *) next->data;
802 toolbar_update_toolbar(filer_window);
807 static void update_tools(Option *option)
809 GList *next, *kids;
811 kids = gtk_container_get_children(GTK_CONTAINER(option->widget));
813 for (next = kids; next; next = next->next)
815 GtkToggleButton *kid = (GtkToggleButton *) next->data;
816 guchar *name;
818 name = g_object_get_data(G_OBJECT(kid), "tool_name");
820 g_return_if_fail(name != NULL);
822 gtk_toggle_button_set_active(kid,
823 !in_list(name, option->value));
826 g_list_free(kids);
829 static guchar *read_tools(Option *option)
831 GList *next, *kids;
832 GString *list;
833 guchar *retval;
835 list = g_string_new(NULL);
837 kids = gtk_container_get_children(GTK_CONTAINER(option->widget));
839 for (next = kids; next; next = next->next)
841 GtkToggleButton *kid = (GtkToggleButton *) next->data;
842 guchar *name;
844 if (!gtk_toggle_button_get_active(kid))
846 name = g_object_get_data(G_OBJECT(kid), "tool_name");
847 g_return_val_if_fail(name != NULL, list->str);
849 if (list->len)
850 g_string_append(list, ", ");
851 g_string_append(list, name);
855 g_list_free(kids);
856 retval = list->str;
857 g_string_free(list, FALSE);
859 return retval;
862 static GList *build_tool_options(Option *option, xmlNode *node, guchar *label)
864 GtkWidget *bar;
866 g_return_val_if_fail(option != NULL, NULL);
868 bar = create_toolbar(NULL);
870 option->update_widget = update_tools;
871 option->read_widget = read_tools;
872 option->widget = bar;
874 return g_list_append(NULL, bar);