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>
25 #include <gdk/gdkkeysyms.h> /* GDK_* */
30 #include "rendering.h"
32 #include "mnemonics.h"
34 #include "next_image.h"
37 #include "math_floats.h"
38 #include "files_list.h"
40 #include "open_dialog.h"
43 #include "scrollbars.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
)
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
;
65 label
= children
->data
;
69 gtk_label_set_text_with_mnemonic(GTK_LABEL(label
), add_mnemonic(text
));
72 gtk_label_set_text(GTK_LABEL(label
), text
);
75 static GtkMenuShell
*add_menu(const gchar
* name
)
79 static gboolean first_time
= TRUE
;
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
));
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
;
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
);
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
);
157 TRANSFORMATION_MOVE_LEFT
,
158 TRANSFORMATION_MOVE_RIGHT
,
159 TRANSFORMATION_MOVE_UP
,
160 TRANSFORMATION_MOVE_DOWN
,
162 TRANSFORMATION_ROTATE_BIG_PLUS
,
163 TRANSFORMATION_ROTATE_BIG_MINUS
,
164 TRANSFORMATION_ROTATE_SMALL_PLUS
,
165 TRANSFORMATION_ROTATE_SMALL_MINUS
,
167 TRANSFORMATION_ZOOM_IN
,
168 TRANSFORMATION_ZOOM_OUT
,
169 TRANSFORMATION_FLIP_H
,
170 TRANSFORMATION_FLIP_V
,
174 static guchar
menu_move(guchar action
)
177 case TRANSFORMATION_MOVE_LEFT
:
178 matrix_move(MOVE_OFFSET
, 0.0);
181 case TRANSFORMATION_MOVE_RIGHT
:
182 matrix_move(-MOVE_OFFSET
, 0.0);
185 case TRANSFORMATION_MOVE_UP
:
186 matrix_move(0.0, MOVE_OFFSET
);
189 /* case TRANSFORMATION_MOVE_DOWN: */
191 matrix_move(0.0, -MOVE_OFFSET
);
194 return REFRESH_IMAGE
| APPEND_HISTORY
;
197 static guchar
menu_rotate(guchar action
)
200 case TRANSFORMATION_ROTATE_BIG_PLUS
:
201 matrix_rotate(BIG_ROTATION
);
204 case TRANSFORMATION_ROTATE_BIG_MINUS
:
205 matrix_rotate(-BIG_ROTATION
);
208 case TRANSFORMATION_ROTATE_SMALL_PLUS
:
209 matrix_rotate(SMALL_ROTATION
);
212 /* case TRANSFORMATION_ROTATE_SMALL_MINUS: */
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
);
230 zoom_in(1.0 / ZOOM_FACTOR
);
232 options
->zoom_pointer
= zoom_pointer
;
235 static void menu_transformation(guchar 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
);
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
);
254 case TRANSFORMATION_ZOOM_IN
:
255 case TRANSFORMATION_ZOOM_OUT
:
259 case TRANSFORMATION_FLIP_H
:
261 what
= REFRESH_IMAGE
| REFRESH_STATUS
| APPEND_HISTORY
;
264 case TRANSFORMATION_FLIP_V
:
266 what
= REFRESH_IMAGE
| REFRESH_STATUS
| APPEND_HISTORY
;
269 /* case TRANSFORMATION_RESET: */
272 what
= REFRESH_IMAGE
| REFRESH_STATUS
| APPEND_HISTORY
;
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) \
286 submenu = add_menu(str); \
288 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_group); \
291 /* Used to add an images menu. */
292 static GtkMenuItem
*add_special_menu(GtkAccelGroup
* accel_group
,
293 const gchar
* name
, GCallback rebuild_menu
)
296 GtkMenuShell
*submenu
;
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);
311 #define ADD_SPECIAL_MENU(str, cb) cb(add_special_menu(accel_group, str, \
314 GtkAccelGroup
*create_menus(void)
316 GtkMenuShell
*submenu
;
317 GtkAccelGroup
*accel_group
;
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");
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);
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
,
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,
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
);
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
);
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
));
444 ADD_MENU_ITEM(_("About..."), show_about_box
, 0, 0);
445 ADD_MENU_ITEM(_("Controls..."), toggle_help
, GDK_h
, 0);