4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2000, Thomas Leonard, <tal197@users.sourceforge.net>.
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)
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
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 */
40 typedef struct _Tool Tool
;
42 typedef enum {DROP_NONE
, DROP_TO_PARENT
, DROP_TO_HOME
} DropDest
;
47 guchar
*tip
; /* Tooltip */
48 void (*clicked
)(GtkWidget
*w
, FilerWindow
*filer_window
);
52 GtkWidget
**menu
; /* Right-click menu widget addr */
55 ToolbarType o_toolbar
= TOOLBAR_NORMAL
;
57 static GtkTooltips
*tooltips
= NULL
;
59 /* TRUE if the button presses (or released) should open a new window,
60 * rather than reusing the existing one.
62 #define NEW_WIN_BUTTON(button_event) \
63 (o_new_window_on_1 ? ((GdkEventButton *) button_event)->button == 1 \
64 : ((GdkEventButton *) button_event)->button != 1)
66 /* Static prototypes */
67 static void toolbar_close_clicked(GtkWidget
*widget
, FilerWindow
*filer_window
);
68 static void toolbar_up_clicked(GtkWidget
*widget
, FilerWindow
*filer_window
);
69 static void toolbar_home_clicked(GtkWidget
*widget
, FilerWindow
*filer_window
);
70 static void toolbar_help_clicked(GtkWidget
*widget
, FilerWindow
*filer_window
);
71 static void toolbar_refresh_clicked(GtkWidget
*widget
,
72 FilerWindow
*filer_window
);
73 static void toolbar_large_clicked(GtkWidget
*widget
, FilerWindow
*filer_window
);
74 static void toolbar_small_clicked(GtkWidget
*widget
, FilerWindow
*filer_window
);
75 static GtkWidget
*add_button(GtkWidget
*box
, Tool
*tool
,
76 FilerWindow
*filer_window
);
77 static GtkWidget
*create_toolbar(FilerWindow
*filer_window
);
78 static gboolean
drag_motion(GtkWidget
*widget
,
79 GdkDragContext
*context
,
83 FilerWindow
*filer_window
);
84 static void drag_leave(GtkWidget
*widget
,
85 GdkDragContext
*context
,
87 FilerWindow
*filer_window
);
88 static void handle_drops(FilerWindow
*filer_window
,
91 static void recreate_toolbar(FilerWindow
*filer_window
);
92 static void toggle_shaded(GtkWidget
*widget
);
93 static void option_notify(void);
95 static Tool all_tools
[] = {
96 {N_("Close"), "close", N_("Close filer window"),
97 toolbar_close_clicked
, DROP_NONE
, FALSE
,
100 {N_("Up"), "up", N_("Change to parent directory"),
101 toolbar_up_clicked
, DROP_TO_PARENT
, TRUE
,
104 {N_("Home"), "home", N_("Change to home directory"),
105 toolbar_home_clicked
, DROP_TO_HOME
, TRUE
,
108 {N_("Scan"), "refresh", N_("Rescan directory contents"),
109 toolbar_refresh_clicked
, DROP_NONE
, TRUE
,
112 {N_("Large"), "large", N_("Display using large icons"),
113 toolbar_large_clicked
, DROP_NONE
, TRUE
,
114 NULL
, &display_large_menu
},
116 {N_("Small"), "small", N_("Display using small icons"),
117 toolbar_small_clicked
, DROP_NONE
, TRUE
,
118 NULL
, &display_small_menu
},
120 {N_("Help"), "help", N_("Show ROX-Filer help"),
121 toolbar_help_clicked
, DROP_NONE
, TRUE
,
126 /****************************************************************
127 * EXTERNAL INTERFACE *
128 ****************************************************************/
130 void toolbar_init(void)
134 option_add_int("toolbar_type", o_toolbar
, NULL
);
135 option_add_string("toolbar_disable", "close", NULL
);
136 option_add_notify(option_notify
);
138 tooltips
= gtk_tooltips_new();
140 for (i
= 0; i
< sizeof(all_tools
) / sizeof(*all_tools
); i
++)
142 Tool
*tool
= &all_tools
[i
];
148 path
= g_strconcat("pixmaps/",
149 tool
->name
, ".xpm", NULL
);
150 tool
->icon
= load_pixmap(path
);
156 /* Returns a button which can be used to turn a tool on and off.
157 * Button has 'tool_name' set to the tool's name.
158 * NULL if tool number i is too big.
160 GtkWidget
*toolbar_tool_option(int i
)
162 Tool
*tool
= &all_tools
[i
];
164 GtkWidget
*icon_widget
, *vbox
, *text
;
166 g_return_val_if_fail(i
>= 0, NULL
);
168 if (i
>= sizeof(all_tools
) / sizeof(*all_tools
))
171 button
= gtk_button_new();
172 GTK_WIDGET_UNSET_FLAGS(button
, GTK_CAN_FOCUS
);
173 gtk_tooltips_set_tip(tooltips
, button
, _(tool
->tip
), NULL
);
175 icon_widget
= gtk_pixmap_new(tool
->icon
->pixmap
,
178 vbox
= gtk_vbox_new(FALSE
, 0);
179 gtk_box_pack_start(GTK_BOX(vbox
), icon_widget
, TRUE
, TRUE
, 0);
181 text
= gtk_label_new(_(tool
->label
));
182 gtk_box_pack_start(GTK_BOX(vbox
), text
, FALSE
, TRUE
, 0);
184 gtk_container_add(GTK_CONTAINER(button
), vbox
);
186 gtk_container_set_border_width(GTK_CONTAINER(button
), 1);
187 gtk_misc_set_padding(GTK_MISC(icon_widget
), 16, 1);
189 gtk_signal_connect_object(GTK_OBJECT(button
), "clicked",
190 GTK_SIGNAL_FUNC(toggle_shaded
), GTK_OBJECT(vbox
));
192 gtk_object_set_data(GTK_OBJECT(button
), "tool_name", tool
->name
);
197 /* Create a new toolbar widget, suitable for adding to a filer window,
200 GtkWidget
*toolbar_new(FilerWindow
*filer_window
)
202 g_return_val_if_fail(filer_window
!= NULL
, NULL
);
203 g_return_val_if_fail(o_toolbar
!= TOOLBAR_NONE
, NULL
);
205 return create_toolbar(filer_window
);
209 /****************************************************************
210 * INTERNAL FUNCTIONS *
211 ****************************************************************/
213 static void toolbar_help_clicked(GtkWidget
*widget
, FilerWindow
*filer_window
)
215 filer_opendir(make_path(app_dir
, "Help")->str
);
218 static void toolbar_refresh_clicked(GtkWidget
*widget
,
219 FilerWindow
*filer_window
)
223 event
= gtk_get_current_event();
224 if (event
->type
== GDK_BUTTON_RELEASE
&&
225 ((GdkEventButton
*) event
)->button
!= 1)
227 filer_opendir(filer_window
->path
);
232 filer_update_dir(filer_window
, TRUE
);
236 static void toolbar_home_clicked(GtkWidget
*widget
, FilerWindow
*filer_window
)
240 event
= gtk_get_current_event();
241 if (event
->type
== GDK_BUTTON_RELEASE
&& NEW_WIN_BUTTON(event
))
243 filer_opendir(home_dir
);
246 filer_change_to(filer_window
, home_dir
, NULL
);
249 static void toolbar_close_clicked(GtkWidget
*widget
, FilerWindow
*filer_window
)
253 g_return_if_fail(filer_window
!= NULL
);
255 event
= gtk_get_current_event();
256 if (event
->type
== GDK_BUTTON_RELEASE
&&
257 ((GdkEventButton
*) event
)->button
!= 1)
259 filer_opendir(filer_window
->path
);
262 gtk_widget_destroy(filer_window
->window
);
265 static void toolbar_up_clicked(GtkWidget
*widget
, FilerWindow
*filer_window
)
269 event
= gtk_get_current_event();
270 if (event
->type
== GDK_BUTTON_RELEASE
&& NEW_WIN_BUTTON(event
))
272 filer_open_parent(filer_window
);
275 change_to_parent(filer_window
);
278 static void toolbar_large_clicked(GtkWidget
*widget
, FilerWindow
*filer_window
)
280 display_set_layout(filer_window
, LARGE_ICONS
, DETAILS_NONE
);
283 static void toolbar_small_clicked(GtkWidget
*widget
, FilerWindow
*filer_window
)
285 display_set_layout(filer_window
, SMALL_ICONS
, DETAILS_NONE
);
288 static GtkWidget
*create_toolbar(FilerWindow
*filer_window
)
294 box
= gtk_hbox_new(FALSE
, 0);
296 for (i
= 0; i
< sizeof(all_tools
) / sizeof(*all_tools
); i
++)
298 Tool
*tool
= &all_tools
[i
];
303 b
= add_button(box
, tool
, filer_window
);
304 if (tool
->drop_action
!= DROP_NONE
)
305 handle_drops(filer_window
, b
, tool
->drop_action
);
308 filer_window
->toolbar_text
= gtk_label_new("");
309 gtk_box_pack_start(GTK_BOX(box
), filer_window
->toolbar_text
,
315 /* This is used to simulate a click when button 3 is used (GtkButton
316 * normally ignores this).
318 static gint toolbar_other_button
= 0;
319 static gint
toolbar_adjust_pressed(GtkButton
*button
,
320 GdkEventButton
*event
,
321 FilerWindow
*filer_window
)
323 gint b
= event
->button
;
325 if ((b
== 2 || b
== 3) && toolbar_other_button
== 0)
327 toolbar_other_button
= event
->button
;
328 gtk_grab_add(GTK_WIDGET(button
));
329 gtk_button_pressed(button
);
335 static gint
toolbar_adjust_released(GtkButton
*button
,
336 GdkEventButton
*event
,
337 FilerWindow
*filer_window
)
339 if (event
->button
== toolbar_other_button
)
341 toolbar_other_button
= 0;
342 gtk_grab_remove(GTK_WIDGET(button
));
343 gtk_button_released(button
);
349 static gint
menu_pressed(GtkWidget
*button
,
350 GdkEventButton
*event
,
351 FilerWindow
*filer_window
)
355 if (event
->button
!= 3 && event
->button
!= 2)
358 menu
= gtk_object_get_data(GTK_OBJECT(button
), "popup_menu");
359 g_return_val_if_fail(menu
!= NULL
, TRUE
);
361 show_style_menu(filer_window
, event
, menu
);
366 static GtkWidget
*add_button(GtkWidget
*box
, Tool
*tool
,
367 FilerWindow
*filer_window
)
369 GtkWidget
*button
, *icon_widget
;
370 GtkSignalFunc cb
= GTK_SIGNAL_FUNC(tool
->clicked
);
372 button
= gtk_button_new();
373 gtk_button_set_relief(GTK_BUTTON(button
), GTK_RELIEF_NONE
);
374 GTK_WIDGET_UNSET_FLAGS(button
, GTK_CAN_FOCUS
);
378 gtk_object_set_data(GTK_OBJECT(button
), "popup_menu",
380 gtk_signal_connect(GTK_OBJECT(button
), "button_press_event",
381 GTK_SIGNAL_FUNC(menu_pressed
), filer_window
);
385 gtk_signal_connect(GTK_OBJECT(button
), "button_press_event",
386 GTK_SIGNAL_FUNC(toolbar_adjust_pressed
), filer_window
);
387 gtk_signal_connect(GTK_OBJECT(button
), "button_release_event",
388 GTK_SIGNAL_FUNC(toolbar_adjust_released
), filer_window
);
391 gtk_signal_connect(GTK_OBJECT(button
), "clicked",
394 gtk_tooltips_set_tip(tooltips
, button
, _(tool
->tip
), NULL
);
396 icon_widget
= gtk_pixmap_new(tool
->icon
->pixmap
, tool
->icon
->mask
);
398 if (o_toolbar
== TOOLBAR_LARGE
)
400 GtkWidget
*vbox
, *text
;
402 vbox
= gtk_vbox_new(FALSE
, 0);
403 gtk_box_pack_start(GTK_BOX(vbox
), icon_widget
, TRUE
, TRUE
, 0);
405 text
= gtk_label_new(_(tool
->label
));
406 gtk_box_pack_start(GTK_BOX(vbox
), text
, FALSE
, TRUE
, 0);
408 gtk_container_add(GTK_CONTAINER(button
), vbox
);
411 gtk_container_add(GTK_CONTAINER(button
), icon_widget
);
413 gtk_container_set_border_width(GTK_CONTAINER(button
), 1);
414 gtk_misc_set_padding(GTK_MISC(icon_widget
),
415 o_toolbar
== TOOLBAR_LARGE
? 16 : 8, 1);
416 gtk_box_pack_start(GTK_BOX(box
), button
, FALSE
, TRUE
, 0);
421 static void toggle_shaded(GtkWidget
*widget
)
423 gtk_widget_set_sensitive(widget
, !GTK_WIDGET_SENSITIVE(widget
));
426 /* Called during the drag when the mouse is in a widget registered
427 * as a drop target. Returns TRUE if we can accept the drop.
429 static gboolean
drag_motion(GtkWidget
*widget
,
430 GdkDragContext
*context
,
434 FilerWindow
*filer_window
)
436 GdkDragAction action
= context
->suggested_action
;
439 dest
= (DropDest
) gtk_object_get_data(GTK_OBJECT(widget
),
442 if (dest
== DROP_TO_HOME
)
443 g_dataset_set_data(context
, "drop_dest_path", home_dir
);
446 guchar
*slash
, *path
;
448 slash
= strrchr(filer_window
->path
, '/');
449 if (slash
== NULL
|| slash
== filer_window
->path
)
450 path
= g_strdup("/");
452 path
= g_strndup(filer_window
->path
,
453 slash
- filer_window
->path
);
454 g_dataset_set_data_full(context
, "drop_dest_path",
458 g_dataset_set_data(context
, "drop_dest_type", drop_dest_dir
);
459 gdk_drag_status(context
, action
, time
);
461 dnd_spring_load(context
);
462 gtk_button_set_relief(GTK_BUTTON(widget
), GTK_RELIEF_NORMAL
);
467 static void drag_leave(GtkWidget
*widget
,
468 GdkDragContext
*context
,
470 FilerWindow
*filer_window
)
472 gtk_button_set_relief(GTK_BUTTON(widget
), GTK_RELIEF_NONE
);
476 static void handle_drops(FilerWindow
*filer_window
,
480 make_drop_target(button
, 0);
481 gtk_signal_connect(GTK_OBJECT(button
), "drag_motion",
482 GTK_SIGNAL_FUNC(drag_motion
), filer_window
);
483 gtk_signal_connect(GTK_OBJECT(button
), "drag_leave",
484 GTK_SIGNAL_FUNC(drag_leave
), filer_window
);
485 gtk_object_set_data(GTK_OBJECT(button
), "toolbar_dest",
489 static void recreate_toolbar(FilerWindow
*filer_window
)
491 GtkWidget
*frame
= filer_window
->toolbar_frame
;
493 if (GTK_BIN(frame
)->child
)
495 filer_window
->toolbar_text
= NULL
;
496 gtk_widget_destroy(((GtkBin
*) frame
)->child
);
499 if (o_toolbar
== TOOLBAR_NONE
)
500 gtk_widget_hide(frame
);
505 toolbar
= toolbar_new(filer_window
);
506 gtk_container_add(GTK_CONTAINER(filer_window
->toolbar_frame
),
508 gtk_widget_show_all(frame
);
511 filer_target_mode(filer_window
, NULL
, NULL
, NULL
);
514 static void option_notify(void)
516 ToolbarType old_type
= o_toolbar
;
519 gboolean changed
= FALSE
;
521 list
= option_get_static_string("toolbar_disable");
523 for (i
= 0; i
< sizeof(all_tools
) / sizeof(*all_tools
); i
++)
525 Tool
*tool
= &all_tools
[i
];
526 gboolean old
= tool
->enabled
;
528 tool
->enabled
= !in_list(tool
->name
, list
);
530 if (old
!= tool
->enabled
)
534 o_toolbar
= option_get_int("toolbar_type");
536 if (changed
|| old_type
!= o_toolbar
)
540 for (next
= all_filer_windows
; next
; next
= next
->next
)
542 FilerWindow
*filer_window
= (FilerWindow
*) next
->data
;
544 recreate_toolbar(filer_window
);