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"
50 extern options_struct
*options
;
51 extern GtkMenuBar
*menu_bar
;
53 void set_menu_label(GtkMenuItem
* item
, const gchar
* text
, gboolean mnemonic
)
58 /* Find the label to change. */
59 children
= gtk_container_get_children(GTK_CONTAINER(item
));
60 while (children
!= NULL
&& GTK_IS_ACCEL_LABEL(children
->data
) == FALSE
)
61 children
= children
->next
;
66 label
= children
->data
;
70 gtk_label_set_text_with_mnemonic(GTK_LABEL(label
), add_mnemonic(text
));
73 gtk_label_set_text(GTK_LABEL(label
), text
);
76 static GtkMenuShell
*add_menu(const gchar
* name
)
80 static gboolean first_time
= TRUE
;
87 name
= add_mnemonic(name
);
88 item
= GTK_MENU_ITEM(gtk_menu_item_new_with_mnemonic(name
));
89 gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar
), GTK_WIDGET(item
));
91 menu
= GTK_MENU_SHELL(gtk_menu_new());
92 gtk_menu_shell_append(menu
, gtk_tearoff_menu_item_new());
93 gtk_menu_item_set_submenu(item
, GTK_WIDGET(menu
));
99 static GtkMenuItem
*add_menu_item(GtkMenuShell
* menu
,
100 GtkAccelGroup
* accel_group
,
101 const gchar
* menu_name
, const gchar
* name
,
102 GCallback func
, guint key
, gpointer data
)
104 GtkMenuItem
*menu_item
;
107 const gchar
*menu_item_name
;
109 menu_item_name
= add_mnemonic(name
);
110 menu_item
= GTK_MENU_ITEM(gtk_menu_item_new_with_mnemonic(menu_item_name
));
112 gtk_menu_shell_append(menu
, GTK_WIDGET(menu_item
));
113 g_signal_connect_swapped(menu_item
, "activate", func
, data
);
115 mod
= (key
>= GDK_A
&& key
<= GDK_Z
) ? GDK_SHIFT_MASK
: 0;
117 accel_path
= g_strconcat("<GLiv>/", menu_name
, "/", name
, NULL
);
118 gtk_accel_map_add_entry(accel_path
, key
, mod
);
119 gtk_menu_item_set_accel_path(menu_item
, accel_path
);
125 static void toggle_alpha_checks(void)
127 options
->alpha_checks
^= TRUE
;
128 refresh(REFRESH_IMAGE
);
131 static void menu_fullscreen(void)
133 toggle_fullscreen(!options
->fullscreen
);
136 #define MAXIMIZE (1 << 0)
137 #define SCALE_DOWN (1 << 1)
139 static void menu_maximize(gint what
)
141 gboolean old_maximize
, old_scale_down
;
143 old_maximize
= options
->maximize
;
144 old_scale_down
= options
->scaledown
;
146 options
->maximize
= ((what
& MAXIMIZE
) != 0);
147 options
->scaledown
= ((what
& SCALE_DOWN
) != 0);
149 matrix_set_max_zoom(-1, -1, TRUE
);
151 options
->maximize
= old_maximize
;
152 options
->scaledown
= old_scale_down
;
154 refresh(REFRESH_IMAGE
| REFRESH_STATUS
| APPEND_HISTORY
);
158 TRANSFORMATION_MOVE_LEFT
,
159 TRANSFORMATION_MOVE_RIGHT
,
160 TRANSFORMATION_MOVE_UP
,
161 TRANSFORMATION_MOVE_DOWN
,
163 TRANSFORMATION_ROTATE_BIG_PLUS
,
164 TRANSFORMATION_ROTATE_BIG_MINUS
,
165 TRANSFORMATION_ROTATE_SMALL_PLUS
,
166 TRANSFORMATION_ROTATE_SMALL_MINUS
,
168 TRANSFORMATION_ZOOM_IN
,
169 TRANSFORMATION_ZOOM_OUT
,
170 TRANSFORMATION_FLIP_H
,
171 TRANSFORMATION_FLIP_V
,
175 static guchar
menu_move(guchar action
)
178 case TRANSFORMATION_MOVE_LEFT
:
179 matrix_move(MOVE_OFFSET
, 0.0);
182 case TRANSFORMATION_MOVE_RIGHT
:
183 matrix_move(-MOVE_OFFSET
, 0.0);
186 case TRANSFORMATION_MOVE_UP
:
187 matrix_move(0.0, MOVE_OFFSET
);
190 /* case TRANSFORMATION_MOVE_DOWN: */
192 matrix_move(0.0, -MOVE_OFFSET
);
195 return REFRESH_IMAGE
| APPEND_HISTORY
;
198 static guchar
menu_rotate(guchar action
)
201 case TRANSFORMATION_ROTATE_BIG_PLUS
:
202 matrix_rotate(BIG_ROTATION
);
205 case TRANSFORMATION_ROTATE_BIG_MINUS
:
206 matrix_rotate(-BIG_ROTATION
);
209 case TRANSFORMATION_ROTATE_SMALL_PLUS
:
210 matrix_rotate(SMALL_ROTATION
);
213 /* case TRANSFORMATION_ROTATE_SMALL_MINUS: */
215 matrix_rotate(-SMALL_ROTATION
);
218 return REFRESH_IMAGE
| REFRESH_STATUS
| APPEND_HISTORY
;
221 static void menu_set_top_left(void)
223 matrix_set_top_left();
224 refresh(REFRESH_IMAGE
| APPEND_HISTORY
);
227 static void menu_zoom(guchar action
)
229 gboolean zoom_pointer
;
231 zoom_pointer
= options
->zoom_pointer
;
232 options
->zoom_pointer
= FALSE
;
234 if (action
== TRANSFORMATION_ZOOM_IN
)
235 zoom_in(ZOOM_FACTOR
);
237 zoom_in(1.0 / ZOOM_FACTOR
);
239 options
->zoom_pointer
= zoom_pointer
;
242 static void menu_transformation(guchar action
)
247 case TRANSFORMATION_MOVE_LEFT
:
248 case TRANSFORMATION_MOVE_RIGHT
:
249 case TRANSFORMATION_MOVE_UP
:
250 case TRANSFORMATION_MOVE_DOWN
:
251 what
= menu_move(action
);
254 case TRANSFORMATION_ROTATE_BIG_PLUS
:
255 case TRANSFORMATION_ROTATE_BIG_MINUS
:
256 case TRANSFORMATION_ROTATE_SMALL_PLUS
:
257 case TRANSFORMATION_ROTATE_SMALL_MINUS
:
258 what
= menu_rotate(action
);
261 case TRANSFORMATION_ZOOM_IN
:
262 case TRANSFORMATION_ZOOM_OUT
:
266 case TRANSFORMATION_FLIP_H
:
268 what
= REFRESH_IMAGE
| REFRESH_STATUS
| APPEND_HISTORY
;
271 case TRANSFORMATION_FLIP_V
:
273 what
= REFRESH_IMAGE
| REFRESH_STATUS
| APPEND_HISTORY
;
276 /* case TRANSFORMATION_RESET: */
279 what
= REFRESH_IMAGE
| REFRESH_STATUS
| APPEND_HISTORY
;
285 #define SEPARATOR gtk_menu_shell_append(submenu, gtk_separator_menu_item_new())
287 #define ADD_MENU_ITEM(str, signal_func, key, val) \
288 add_menu_item(submenu, accel_group, menu_name, str, \
289 G_CALLBACK(signal_func), key, GINT_TO_POINTER(val))
291 #define ADD_MENU(str) \
293 submenu = add_menu(str); \
295 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_group); \
298 /* Used to add an images menu. */
299 static GtkMenuItem
*add_special_menu(GtkAccelGroup
* accel_group
,
300 const gchar
* name
, GCallback rebuild_menu
)
303 GtkMenuShell
*submenu
;
305 gchar
*menu_name
= NULL
;
307 submenu
= add_menu(name
);
309 children
= gtk_container_get_children(GTK_CONTAINER(submenu
));
310 item
= GTK_MENU_ITEM(gtk_menu_get_attach_widget(GTK_MENU(submenu
)));
311 g_list_free(children
);
313 ADD_MENU_ITEM(_("Rebuild this menu"), rebuild_menu
, 0, 0);
318 #define ADD_SPECIAL_MENU(str, cb) cb(add_special_menu(accel_group, str, \
321 GtkAccelGroup
*create_menus(void)
323 GtkMenuShell
*submenu
;
324 GtkAccelGroup
*accel_group
;
328 menu_bar
= GTK_MENU_BAR(gtk_menu_bar_new());
329 accel_group
= gtk_accel_group_new();
331 gtk_settings_set_long_property(gtk_settings_get_default(),
332 "gtk-can-change-accels", 1, "GLiv");
337 ADD_MENU_ITEM(_("Open..."), menu_open
, GDK_o
, 0);
338 SEPARATOR
; /* ------------------------------------ */
339 ADD_MENU_ITEM(_("Load collection..."), deserialize_collection
, 0, 0);
340 ADD_MENU_ITEM(_("Save collection..."), serialize_collection
, 0, 0);
341 SEPARATOR
; /* ------------------------------------ */
342 ADD_MENU_ITEM(_("Quit"), gui_quit
, GDK_q
, 0);
346 ADD_MENU(_("Commands"));
347 ADD_MENU_ITEM(_("Move top left"), menu_set_top_left
, GDK_Home
, 0);
348 ADD_MENU_ITEM(_("Maximize small image"), menu_maximize
, GDK_M
, MAXIMIZE
);
349 ADD_MENU_ITEM(_("Scale down large image"), menu_maximize
, GDK_l
,
351 ADD_MENU_ITEM(_("Image fit window"), menu_maximize
, GDK_m
,
352 MAXIMIZE
| SCALE_DOWN
);
353 SEPARATOR
; /* ------------------------------------ */
354 ADD_MENU_ITEM(_("Horizontal flip"), menu_transformation
, GDK_z
,
355 TRANSFORMATION_FLIP_H
);
357 ADD_MENU_ITEM(_("Vertical flip"), menu_transformation
, GDK_e
,
358 TRANSFORMATION_FLIP_V
);
359 SEPARATOR
; /* ------------------------------------ */
360 ADD_MENU_ITEM(_("Load previous image"), load_direction
, GDK_p
, -1);
361 ADD_MENU_ITEM(_("Load next image"), load_direction
, GDK_n
, 1);
362 SEPARATOR
; /* ------------------------------------ */
363 ADD_MENU_ITEM(_("Rebuild images menus"), rebuild_images_menus
, 0, 0);
364 ADD_MENU_ITEM(_("Sort images list"), reorder_files
, 0, FALSE
);
365 item
= ADD_MENU_ITEM(_("Stop rebuilding the images menu"),
366 cancel_using_tree
, 0, 0);
367 set_stop_rebuilding_menu(item
);
369 ADD_MENU_ITEM(_("Shuffle images list"), reorder_files
, 0, TRUE
);
371 item
= ADD_MENU_ITEM(_("Start the slide show"), toggle_slide_show
, 0,
373 set_slide_show_menu(item
);
375 ADD_MENU_ITEM(_("Remove the current file"), confirm_remove_current
, GDK_x
,
378 /*************************/
379 /* Transformations menu. */
380 ADD_MENU(_("Transformations"));
381 ADD_MENU_ITEM(_("Undo"), undo
, GDK_u
, 0);
382 ADD_MENU_ITEM(_("Redo"), redo
, GDK_y
, 0);
383 ADD_MENU_ITEM(_("Clear history"), clear_history
, GDK_c
, 0);
384 SEPARATOR
; /* ------------------------------------ */
385 ADD_MENU_ITEM(_("Move left"), menu_transformation
, 0,
386 TRANSFORMATION_MOVE_LEFT
);
388 ADD_MENU_ITEM(_("Move right"), menu_transformation
, 0,
389 TRANSFORMATION_MOVE_RIGHT
);
391 ADD_MENU_ITEM(_("Move up"), menu_transformation
, 0, TRANSFORMATION_MOVE_UP
);
393 ADD_MENU_ITEM(_("Move down"), menu_transformation
, 0,
394 TRANSFORMATION_MOVE_DOWN
);
396 SEPARATOR
; /* ------------------------------------ */
398 ADD_MENU_ITEM(_("Rotate +45 deg"), menu_transformation
, 0,
399 TRANSFORMATION_ROTATE_BIG_PLUS
);
401 ADD_MENU_ITEM(_("Rotate -45 deg"), menu_transformation
, 0,
402 TRANSFORMATION_ROTATE_BIG_MINUS
);
404 ADD_MENU_ITEM(_("Rotate +0.1 deg"), menu_transformation
, 0,
405 TRANSFORMATION_ROTATE_SMALL_PLUS
);
407 ADD_MENU_ITEM(_("Rotate -0.1 deg"), menu_transformation
, 0,
408 TRANSFORMATION_ROTATE_SMALL_MINUS
);
410 SEPARATOR
; /* ------------------------------------ */
412 ADD_MENU_ITEM(_("Zoom in"), menu_transformation
, 0, TRANSFORMATION_ZOOM_IN
);
414 ADD_MENU_ITEM(_("Zoom out"), menu_transformation
, 0,
415 TRANSFORMATION_ZOOM_OUT
);
417 SEPARATOR
; /* ------------------------------------ */
419 ADD_MENU_ITEM(_("Reset"), menu_transformation
, GDK_r
, TRANSFORMATION_RESET
);
423 ADD_MENU(_("Options"));
424 ADD_MENU_ITEM(_("Toggle Fullscreen mode"), menu_fullscreen
, GDK_f
, 0);
425 ADD_MENU_ITEM(_("Toggle Menu Bar"), toggle_menu_bar
, GDK_b
, 0);
426 ADD_MENU_ITEM(_("Toggle Status Bar"), toggle_status_bar
, GDK_i
, 0);
427 ADD_MENU_ITEM(_("Toggle Scrollbars"), toggle_scrollbars
, GDK_s
, 0);
428 ADD_MENU_ITEM(_("Toggle Alpha checks"), toggle_alpha_checks
, GDK_a
, 0);
429 SEPARATOR
; /* ------------------------------------ */
430 ADD_MENU_ITEM(_("Hide the cursor"), hide_cursor
, GDK_d
, 0);
431 ADD_MENU_ITEM(_("Set this window as server"), start_server
, 0, 0);
432 SEPARATOR
; /* ------------------------------------ */
433 ADD_MENU_ITEM(_("Options..."), show_options
, GDK_t
, 0);
435 /*********************/
436 /* Directories menu. */
437 ADD_SPECIAL_MENU(_("Directories"), rebuild_directories
);
441 ADD_SPECIAL_MENU(_("Images"), rebuild_images
);
443 /*******************************/
444 /* Menus rebuilding indicator. */
445 item
= GTK_MENU_ITEM(gtk_menu_item_new_with_label(""));
446 set_rebuilding_entry(item
);
447 gtk_widget_set_sensitive(GTK_WIDGET(item
), FALSE
);
448 gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar
), GTK_WIDGET(item
));
453 ADD_MENU_ITEM(_("About..."), show_about_box
, 0, 0);
454 ADD_MENU_ITEM(_("Controls..."), toggle_help
, GDK_h
, 0);