Better cut cursors and better chosen hot spots.
[gliv.git] / src / menus.c
blob9bab84fd08b4c73eba9014656112994310f60339
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * See the COPYING file for license information.
18 * Guillaume Chazarain <guichaz@yahoo.fr>
21 /***************
22 * The menubar *
23 ***************/
25 #include <gdk/gdkkeysyms.h> /* GDK_* */
27 #include "gliv.h"
28 #include "menus.h"
29 #include "options.h"
30 #include "rendering.h"
31 #include "rcfile.h"
32 #include "mnemonics.h"
33 #include "params.h"
34 #include "next_image.h"
35 #include "windows.h"
36 #include "matrix.h"
37 #include "math_floats.h"
38 #include "files_list.h"
39 #include "messages.h"
40 #include "open_dialog.h"
41 #include "main.h"
42 #include "history.h"
43 #include "scrollbars.h"
44 #include "cursors.h"
45 #include "help.h"
46 #include "images_menus.h"
47 #include "collection.h"
49 extern options_struct *options;
50 extern GtkMenuBar *menu_bar;
52 void set_menu_label(GtkMenuItem * item, const gchar * text, gboolean mnemonic)
54 GList *children;
55 GtkLabel *label;
57 /* Find the label to change. */
58 children = gtk_container_get_children(GTK_CONTAINER(item));
59 while (children != NULL && GTK_IS_ACCEL_LABEL(children->data) == FALSE)
60 children = children->next;
62 if (children == NULL)
63 return;
65 label = children->data;
67 if (mnemonic) {
68 push_mnemonics();
69 gtk_label_set_text_with_mnemonic(GTK_LABEL(label), add_mnemonic(text));
70 pop_mnemonics();
71 } else
72 gtk_label_set_text(GTK_LABEL(label), text);
75 static GtkMenuShell *add_menu(const gchar * name)
77 GtkMenuShell *menu;
78 GtkMenuItem *item;
79 static gboolean first_time = TRUE;
81 if (first_time)
82 reset_mnemonics();
83 else
84 pop_mnemonics();
86 name = add_mnemonic(name);
87 item = GTK_MENU_ITEM(gtk_menu_item_new_with_mnemonic(name));
88 gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), GTK_WIDGET(item));
90 menu = GTK_MENU_SHELL(gtk_menu_new());
91 gtk_menu_shell_append(menu, gtk_tearoff_menu_item_new());
92 gtk_menu_item_set_submenu(item, GTK_WIDGET(menu));
94 push_mnemonics();
95 return menu;
98 static GtkMenuItem *add_menu_item(GtkMenuShell * menu,
99 GtkAccelGroup * accel_group,
100 const gchar * menu_name, const gchar * name,
101 GCallback func, guint key, gpointer data)
103 GtkMenuItem *menu_item;
104 GdkModifierType mod;
105 gchar *accel_path;
106 const gchar *menu_item_name;
108 menu_item_name = add_mnemonic(name);
109 menu_item = GTK_MENU_ITEM(gtk_menu_item_new_with_mnemonic(menu_item_name));
111 gtk_menu_shell_append(menu, GTK_WIDGET(menu_item));
112 g_signal_connect_swapped(menu_item, "activate", func, data);
114 mod = (key >= GDK_A && key <= GDK_Z) ? GDK_SHIFT_MASK : 0;
116 accel_path = g_strconcat("<GLiv>/", menu_name, "/", name, NULL);
117 gtk_accel_map_add_entry(accel_path, key, mod);
118 gtk_menu_item_set_accel_path(menu_item, accel_path);
119 g_free(accel_path);
121 return menu_item;
124 static void toggle_alpha_checks(void)
126 options->alpha_checks ^= TRUE;
127 refresh(REFRESH_IMAGE);
130 static void menu_fullscreen(void)
132 toggle_fullscreen(!options->fullscreen);
135 #define MAXIMIZE (1 << 0)
136 #define SCALE_DOWN (1 << 1)
138 static void menu_maximize(gint what)
140 gboolean old_maximize, old_scale_down;
142 old_maximize = options->maximize;
143 old_scale_down = options->scaledown;
145 options->maximize = ((what & MAXIMIZE) != 0);
146 options->scaledown = ((what & SCALE_DOWN) != 0);
148 matrix_set_max_zoom(-1, -1, TRUE);
150 options->maximize = old_maximize;
151 options->scaledown = old_scale_down;
153 refresh(REFRESH_IMAGE | REFRESH_STATUS | APPEND_HISTORY);
156 enum {
157 TRANSFORMATION_MOVE_LEFT,
158 TRANSFORMATION_MOVE_RIGHT,
159 TRANSFORMATION_MOVE_UP,
160 TRANSFORMATION_MOVE_DOWN,
161 /* --- */
162 TRANSFORMATION_ROTATE_BIG_PLUS,
163 TRANSFORMATION_ROTATE_BIG_MINUS,
164 TRANSFORMATION_ROTATE_SMALL_PLUS,
165 TRANSFORMATION_ROTATE_SMALL_MINUS,
166 /* --- */
167 TRANSFORMATION_ZOOM_IN,
168 TRANSFORMATION_ZOOM_OUT,
169 TRANSFORMATION_FLIP_H,
170 TRANSFORMATION_FLIP_V,
171 TRANSFORMATION_RESET
174 static guchar menu_move(guchar action)
176 switch (action) {
177 case TRANSFORMATION_MOVE_LEFT:
178 matrix_move(MOVE_OFFSET, 0.0);
179 break;
181 case TRANSFORMATION_MOVE_RIGHT:
182 matrix_move(-MOVE_OFFSET, 0.0);
183 break;
185 case TRANSFORMATION_MOVE_UP:
186 matrix_move(0.0, MOVE_OFFSET);
187 break;
189 /* case TRANSFORMATION_MOVE_DOWN: */
190 default:
191 matrix_move(0.0, -MOVE_OFFSET);
194 return REFRESH_IMAGE | APPEND_HISTORY;
197 static guchar menu_rotate(guchar action)
199 switch (action) {
200 case TRANSFORMATION_ROTATE_BIG_PLUS:
201 matrix_rotate(BIG_ROTATION);
202 break;
204 case TRANSFORMATION_ROTATE_BIG_MINUS:
205 matrix_rotate(-BIG_ROTATION);
206 break;
208 case TRANSFORMATION_ROTATE_SMALL_PLUS:
209 matrix_rotate(SMALL_ROTATION);
210 break;
212 /* case TRANSFORMATION_ROTATE_SMALL_MINUS: */
213 default:
214 matrix_rotate(-SMALL_ROTATION);
217 return REFRESH_IMAGE | REFRESH_STATUS | APPEND_HISTORY;
220 static void menu_zoom(guchar action)
222 gboolean zoom_pointer;
224 zoom_pointer = options->zoom_pointer;
225 options->zoom_pointer = FALSE;
227 if (action == TRANSFORMATION_ZOOM_IN)
228 zoom_in(ZOOM_FACTOR);
229 else
230 zoom_in(1.0 / ZOOM_FACTOR);
232 options->zoom_pointer = zoom_pointer;
235 static void menu_transformation(guchar action)
237 gint what = 0;
239 switch (action) {
240 case TRANSFORMATION_MOVE_LEFT:
241 case TRANSFORMATION_MOVE_RIGHT:
242 case TRANSFORMATION_MOVE_UP:
243 case TRANSFORMATION_MOVE_DOWN:
244 what = menu_move(action);
245 break;
247 case TRANSFORMATION_ROTATE_BIG_PLUS:
248 case TRANSFORMATION_ROTATE_BIG_MINUS:
249 case TRANSFORMATION_ROTATE_SMALL_PLUS:
250 case TRANSFORMATION_ROTATE_SMALL_MINUS:
251 what = menu_rotate(action);
252 break;
254 case TRANSFORMATION_ZOOM_IN:
255 case TRANSFORMATION_ZOOM_OUT:
256 menu_zoom(action);
257 break;
259 case TRANSFORMATION_FLIP_H:
260 matrix_flip_h();
261 what = REFRESH_IMAGE | REFRESH_STATUS | APPEND_HISTORY;
262 break;
264 case TRANSFORMATION_FLIP_V:
265 matrix_flip_v();
266 what = REFRESH_IMAGE | REFRESH_STATUS | APPEND_HISTORY;
267 break;
269 /* case TRANSFORMATION_RESET: */
270 default:
271 matrix_reset();
272 what = REFRESH_IMAGE | REFRESH_STATUS | APPEND_HISTORY;
275 refresh(what);
278 #define SEPARATOR gtk_menu_shell_append(submenu, gtk_separator_menu_item_new())
280 #define ADD_MENU_ITEM(str, signal_func, key, val) \
281 add_menu_item(submenu, accel_group, menu_name, str, \
282 G_CALLBACK(signal_func), key, GINT_TO_POINTER(val))
284 #define ADD_MENU(str) \
285 do { \
286 submenu = add_menu(str); \
287 menu_name = str; \
288 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_group); \
289 } while (0)
291 /* Used to add an images menu. */
292 static GtkMenuItem *add_special_menu(GtkAccelGroup * accel_group,
293 const gchar * name, GCallback rebuild_menu)
295 GList *children;
296 GtkMenuShell *submenu;
297 GtkMenuItem *item;
298 gchar *menu_name = NULL;
300 submenu = add_menu(name);
302 children = gtk_container_get_children(GTK_CONTAINER(submenu));
303 item = GTK_MENU_ITEM(gtk_menu_get_attach_widget(GTK_MENU(submenu)));
304 g_list_free(children);
306 ADD_MENU_ITEM(_("Rebuild this menu"), rebuild_menu, 0, 0);
308 return item;
311 #define ADD_SPECIAL_MENU(str, cb) cb(add_special_menu(accel_group, str, \
312 G_CALLBACK(cb)))
314 GtkAccelGroup *create_menus(void)
316 GtkMenuShell *submenu;
317 GtkAccelGroup *accel_group;
318 GtkMenuItem *item;
319 gchar *menu_name;
321 menu_bar = GTK_MENU_BAR(gtk_menu_bar_new());
322 accel_group = gtk_accel_group_new();
324 gtk_settings_set_long_property(gtk_settings_get_default(),
325 "gtk-can-change-accels", 1, "GLiv");
327 /**************/
328 /* File menu. */
329 ADD_MENU(_("File"));
330 ADD_MENU_ITEM(_("Open..."), menu_open, GDK_o, 0);
331 SEPARATOR; /* ------------------------------------ */
332 ADD_MENU_ITEM(_("Load collection..."), deserialize_collection, 0, 0);
333 ADD_MENU_ITEM(_("Save collection..."), serialize_collection, 0, 0);
334 SEPARATOR; /* ------------------------------------ */
335 ADD_MENU_ITEM(_("Quit"), gui_quit, GDK_q, 0);
337 /******************/
338 /* Commands menu. */
339 ADD_MENU(_("Commands"));
340 ADD_MENU_ITEM(_("Maximize small image"), menu_maximize, GDK_M, MAXIMIZE);
341 ADD_MENU_ITEM(_("Scale down large image"), menu_maximize, GDK_l,
342 SCALE_DOWN);
343 ADD_MENU_ITEM(_("Image fit window"), menu_maximize, GDK_m,
344 MAXIMIZE | SCALE_DOWN);
345 SEPARATOR; /* ------------------------------------ */
346 ADD_MENU_ITEM(_("Horizontal flip"), menu_transformation, GDK_z,
347 TRANSFORMATION_FLIP_H);
349 ADD_MENU_ITEM(_("Vertical flip"), menu_transformation, GDK_e,
350 TRANSFORMATION_FLIP_V);
351 SEPARATOR; /* ------------------------------------ */
352 ADD_MENU_ITEM(_("Load previous image"), load_direction, GDK_p, -1);
353 ADD_MENU_ITEM(_("Load next image"), load_direction, GDK_n, 1);
354 SEPARATOR; /* ------------------------------------ */
355 ADD_MENU_ITEM(_("Rebuild images menus"), rebuild_images_menus, 0, 0);
356 ADD_MENU_ITEM(_("Sort images list"), reorder_files, 0, FALSE);
357 item = ADD_MENU_ITEM(_("Stop rebuilding the images menu"),
358 cancel_using_tree, 0, 0);
359 set_stop_rebuilding_menu(item);
361 ADD_MENU_ITEM(_("Shuffle images list"), reorder_files, 0, TRUE);
363 item = ADD_MENU_ITEM(_("Start the slide show"), toggle_slide_show, 0,
364 FALSE);
365 set_slide_show_menu(item);
367 ADD_MENU_ITEM(_("Remove the current file"), confirm_remove_current, GDK_x,
370 /*************************/
371 /* Transformations menu. */
372 ADD_MENU(_("Transformations"));
373 ADD_MENU_ITEM(_("Undo"), undo, GDK_u, 0);
374 ADD_MENU_ITEM(_("Redo"), redo, GDK_y, 0);
375 ADD_MENU_ITEM(_("Clear history"), clear_history, GDK_c, 0);
376 SEPARATOR; /* ------------------------------------ */
377 ADD_MENU_ITEM(_("Move left"), menu_transformation, 0,
378 TRANSFORMATION_MOVE_LEFT);
380 ADD_MENU_ITEM(_("Move right"), menu_transformation, 0,
381 TRANSFORMATION_MOVE_RIGHT);
383 ADD_MENU_ITEM(_("Move up"), menu_transformation, 0, TRANSFORMATION_MOVE_UP);
385 ADD_MENU_ITEM(_("Move down"), menu_transformation, 0,
386 TRANSFORMATION_MOVE_DOWN);
388 SEPARATOR; /* ------------------------------------ */
390 ADD_MENU_ITEM(_("Rotate +45 deg"), menu_transformation, 0,
391 TRANSFORMATION_ROTATE_BIG_PLUS);
393 ADD_MENU_ITEM(_("Rotate -45 deg"), menu_transformation, 0,
394 TRANSFORMATION_ROTATE_BIG_MINUS);
396 ADD_MENU_ITEM(_("Rotate +0.1 deg"), menu_transformation, 0,
397 TRANSFORMATION_ROTATE_SMALL_PLUS);
399 ADD_MENU_ITEM(_("Rotate -0.1 deg"), menu_transformation, 0,
400 TRANSFORMATION_ROTATE_SMALL_MINUS);
402 SEPARATOR; /* ------------------------------------ */
404 ADD_MENU_ITEM(_("Zoom in"), menu_transformation, 0, TRANSFORMATION_ZOOM_IN);
406 ADD_MENU_ITEM(_("Zoom out"), menu_transformation, 0,
407 TRANSFORMATION_ZOOM_OUT);
409 SEPARATOR; /* ------------------------------------ */
411 ADD_MENU_ITEM(_("Reset"), menu_transformation, GDK_r, TRANSFORMATION_RESET);
413 /*****************/
414 /* Options menu. */
415 ADD_MENU(_("Options"));
416 ADD_MENU_ITEM(_("Toggle Fullscreen mode"), menu_fullscreen, GDK_f, 0);
417 ADD_MENU_ITEM(_("Toggle Menu Bar"), toggle_menu_bar, GDK_b, 0);
418 ADD_MENU_ITEM(_("Toggle Status Bar"), toggle_status_bar, GDK_i, 0);
419 ADD_MENU_ITEM(_("Toggle Scrollbars"), toggle_scrollbars, GDK_s, 0);
420 ADD_MENU_ITEM(_("Toggle Alpha checks"), toggle_alpha_checks, GDK_a, 0);
421 SEPARATOR; /* ------------------------------------ */
422 ADD_MENU_ITEM(_("Hide the cursor"), hide_cursor, GDK_d, 0);
423 SEPARATOR; /* ------------------------------------ */
424 ADD_MENU_ITEM(_("Options..."), show_options, GDK_t, 0);
426 /*********************/
427 /* Directories menu. */
428 ADD_SPECIAL_MENU(_("Directories"), rebuild_directories);
430 /****************/
431 /* Images menu. */
432 ADD_SPECIAL_MENU(_("Images"), rebuild_images);
434 /*******************************/
435 /* Menus rebuilding indicator. */
436 item = GTK_MENU_ITEM(gtk_menu_item_new_with_label(""));
437 set_rebuilding_entry(item);
438 gtk_widget_set_sensitive(GTK_WIDGET(item), FALSE);
439 gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), GTK_WIDGET(item));
441 /**************/
442 /* Help menu. */
443 ADD_MENU(_("Help"));
444 ADD_MENU_ITEM(_("About..."), show_about_box, 0, 0);
445 ADD_MENU_ITEM(_("Controls..."), toggle_help, GDK_h, 0);
447 load_accelerators();
448 return accel_group;