Merge view_overlay_toggle() and layout_image_overlay_toggle() into new image_osd_togg...
[geeqie.git] / src / layout_image.c
1 /*
2  * Geeqie
3  * (C) 2006 John Ellis
4  * Copyright (C) 2008 The Geeqie Team
5  *
6  * Author: John Ellis
7  *
8  * This software is released under the GNU General Public License (GNU GPL).
9  * Please read the included file COPYING for more information.
10  * This software comes with no warranty of any kind, use at your own risk!
11  */
12
13 #include "main.h"
14 #include "layout_image.h"
15
16 #include "collect.h"
17 #include "dnd.h"
18 #include "editors.h"
19 #include "filelist.h"
20 #include "fullscreen.h"
21 #include "image.h"
22 #include "image-overlay.h"
23 #include "img-view.h"
24 #include "info.h"
25 #include "layout.h"
26 #include "layout_util.h"
27 #include "menu.h"
28 #include "pixbuf_util.h"
29 #include "utilops.h"
30 #include "slideshow.h"
31 #include "ui_bookmark.h"
32 #include "ui_fileops.h"
33 #include "ui_menu.h"
34
35 #include <gdk/gdkkeysyms.h> /* for keyboard values */
36
37
38 static GtkWidget *layout_image_pop_menu(LayoutWindow *lw);
39 static void layout_image_set_buttons(LayoutWindow *lw);
40
41 /*
42  *----------------------------------------------------------------------------
43  * full screen overlay
44  *----------------------------------------------------------------------------
45  */
46
47 void layout_image_overlay_toggle(LayoutWindow *lw)
48 {
49         if (!lw) return;
50         image_osd_toggle(lw->image);
51 }
52
53 void layout_image_overlay_update(LayoutWindow *lw)
54 {
55         if (!lw) return;
56
57         image_osd_update(lw->image);
58 }
59
60 /*
61  *----------------------------------------------------------------------------
62  * full screen
63  *----------------------------------------------------------------------------
64  */
65 #if 0
66 static void layout_image_fullscreen_menu_pos_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data)
67 {
68         LayoutWindow *lw = data;
69
70         if (!lw->full_screen) return;
71
72         gdk_window_get_origin(lw->full_screen->imd->pr->window, x, y);
73         popup_menu_position_clamp(menu, x, y, 0);
74 }
75
76 static void layout_image_full_screen_menu_popup(LayoutWindow *lw)
77 {
78         GtkWidget *menu;
79
80         menu = layout_image_pop_menu(lw);
81         gtk_menu_popup(GTK_MENU(menu), NULL, NULL, layout_image_fullscreen_menu_pos_cb, lw, 0, GDK_CURRENT_TIME);
82 }
83
84 /* this is handled by layout_key_press_cb */
85
86
87 static gint layout_image_full_screen_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
88 {
89         LayoutWindow *lw = data;
90         gint stop_signal;
91         gint x = 0;
92         gint y = 0;
93
94         stop_signal = TRUE;
95         switch (event->keyval)
96                 {
97                 case GDK_Left: case GDK_KP_Left:
98                         x -= 1;
99                         break;
100                 case GDK_Right: case GDK_KP_Right:
101                         x += 1;
102                         break;
103                 case GDK_Up: case GDK_KP_Up:
104                         y -= 1;
105                         break;
106                 case GDK_Down: case GDK_KP_Down:
107                         y += 1;
108                         break;
109                 default:
110                         stop_signal = FALSE;
111                         break;
112                 }
113
114         if (x != 0 || y!= 0)
115                 {
116                 if (event->state & GDK_SHIFT_MASK)
117                         {
118                         x *= 3;
119                         y *= 3;
120                         }
121
122                 keyboard_scroll_calc(&x, &y, event);
123                 layout_image_scroll(lw, x, y);
124                 }
125
126         if (stop_signal) return stop_signal;
127
128         if (event->state & GDK_CONTROL_MASK)
129                 {
130                 gint n = -1;
131
132                 stop_signal = TRUE;
133                 switch (event->keyval)
134                         {
135                         case '1':
136                                 n = 0;
137                                 break;
138                         case '2':
139                                 n = 1;
140                                 break;
141                         case '3':
142                                 n = 2;
143                                 break;
144                         case '4':
145                                 n = 3;
146                                 break;
147                         case '5':
148                                 n = 4;
149                                 break;
150                         case '6':
151                                 n = 5;
152                                 break;
153                         case '7':
154                                 n = 6;
155                                 break;
156                         case '8':
157                                 n = 7;
158                                 break;
159                         case '9':
160                                 n = 8;
161                                 break;
162                         case '0':
163                                 n = 9;
164                                 break;
165                         case 'C': case 'c':
166                                 file_util_copy(layout_image_get_fd(lw), NULL, NULL, widget);
167                                 break;
168                         case 'M': case 'm':
169                                 file_util_move(layout_image_get_fd(lw), NULL, NULL, widget);
170                                 break;
171                         case 'R': case 'r':
172                                 file_util_rename(layout_image_get_fd(lw), NULL, widget);
173                                 break;
174                         case 'D': case 'd':
175                                 file_util_delete(layout_image_get_fd(lw), NULL, widget);
176                                 break;
177                         case 'P': case 'p':
178                                 info_window_new(layout_image_get_fd(lw), NULL, NULL);
179                                 break;
180                         case 'Q': case 'q':
181                                 exit_program();
182                                 return FALSE;
183                                 break;
184                         default:
185                                 stop_signal = FALSE;
186                                 break;
187                         }
188                 if (n != -1)
189                         {
190                         if (!editor_window_flag_set(n))
191                                 {
192                                 layout_image_full_screen_stop(lw);
193                                 }
194                         start_editor_from_file(n, layout_image_get_fd(lw));
195                         }
196                 }
197         else if (event->state & GDK_SHIFT_MASK)
198                 {
199                 stop_signal = TRUE;
200                 switch (event->keyval)
201                         {
202                         case 'R': case 'r':
203                                 layout_image_alter(lw, ALTER_ROTATE_180);
204                                 break;
205                         case 'M': case 'm':
206                                 layout_image_alter(lw, ALTER_MIRROR);
207                                 break;
208                         case 'F': case 'f':
209                                 layout_image_alter(lw, ALTER_FLIP);
210                                 break;
211                         case 'G': case 'g':
212                                 layout_image_alter(lw, ALTER_DESATURATE);
213                                 break;
214                         default:
215                                 stop_signal = FALSE;
216                                 break;
217                         }
218                 }
219         else
220                 {
221                 stop_signal = TRUE;
222                 switch (event->keyval)
223                         {
224                         case '+': case '=': case GDK_KP_Add:
225                                 layout_image_zoom_adjust(lw, get_zoom_increment());
226                                 break;
227                         case '-': case GDK_KP_Subtract:
228                                 layout_image_zoom_adjust(lw, -get_zoom_increment());
229                                 break;
230                         case 'X': case 'x': case GDK_KP_Multiply:
231                                 layout_image_zoom_set(lw, 0.0);
232                                 break;
233                         case 'Z': case 'z': case GDK_KP_Divide:
234                         case '1':
235                                 layout_image_zoom_set(lw, 1.0);
236                                 break;
237                         case '2':
238                                 layout_image_zoom_set(lw, 2.0);
239                                 break;
240                         case '3':
241                                 layout_image_zoom_set(lw, 3.0);
242                                 break;
243                         case '4':
244                                 layout_image_zoom_set(lw, 4.0);
245                                 break;
246                         case '7':
247                                 layout_image_zoom_set(lw, -4.0);
248                                 break;
249                         case '8':
250                                 layout_image_zoom_set(lw, -3.0);
251                                 break;
252                         case '9':
253                                 layout_image_zoom_set(lw, -2.0);
254                                 break;
255                         case 'W': case 'w':
256                                 layout_image_zoom_set_fill_geometry(lw, FALSE);
257                                 break;
258                         case 'H': case 'h':
259                                 layout_image_zoom_set_fill_geometry(lw, TRUE);
260                                 break;
261                         case GDK_Page_Up: case GDK_KP_Page_Up:
262                         case GDK_BackSpace:
263                         case 'B': case 'b':
264                                 layout_image_prev(lw);
265                                 break;
266                         case GDK_Page_Down: case GDK_KP_Page_Down:
267                         case GDK_space:
268                         case 'N': case 'n':
269                                 layout_image_next(lw);
270                                 break;
271                         case GDK_Home: case GDK_KP_Home:
272                                 layout_image_first(lw);
273                                 break;
274                         case GDK_End: case GDK_KP_End:
275                                 layout_image_last(lw);
276                                 break;
277                         case ']':
278                                 layout_image_alter(lw, ALTER_ROTATE_90);
279                                 break;
280                         case '[':
281                                 layout_image_alter(lw, ALTER_ROTATE_90_CC);
282                                 break;
283                         case GDK_Delete: case GDK_KP_Delete:
284                                 if (enable_delete_key)
285                                         {
286                                         file_util_delete(layout_image_get_fd(lw), NULL, widget);
287                                         }
288                                 break;
289                         case GDK_Escape:
290                                 layout_image_full_screen_stop(lw);
291                                 break;
292                         case 'R': case 'r':
293                                 layout_refresh(lw);
294                                 break;
295                         case 'S': case 's':
296                                 layout_image_slideshow_toggle(lw);
297                                 break;
298                         case 'P': case 'p':
299                                 layout_image_slideshow_pause_toggle(lw);
300                                 break;
301                         case 'F': case 'f':
302                         case 'V': case 'v':
303                         case GDK_F11:
304                                 layout_image_full_screen_stop(lw);
305                                 break;
306                         case GDK_Menu:
307                         case GDK_F10:
308                                 layout_image_full_screen_menu_popup(lw);
309                                 break;
310                         case 'I': case 'i':
311                                 layout_image_overlay_toggle(lw);
312                                 break;
313                         default:
314                                 stop_signal = FALSE;
315                                 break;
316                         }
317                 }
318
319         return stop_signal;
320 }
321
322 #endif
323
324 static void layout_image_full_screen_stop_func(FullScreenData *fs, gpointer data)
325 {
326         LayoutWindow *lw = data;
327
328         /* restore image window */
329         lw->image = fs->normal_imd;
330
331         if (lw->slideshow)
332                 {
333                 lw->slideshow->imd = lw->image;
334                 }
335
336         lw->full_screen = NULL;
337 }
338
339 void layout_image_full_screen_start(LayoutWindow *lw)
340 {
341         if (!layout_valid(&lw)) return;
342
343         if (lw->full_screen) return;
344
345         lw->full_screen = fullscreen_start(lw->window, lw->image,
346                                            layout_image_full_screen_stop_func, lw);
347
348         /* set to new image window */
349         lw->image = lw->full_screen->imd;
350
351         if (lw->slideshow)
352                 {
353                 lw->slideshow->imd = lw->image;
354                 }
355
356         layout_image_set_buttons(lw);
357
358         g_signal_connect(G_OBJECT(lw->full_screen->window), "key_press_event",
359                          G_CALLBACK(layout_key_press_cb), lw);
360
361         layout_actions_add_window(lw, lw->full_screen->window);
362 #if 0
363         gtk_widget_set_sensitive(lw->window, FALSE);
364         if (lw->tools) gtk_widget_set_sensitive(lw->tools, FALSE);
365 #endif
366
367         if (image_osd_get(lw->full_screen->normal_imd, NULL, NULL))
368                 {
369                 image_osd_set(lw->image, TRUE, TRUE);
370                 image_osd_set(lw->full_screen->normal_imd, FALSE, FALSE);
371                 }
372 }
373
374 void layout_image_full_screen_stop(LayoutWindow *lw)
375 {
376         if (!layout_valid(&lw)) return;
377         if (!lw->full_screen) return;
378
379         if (image_osd_get(lw->image, NULL, NULL))
380                 {
381                 image_osd_set(lw->full_screen->normal_imd, FALSE, TRUE);
382                 }
383         fullscreen_stop(lw->full_screen);
384
385 #if 0
386         gtk_widget_set_sensitive(lw->window, TRUE);
387         if (lw->tools) gtk_widget_set_sensitive(lw->tools, TRUE);
388 #endif
389 }
390
391 void layout_image_full_screen_toggle(LayoutWindow *lw)
392 {
393         if (!layout_valid(&lw)) return;
394         if (lw->full_screen)
395                 {
396                 layout_image_full_screen_stop(lw);
397                 }
398         else
399                 {
400                 layout_image_full_screen_start(lw);
401                 }
402 }
403
404 gint layout_image_full_screen_active(LayoutWindow *lw)
405 {
406         if (!layout_valid(&lw)) return FALSE;
407
408         return (lw->full_screen != NULL);
409 }
410
411 /*
412  *----------------------------------------------------------------------------
413  * slideshow
414  *----------------------------------------------------------------------------
415  */
416
417 static void layout_image_slideshow_next(LayoutWindow *lw)
418 {
419         if (lw->slideshow) slideshow_next(lw->slideshow);
420 }
421
422 static void layout_image_slideshow_prev(LayoutWindow *lw)
423 {
424         if (lw->slideshow) slideshow_prev(lw->slideshow);
425 }
426
427 static void layout_image_slideshow_stop_func(SlideShowData *ss, gpointer data)
428 {
429         LayoutWindow *lw = data;
430
431         lw->slideshow = NULL;
432         layout_status_update_info(lw, NULL);
433 }
434
435 void layout_image_slideshow_start(LayoutWindow *lw)
436 {
437         CollectionData *cd;
438         CollectInfo *info;
439
440         if (!layout_valid(&lw)) return;
441         if (lw->slideshow) return;
442
443         cd = image_get_collection(lw->image, &info);
444
445         if (cd && info)
446                 {
447                 lw->slideshow = slideshow_start_from_collection(lw->image, cd,
448                                 layout_image_slideshow_stop_func, lw, info);
449                 }
450         else
451                 {
452                 lw->slideshow = slideshow_start(lw->image, lw,
453                                 layout_list_get_index(lw, layout_image_get_path(lw)),
454                                 layout_image_slideshow_stop_func, lw);
455                 }
456
457         layout_status_update_info(lw, NULL);
458 }
459
460 /* note that slideshow will take ownership of the list, do not free it */
461 void layout_image_slideshow_start_from_list(LayoutWindow *lw, GList *list)
462 {
463         if (!layout_valid(&lw)) return;
464
465         if (lw->slideshow || !list)
466                 {
467                 filelist_free(list);
468                 return;
469                 }
470
471         lw->slideshow = slideshow_start_from_filelist(lw->image, list,
472                                                        layout_image_slideshow_stop_func, lw);
473
474         layout_status_update_info(lw, NULL);
475 }
476
477 void layout_image_slideshow_stop(LayoutWindow *lw)
478 {
479         if (!layout_valid(&lw)) return;
480
481         if (!lw->slideshow) return;
482
483         slideshow_free(lw->slideshow);
484         /* the stop_func sets lw->slideshow to NULL for us */
485 }
486
487 void layout_image_slideshow_toggle(LayoutWindow *lw)
488 {
489         if (!layout_valid(&lw)) return;
490
491         if (lw->slideshow)
492                 {
493                 layout_image_slideshow_stop(lw);
494                 }
495         else
496                 {
497                 layout_image_slideshow_start(lw);
498                 }
499 }
500
501 gint layout_image_slideshow_active(LayoutWindow *lw)
502 {
503         if (!layout_valid(&lw)) return FALSE;
504
505         return (lw->slideshow != NULL);
506 }
507
508 gint layout_image_slideshow_pause_toggle(LayoutWindow *lw)
509 {
510         gint ret;
511
512         if (!layout_valid(&lw)) return FALSE;
513
514         ret = slideshow_pause_toggle(lw->slideshow);
515
516         layout_status_update_info(lw, NULL);
517
518         return ret;
519 }
520
521 gint layout_image_slideshow_paused(LayoutWindow *lw)
522 {
523         if (!layout_valid(&lw)) return FALSE;
524
525         return (slideshow_paused(lw->slideshow));
526 }
527
528 static gint layout_image_slideshow_continue_check(LayoutWindow *lw)
529 {
530         if (!lw->slideshow) return FALSE;
531
532         if (!slideshow_should_continue(lw->slideshow))
533                 {
534                 layout_image_slideshow_stop(lw);
535                 return FALSE;
536                 }
537
538         return TRUE;
539 }
540
541 /*
542  *----------------------------------------------------------------------------
543  * pop-up menus
544  *----------------------------------------------------------------------------
545  */
546
547 static void li_pop_menu_zoom_in_cb(GtkWidget *widget, gpointer data)
548 {
549         LayoutWindow *lw = data;
550
551         layout_image_zoom_adjust(lw, get_zoom_increment());
552 }
553
554 static void li_pop_menu_zoom_out_cb(GtkWidget *widget, gpointer data)
555 {
556         LayoutWindow *lw = data;
557         layout_image_zoom_adjust(lw, -get_zoom_increment());
558 }
559
560 static void li_pop_menu_zoom_1_1_cb(GtkWidget *widget, gpointer data)
561 {
562         LayoutWindow *lw = data;
563
564         layout_image_zoom_set(lw, 1.0);
565 }
566
567 static void li_pop_menu_zoom_fit_cb(GtkWidget *widget, gpointer data)
568 {
569         LayoutWindow *lw = data;
570
571         layout_image_zoom_set(lw, 0.0);
572 }
573
574 static void li_pop_menu_edit_cb(GtkWidget *widget, gpointer data)
575 {
576         LayoutWindow *lw;
577         gint n;
578
579         lw = submenu_item_get_data(widget);
580         n = GPOINTER_TO_INT(data);
581
582         if (!editor_window_flag_set(n))
583                 {
584                 layout_image_full_screen_stop(lw);
585                 }
586         start_editor_from_file(n, layout_image_get_fd(lw));
587 }
588
589 static void li_pop_menu_wallpaper_cb(GtkWidget *widget, gpointer data)
590 {
591         LayoutWindow *lw = data;
592
593         layout_image_to_root(lw);
594 }
595
596 static void li_pop_menu_alter_cb(GtkWidget *widget, gpointer data)
597 {
598         LayoutWindow *lw = data;
599         AlterType type;
600
601         lw = submenu_item_get_data(widget);
602         type = (AlterType)GPOINTER_TO_INT(data);
603
604         image_alter(lw->image, type);
605 }
606
607 static void li_pop_menu_info_cb(GtkWidget *widget, gpointer data)
608 {
609         LayoutWindow *lw = data;
610
611         info_window_new(layout_image_get_fd(lw), NULL, lw->full_screen ? lw->full_screen->window : NULL);
612 }
613
614 static void li_pop_menu_new_cb(GtkWidget *widget, gpointer data)
615 {
616         LayoutWindow *lw = data;
617
618         view_window_new(layout_image_get_fd(lw));
619 }
620
621 static GtkWidget *li_pop_menu_click_parent(GtkWidget *widget, LayoutWindow *lw)
622 {
623         GtkWidget *menu;
624         GtkWidget *parent;
625
626         menu = gtk_widget_get_toplevel(widget);
627         if (!menu) return NULL;
628
629         parent = g_object_get_data(G_OBJECT(menu), "click_parent");
630
631         if (!parent && lw->full_screen)
632                 {
633                 parent = lw->full_screen->imd->widget;
634                 }
635
636         return parent;
637 }
638
639 static void li_pop_menu_copy_cb(GtkWidget *widget, gpointer data)
640 {
641         LayoutWindow *lw = data;
642
643         file_util_copy(layout_image_get_fd(lw), NULL, NULL,
644                        li_pop_menu_click_parent(widget, lw));
645 }
646
647 static void li_pop_menu_move_cb(GtkWidget *widget, gpointer data)
648 {
649         LayoutWindow *lw = data;
650
651         file_util_move(layout_image_get_fd(lw), NULL, NULL,
652                        li_pop_menu_click_parent(widget, lw));
653 }
654
655 static void li_pop_menu_rename_cb(GtkWidget *widget, gpointer data)
656 {
657         LayoutWindow *lw = data;
658
659         file_util_rename(layout_image_get_fd(lw), NULL,
660                          li_pop_menu_click_parent(widget, lw));
661 }
662
663 static void li_pop_menu_delete_cb(GtkWidget *widget, gpointer data)
664 {
665         LayoutWindow *lw = data;
666
667         file_util_delete(layout_image_get_fd(lw), NULL,
668                          li_pop_menu_click_parent(widget, lw));
669 }
670
671 static void li_pop_menu_slide_start_cb(GtkWidget *widget, gpointer data)
672 {
673         LayoutWindow *lw = data;
674
675         layout_image_slideshow_start(lw);
676 }
677
678 static void li_pop_menu_slide_stop_cb(GtkWidget *widget, gpointer data)
679 {
680         LayoutWindow *lw = data;
681
682         layout_image_slideshow_stop(lw);
683 }
684
685 static void li_pop_menu_slide_pause_cb(GtkWidget *widget, gpointer data)
686 {
687         LayoutWindow *lw = data;
688
689         layout_image_slideshow_pause_toggle(lw);
690 }
691
692 static void li_pop_menu_full_screen_cb(GtkWidget *widget, gpointer data)
693 {
694         LayoutWindow *lw = data;
695
696         layout_image_full_screen_toggle(lw);
697 }
698
699 static void li_pop_menu_hide_cb(GtkWidget *widget, gpointer data)
700 {
701         LayoutWindow *lw = data;
702
703         layout_tools_hide_toggle(lw);
704 }
705
706 static void li_set_layout_path_cb(GtkWidget *widget, gpointer data)
707 {
708         LayoutWindow *lw = data;
709         const gchar *path;
710
711         if (!layout_valid(&lw)) return;
712
713         path = layout_image_get_path(lw);
714         if (path) layout_set_path(lw, path);
715 }
716
717 static gint li_check_if_current_path(LayoutWindow *lw, const gchar *path)
718 {
719         gchar *dirname;
720         gint ret;
721
722         if (!path || !layout_valid(&lw) || !lw->path) return FALSE;
723
724         dirname = g_path_get_dirname(path);
725         ret = (strcmp(lw->path, dirname) == 0);
726         g_free(dirname);
727         return ret;
728 }
729
730 static GtkWidget *layout_image_pop_menu(LayoutWindow *lw)
731 {
732         GtkWidget *menu;
733         GtkWidget *item;
734         GtkWidget *submenu;
735         const gchar *path;
736         gint fullscreen;
737
738         path = layout_image_get_path(lw);
739         fullscreen = layout_image_full_screen_active(lw);
740
741         menu = popup_menu_short_lived();
742
743         menu_item_add_stock(menu, _("Zoom _in"), GTK_STOCK_ZOOM_IN, G_CALLBACK(li_pop_menu_zoom_in_cb), lw);
744         menu_item_add_stock(menu, _("Zoom _out"), GTK_STOCK_ZOOM_OUT, G_CALLBACK(li_pop_menu_zoom_out_cb), lw);
745         menu_item_add_stock(menu, _("Zoom _1:1"), GTK_STOCK_ZOOM_100, G_CALLBACK(li_pop_menu_zoom_1_1_cb), lw);
746         menu_item_add_stock(menu, _("Fit image to _window"), GTK_STOCK_ZOOM_FIT, G_CALLBACK(li_pop_menu_zoom_fit_cb), lw);
747         menu_item_add_divider(menu);
748
749         submenu = submenu_add_edit(menu, &item, G_CALLBACK(li_pop_menu_edit_cb), lw);
750         if (!path) gtk_widget_set_sensitive(item, FALSE);
751         menu_item_add_divider(submenu);
752         menu_item_add(submenu, _("Set as _wallpaper"), G_CALLBACK(li_pop_menu_wallpaper_cb), lw);
753
754         item = submenu_add_alter(menu, G_CALLBACK(li_pop_menu_alter_cb), lw);
755
756         item = menu_item_add_stock(menu, _("_Properties"), GTK_STOCK_PROPERTIES, G_CALLBACK(li_pop_menu_info_cb), lw);
757         if (!path) gtk_widget_set_sensitive(item, FALSE);
758
759         item = menu_item_add_stock(menu, _("View in _new window"), GTK_STOCK_NEW, G_CALLBACK(li_pop_menu_new_cb), lw);
760         if (!path || fullscreen) gtk_widget_set_sensitive(item, FALSE);
761
762         item = menu_item_add(menu, _("_Go to directory view"), G_CALLBACK(li_set_layout_path_cb), lw);
763         if (!path || li_check_if_current_path(lw, path)) gtk_widget_set_sensitive(item, FALSE);
764
765         menu_item_add_divider(menu);
766
767         item = menu_item_add_stock(menu, _("_Copy..."), GTK_STOCK_COPY, G_CALLBACK(li_pop_menu_copy_cb), lw);
768         if (!path) gtk_widget_set_sensitive(item, FALSE);
769         item = menu_item_add(menu, _("_Move..."), G_CALLBACK(li_pop_menu_move_cb), lw);
770         if (!path) gtk_widget_set_sensitive(item, FALSE);
771         item = menu_item_add(menu, _("_Rename..."), G_CALLBACK(li_pop_menu_rename_cb), lw);
772         if (!path) gtk_widget_set_sensitive(item, FALSE);
773         item = menu_item_add_stock(menu, _("_Delete..."), GTK_STOCK_DELETE, G_CALLBACK(li_pop_menu_delete_cb), lw);
774         if (!path) gtk_widget_set_sensitive(item, FALSE);
775
776         menu_item_add_divider(menu);
777
778         if (layout_image_slideshow_active(lw))
779                 {
780                 menu_item_add(menu, _("_Stop slideshow"), G_CALLBACK(li_pop_menu_slide_stop_cb), lw);
781                 if (layout_image_slideshow_paused(lw))
782                         {
783                         item = menu_item_add(menu, _("Continue slides_how"),
784                                              G_CALLBACK(li_pop_menu_slide_pause_cb), lw);
785                         }
786                 else
787                         {
788                         item = menu_item_add(menu, _("Pause slides_how"),
789                                              G_CALLBACK(li_pop_menu_slide_pause_cb), lw);
790                         }
791                 }
792         else
793                 {
794                 menu_item_add(menu, _("_Start slideshow"), G_CALLBACK(li_pop_menu_slide_start_cb), lw);
795                 item = menu_item_add(menu, _("Pause slides_how"), G_CALLBACK(li_pop_menu_slide_pause_cb), lw);
796                 gtk_widget_set_sensitive(item, FALSE);
797                 }
798
799         if (!fullscreen)
800                 {
801                 menu_item_add(menu, _("_Full screen"), G_CALLBACK(li_pop_menu_full_screen_cb), lw);
802                 }
803         else
804                 {
805                 menu_item_add(menu, _("Exit _full screen"), G_CALLBACK(li_pop_menu_full_screen_cb), lw);
806                 }
807
808         menu_item_add_divider(menu);
809
810         item = menu_item_add_check(menu, _("Hide file _list"), lw->tools_hidden,
811                                    G_CALLBACK(li_pop_menu_hide_cb), lw);
812         if (fullscreen) gtk_widget_set_sensitive(item, FALSE);
813
814         return menu;
815 }
816
817 static void layout_image_menu_pos_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data)
818 {
819         LayoutWindow *lw = data;
820
821         gdk_window_get_origin(lw->image->pr->window, x, y);
822         popup_menu_position_clamp(menu, x, y, 0);
823 }
824
825 void layout_image_menu_popup(LayoutWindow *lw)
826 {
827         GtkWidget *menu;
828
829         menu = layout_image_pop_menu(lw);
830         gtk_menu_popup(GTK_MENU(menu), NULL, NULL, layout_image_menu_pos_cb, lw, 0, GDK_CURRENT_TIME);
831 }
832
833 /*
834  *----------------------------------------------------------------------------
835  * dnd
836  *----------------------------------------------------------------------------
837  */
838
839 static void layout_image_dnd_receive(GtkWidget *widget, GdkDragContext *context,
840                                      gint x, gint y,
841                                      GtkSelectionData *selection_data, guint info,
842                                      guint time, gpointer data)
843 {
844         LayoutWindow *lw = data;
845         gint i;
846
847
848         for (i=0; i < MAX_SPLIT_IMAGES; i++)
849                 {
850                 if (lw->split_images[i] && lw->split_images[i]->pr == widget)
851                         break;
852                 }
853         if (i < MAX_SPLIT_IMAGES)
854                 {
855                 if (debug) printf("dnd image activate %d\n", i);
856                 layout_image_activate(lw, i);
857                 }
858
859
860         if (info == TARGET_URI_LIST || info == TARGET_APP_COLLECTION_MEMBER)
861                 {
862                 CollectionData *source;
863                 GList *list;
864                 GList *info_list;
865
866                 if (info == TARGET_URI_LIST)
867                         {
868                         list = uri_filelist_from_text((gchar *)selection_data->data, TRUE);
869                         source = NULL;
870                         info_list = NULL;
871                         }
872                 else
873                         {
874                         source = collection_from_dnd_data((gchar *)selection_data->data, &list, &info_list);
875                         }
876
877                 if (list)
878                         {
879                         FileData *fd = list->data;
880
881                         if (isfile(fd->path))
882                                 {
883                                 gchar *base;
884                                 gint row;
885
886                                 base = remove_level_from_path(fd->path);
887                                 if (strcmp(base, layout_get_path(lw)) != 0)
888                                         {
889                                         layout_set_path(lw, base);
890                                         }
891                                 g_free(base);
892
893                                 row = layout_list_get_index(lw, fd->path);
894                                 if (source && info_list)
895                                         {
896                                         layout_image_set_collection(lw, source, info_list->data);
897                                         }
898                                 else if (row == -1)
899                                         {
900                                         layout_image_set_fd(lw, fd);
901                                         }
902                                 else
903                                         {
904                                         layout_image_set_index(lw, row);
905                                         }
906                                 }
907                         else if (isdir(fd->path))
908                                 {
909                                 layout_set_path(lw, fd->path);
910                                 layout_image_set_fd(lw, NULL);
911                                 }
912                         }
913
914                 filelist_free(list);
915                 g_list_free(info_list);
916                 }
917 }
918
919 static void layout_image_dnd_get(GtkWidget *widget, GdkDragContext *context,
920                                  GtkSelectionData *selection_data, guint info,
921                                  guint time, gpointer data)
922 {
923         LayoutWindow *lw = data;
924         FileData *fd;
925         gint i;
926
927
928         for (i=0; i < MAX_SPLIT_IMAGES; i++)
929                 {
930                 if (lw->split_images[i] && lw->split_images[i]->pr == widget)
931                         break;
932                 }
933         if (i < MAX_SPLIT_IMAGES)
934                 {
935                 if (debug) printf("dnd get from %d\n", i);
936                 fd = image_get_fd(lw->split_images[i]);
937                 }
938         else
939                 fd = layout_image_get_fd(lw);
940
941         if (fd)
942                 {
943                 gchar *text = NULL;
944                 gint len;
945                 gint plain_text;
946                 GList *list;
947
948                 switch (info)
949                         {
950                         case TARGET_URI_LIST:
951                                 plain_text = FALSE;
952                                 break;
953                         case TARGET_TEXT_PLAIN:
954                         default:
955                                 plain_text = TRUE;
956                                 break;
957                         }
958                 list = g_list_append(NULL, fd);
959                 text = uri_text_from_filelist(list, &len, plain_text);
960                 g_list_free(list);
961                 if (text)
962                         {
963                         gtk_selection_data_set (selection_data, selection_data->target,
964                                                 8, (guchar *)text, len);
965                         g_free(text);
966                         }
967                 }
968         else
969                 {
970                 gtk_selection_data_set (selection_data, selection_data->target,
971                                         8, NULL, 0);
972                 }
973 }
974
975 static void layout_image_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
976 {
977         LayoutWindow *lw = data;
978         if (context->action == GDK_ACTION_MOVE)
979                 {
980                 const gchar *path;
981                 gint row;
982
983                 path = layout_image_get_path(lw);
984                 row = layout_list_get_index(lw, path);
985                 if (row < 0) return;
986
987                 if (!isfile(path))
988                         {
989                         if (row < layout_list_count(lw, NULL) - 1)
990                                 {
991                                 layout_image_next(lw);
992                                 }
993                         else
994                                 {
995                                 layout_image_prev(lw);
996                                 }
997                         }
998                 layout_refresh(lw);
999                 }
1000 }
1001
1002 static void layout_image_dnd_init(LayoutWindow *lw, gint i)
1003 {
1004         ImageWindow *imd = lw->split_images[i];
1005
1006         gtk_drag_source_set(imd->pr, GDK_BUTTON2_MASK,
1007                             dnd_file_drag_types, dnd_file_drag_types_count,
1008                             GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
1009         g_signal_connect(G_OBJECT(imd->pr), "drag_data_get",
1010                          G_CALLBACK(layout_image_dnd_get), lw);
1011         g_signal_connect(G_OBJECT(imd->pr), "drag_end",
1012                          G_CALLBACK(layout_image_dnd_end), lw);
1013
1014         gtk_drag_dest_set(imd->pr,
1015                           GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
1016                           dnd_file_drop_types, dnd_file_drop_types_count,
1017                           GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
1018         g_signal_connect(G_OBJECT(imd->pr), "drag_data_received",
1019                          G_CALLBACK(layout_image_dnd_receive), lw);
1020 }
1021
1022
1023 /*
1024  *----------------------------------------------------------------------------
1025  * misc
1026  *----------------------------------------------------------------------------
1027  */
1028
1029 void layout_image_to_root(LayoutWindow *lw)
1030 {
1031         image_to_root_window(lw->image, (image_zoom_get(lw->image) == 0));
1032 }
1033
1034 /*
1035  *----------------------------------------------------------------------------
1036  * manipulation + accessors
1037  *----------------------------------------------------------------------------
1038  */
1039
1040 void layout_image_scroll(LayoutWindow *lw, gint x, gint y)
1041 {
1042         if (!layout_valid(&lw)) return;
1043
1044         image_scroll(lw->image, x, y);
1045 }
1046
1047 void layout_image_zoom_adjust(LayoutWindow *lw, gdouble increment)
1048 {
1049         gint i;
1050         if (!layout_valid(&lw)) return;
1051
1052         image_zoom_adjust(lw->image, increment);
1053
1054         for (i=0; i < MAX_SPLIT_IMAGES; i++)
1055                 {
1056                 if (lw->split_images[i] && lw->split_images[i] != lw->image && lw->connect_zoom)
1057                         image_zoom_adjust(lw->split_images[i], increment); ;
1058                 }
1059 }
1060
1061 void layout_image_zoom_set(LayoutWindow *lw, gdouble zoom)
1062 {
1063         gint i;
1064         if (!layout_valid(&lw)) return;
1065
1066         image_zoom_set(lw->image, zoom);
1067
1068         for (i=0; i < MAX_SPLIT_IMAGES; i++)
1069                 {
1070                 if (lw->split_images[i] && lw->split_images[i] != lw->image && lw->connect_zoom)
1071                         image_zoom_set(lw->split_images[i], zoom);
1072                 }
1073 }
1074
1075 void layout_image_zoom_set_fill_geometry(LayoutWindow *lw, gint vertical)
1076 {
1077         if (!layout_valid(&lw)) return;
1078
1079         image_zoom_set_fill_geometry(lw->image, vertical);
1080 }
1081
1082 void layout_image_alter(LayoutWindow *lw, AlterType type)
1083 {
1084         if (!layout_valid(&lw)) return;
1085
1086         image_alter(lw->image, type);
1087 }
1088
1089 const gchar *layout_image_get_path(LayoutWindow *lw)
1090 {
1091         if (!layout_valid(&lw)) return NULL;
1092
1093         return image_get_path(lw->image);
1094 }
1095
1096 const gchar *layout_image_get_name(LayoutWindow *lw)
1097 {
1098         if (!layout_valid(&lw)) return NULL;
1099
1100         return image_get_name(lw->image);
1101 }
1102
1103 FileData *layout_image_get_fd(LayoutWindow *lw)
1104 {
1105         if (!layout_valid(&lw)) return NULL;
1106
1107         return image_get_fd(lw->image);
1108 }
1109
1110 CollectionData *layout_image_get_collection(LayoutWindow *lw, CollectInfo **info)
1111 {
1112         if (!layout_valid(&lw)) return NULL;
1113
1114         return image_get_collection(lw->image, info);
1115 }
1116
1117 gint layout_image_get_index(LayoutWindow *lw)
1118 {
1119         return layout_list_get_index(lw, image_get_path(lw->image));
1120 }
1121
1122 /*
1123  *----------------------------------------------------------------------------
1124  * image changers
1125  *----------------------------------------------------------------------------
1126  */
1127
1128 void layout_image_set_fd(LayoutWindow *lw, FileData *fd)
1129 {
1130         gdouble sx, sy;
1131         if (!layout_valid(&lw)) return;
1132
1133         image_get_scroll_center(lw->image, &sx, &sy);
1134
1135         image_change_fd(lw->image, fd, image_zoom_get_default(lw->image, options->image.zoom_mode));
1136
1137         image_set_scroll_center(lw->image, sx, sy);
1138
1139         layout_list_sync_fd(lw, fd);
1140         layout_image_slideshow_continue_check(lw);
1141         layout_bars_new_image(lw);
1142 }
1143
1144 void layout_image_set_with_ahead(LayoutWindow *lw, FileData *fd, FileData *read_ahead_fd)
1145 {
1146         if (!layout_valid(&lw)) return;
1147
1148 /*
1149 This should be handled at the caller: in vflist_select_image
1150         if (path)
1151                 {
1152                 const gchar *old_path;
1153
1154                 old_path = layout_image_get_path(lw);
1155                 if (old_path && strcmp(path, old_path) == 0) return;
1156                 }
1157 */
1158         layout_image_set_fd(lw, fd);
1159         if (options->image.enable_read_ahead) image_prebuffer_set(lw->image, read_ahead_fd);
1160 }
1161
1162 void layout_image_set_index(LayoutWindow *lw, gint index)
1163 {
1164         FileData *fd;
1165         FileData *read_ahead_fd;
1166         gint old;
1167
1168         if (!layout_valid(&lw)) return;
1169
1170         old = layout_list_get_index(lw, layout_image_get_path(lw));
1171         fd = layout_list_get_fd(lw, index);
1172
1173         if (old > index)
1174                 {
1175                 read_ahead_fd = layout_list_get_fd(lw, index - 1);
1176                 }
1177         else
1178                 {
1179                 read_ahead_fd = layout_list_get_fd(lw, index + 1);
1180                 }
1181
1182         if (layout_selection_count(lw, 0) > 1)
1183                 {
1184                 GList *x = layout_selection_list_by_index(lw);
1185                 GList *y;
1186                 GList *last;
1187
1188                 for (last = y = x; y; y = y->next)
1189                         last = y;
1190                 for (y = x; y && ((gint)y->data) != index; y = y->next)
1191                         ;
1192
1193                 if (y)
1194                         {
1195                         gint newindex;
1196
1197                         if ((index > old && (index != (gint) last->data || old != (gint) x->data))
1198                             || (old == (gint) last->data && index == (gint) x->data))
1199                                 {
1200                                 if (y->next)
1201                                         newindex = (gint) y->next->data;
1202                                 else
1203                                         newindex = (gint) x->data;
1204                                 }
1205                         else
1206                                 {
1207                                 if (y->prev)
1208                                         newindex = (gint) y->prev->data;
1209                                 else
1210                                         newindex = (gint) last->data;
1211                                 }
1212
1213                         read_ahead_fd = layout_list_get_fd(lw, newindex);
1214                         }
1215
1216                 while (x)
1217                         x = g_list_remove(x, x->data);
1218                 }
1219
1220         layout_image_set_with_ahead(lw, fd, read_ahead_fd);
1221 }
1222
1223 static void layout_image_set_collection_real(LayoutWindow *lw, CollectionData *cd, CollectInfo *info, gint forward)
1224 {
1225         if (!layout_valid(&lw)) return;
1226
1227         image_change_from_collection(lw->image, cd, info, image_zoom_get_default(lw->image, options->image.zoom_mode));
1228         if (options->image.enable_read_ahead)
1229                 {
1230                 CollectInfo *r_info;
1231                 if (forward)
1232                         {
1233                         r_info = collection_next_by_info(cd, info);
1234                         if (!r_info) r_info = collection_prev_by_info(cd, info);
1235                         }
1236                 else
1237                         {
1238                         r_info = collection_prev_by_info(cd, info);
1239                         if (!r_info) r_info = collection_next_by_info(cd, info);
1240                         }
1241                 if (r_info) image_prebuffer_set(lw->image, r_info->fd);
1242                 }
1243
1244         layout_image_slideshow_continue_check(lw);
1245         layout_bars_new_image(lw);
1246 }
1247
1248 void layout_image_set_collection(LayoutWindow *lw, CollectionData *cd, CollectInfo *info)
1249 {
1250         layout_image_set_collection_real(lw, cd, info, TRUE);
1251         layout_list_sync_fd(lw, layout_image_get_fd(lw));
1252 }
1253
1254 void layout_image_refresh(LayoutWindow *lw)
1255 {
1256         if (!layout_valid(&lw)) return;
1257
1258         image_reload(lw->image);
1259 }
1260
1261 void layout_image_color_profile_set(LayoutWindow *lw,
1262                                     gint input_type, gint screen_type,
1263                                     gint use_image)
1264 {
1265         if (!layout_valid(&lw)) return;
1266
1267         image_color_profile_set(lw->image, input_type, screen_type, use_image);
1268 }
1269
1270 gint layout_image_color_profile_get(LayoutWindow *lw,
1271                                     gint *input_type, gint *screen_type,
1272                                     gint *use_image)
1273 {
1274         if (!layout_valid(&lw)) return FALSE;
1275
1276         return image_color_profile_get(lw->image, input_type, screen_type, use_image);
1277 }
1278
1279 void layout_image_color_profile_set_use(LayoutWindow *lw, gint enable)
1280 {
1281         if (!layout_valid(&lw)) return;
1282
1283         image_color_profile_set_use(lw->image, enable);
1284
1285         if (lw->info_color)
1286                 {
1287 #ifndef HAVE_LCMS
1288                 enable = FALSE;
1289 #endif
1290                 gtk_widget_set_sensitive(GTK_BIN(lw->info_color)->child, enable);
1291                 }
1292 }
1293
1294 gint layout_image_color_profile_get_use(LayoutWindow *lw)
1295 {
1296         if (!layout_valid(&lw)) return FALSE;
1297
1298         return image_color_profile_get_use(lw->image);
1299 }
1300
1301 gint layout_image_color_profile_get_from_image(LayoutWindow *lw)
1302 {
1303         if (!layout_valid(&lw)) return FALSE;
1304
1305         return image_color_profile_get_from_image(lw->image);
1306 }
1307
1308 /*
1309  *----------------------------------------------------------------------------
1310  * list walkers
1311  *----------------------------------------------------------------------------
1312  */
1313
1314 void layout_image_next(LayoutWindow *lw)
1315 {
1316         gint current;
1317         CollectionData *cd;
1318         CollectInfo *info;
1319
1320         if (!layout_valid(&lw)) return;
1321
1322         if (layout_image_slideshow_active(lw))
1323                 {
1324                 layout_image_slideshow_next(lw);
1325                 return;
1326                 }
1327
1328         if (layout_selection_count(lw, 0) > 1)
1329                 {
1330                 GList *x = layout_selection_list_by_index(lw);
1331                 gint old = layout_list_get_index(lw, layout_image_get_path(lw));
1332                 GList *y;
1333
1334                 for (y = x; y && ((gint) y->data) != old; y = y->next)
1335                         ;
1336                 if (y)
1337                         {
1338                         if (y->next)
1339                                 layout_image_set_index(lw, (gint) y->next->data);
1340                         else
1341                                 layout_image_set_index(lw, (gint) x->data);
1342                         }
1343                 while (x)
1344                         x = g_list_remove(x, x->data);
1345                 if (y) /* not dereferenced */
1346                         return;
1347                 }
1348
1349         cd = image_get_collection(lw->image, &info);
1350
1351         if (cd && info)
1352                 {
1353                 info = collection_next_by_info(cd, info);
1354                 if (info)
1355                         {
1356                         layout_image_set_collection_real(lw, cd, info, TRUE);
1357                         }
1358                 else
1359                         {
1360                         image_osd_icon(lw->image, IMAGE_OSD_LAST, -1);
1361                         }
1362                 return;
1363                 }
1364
1365         current = layout_image_get_index(lw);
1366
1367         if (current >= 0)
1368                 {
1369                 if (current < layout_list_count(lw, NULL) - 1)
1370                         {
1371                         layout_image_set_index(lw, current + 1);
1372                         }
1373                 else
1374                         {
1375                         image_osd_icon(lw->image, IMAGE_OSD_LAST, -1);
1376                         }
1377                 }
1378         else
1379                 {
1380                 layout_image_set_index(lw, 0);
1381                 }
1382 }
1383
1384 void layout_image_prev(LayoutWindow *lw)
1385 {
1386         gint current;
1387         CollectionData *cd;
1388         CollectInfo *info;
1389
1390         if (!layout_valid(&lw)) return;
1391
1392         if (layout_image_slideshow_active(lw))
1393                 {
1394                 layout_image_slideshow_prev(lw);
1395                 return;
1396                 }
1397
1398         if (layout_selection_count(lw, 0) > 1)
1399                 {
1400                 GList *x = layout_selection_list_by_index(lw);
1401                 gint old = layout_list_get_index(lw, layout_image_get_path(lw));
1402                 GList *y;
1403                 GList *last;
1404
1405                 for (last = y = x; y; y = y->next)
1406                         last = y;
1407                 for (y = x; y && ((gint) y->data) != old; y = y->next)
1408                         ;
1409                 if (y)
1410                         {
1411                         if (y->prev)
1412                                 layout_image_set_index(lw, (gint) y->prev->data);
1413                         else
1414                                 layout_image_set_index(lw, (gint) last->data);
1415                         }
1416                 while (x)
1417                         x = g_list_remove(x, x->data);
1418                 if (y) /* not dereferenced */
1419                         return;
1420                 }
1421
1422         cd = image_get_collection(lw->image, &info);
1423
1424         if (cd && info)
1425                 {
1426                 info = collection_prev_by_info(cd, info);
1427                 if (info)
1428                         {
1429                         layout_image_set_collection_real(lw, cd, info, FALSE);
1430                         }
1431                 else
1432                         {
1433                         image_osd_icon(lw->image, IMAGE_OSD_FIRST, -1);
1434                         }
1435                 return;
1436                 }
1437
1438         current = layout_image_get_index(lw);
1439
1440         if (current >= 0)
1441                 {
1442                 if (current > 0)
1443                         {
1444                         layout_image_set_index(lw, current - 1);
1445                         }
1446                 else
1447                         {
1448                         image_osd_icon(lw->image, IMAGE_OSD_FIRST, -1);
1449                         }
1450                 }
1451         else
1452                 {
1453                 layout_image_set_index(lw, layout_list_count(lw, NULL) - 1);
1454                 }
1455 }
1456
1457 void layout_image_first(LayoutWindow *lw)
1458 {
1459         gint current;
1460         CollectionData *cd;
1461         CollectInfo *info;
1462
1463         if (!layout_valid(&lw)) return;
1464
1465         cd = image_get_collection(lw->image, &info);
1466
1467         if (cd && info)
1468                 {
1469                 CollectInfo *new;
1470                 new = collection_get_first(cd);
1471                 if (new != info) layout_image_set_collection_real(lw, cd, new, TRUE);
1472                 return;
1473                 }
1474
1475         current = layout_image_get_index(lw);
1476         if (current != 0 && layout_list_count(lw, NULL) > 0)
1477                 {
1478                 layout_image_set_index(lw, 0);
1479                 }
1480 }
1481
1482 void layout_image_last(LayoutWindow *lw)
1483 {
1484         gint current;
1485         gint count;
1486         CollectionData *cd;
1487         CollectInfo *info;
1488
1489         if (!layout_valid(&lw)) return;
1490
1491         cd = image_get_collection(lw->image, &info);
1492
1493         if (cd && info)
1494                 {
1495                 CollectInfo *new;
1496                 new = collection_get_last(cd);
1497                 if (new != info) layout_image_set_collection_real(lw, cd, new, FALSE);
1498                 return;
1499                 }
1500
1501         current = layout_image_get_index(lw);
1502         count = layout_list_count(lw, NULL);
1503         if (current != count - 1 && count > 0)
1504                 {
1505                 layout_image_set_index(lw, count - 1);
1506                 }
1507 }
1508
1509 /*
1510  *----------------------------------------------------------------------------
1511  * mouse callbacks
1512  *----------------------------------------------------------------------------
1513  */
1514
1515 static gint image_idx(LayoutWindow *lw, ImageWindow *imd)
1516 {
1517         gint i;
1518
1519         for (i=0; i < MAX_SPLIT_IMAGES; i++)
1520                 {
1521                 if (lw->split_images[i] == imd)
1522                         break;
1523                 }
1524         if (i < MAX_SPLIT_IMAGES)
1525                 {
1526                 return i;
1527                 }
1528         return -1;
1529 }
1530
1531
1532 static void layout_image_button_cb(ImageWindow *imd, gint button, guint32 time,
1533                                    gdouble x, gdouble y, guint state, gpointer data)
1534 {
1535         LayoutWindow *lw = data;
1536         GtkWidget *menu;
1537
1538         switch (button)
1539                 {
1540                 case MOUSE_BUTTON_LEFT:
1541                         layout_image_next(lw);
1542                         break;
1543                 case MOUSE_BUTTON_MIDDLE:
1544                         layout_image_prev(lw);
1545                         break;
1546                 case MOUSE_BUTTON_RIGHT:
1547                         menu = layout_image_pop_menu(lw);
1548                         if (imd == lw->image)
1549                                 {
1550                                 g_object_set_data(G_OBJECT(menu), "click_parent", imd->widget);
1551                                 }
1552                         gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, time);
1553                         break;
1554                 default:
1555                         break;
1556                 }
1557 }
1558
1559 static void layout_image_scroll_cb(ImageWindow *imd, GdkScrollDirection direction, guint32 time,
1560                                    gdouble x, gdouble y, guint state, gpointer data)
1561 {
1562         LayoutWindow *lw = data;
1563
1564         gint i = image_idx(lw, imd);
1565
1566         if (i != -1)
1567                 {
1568                 printf("image activate scroll %d\n", i);
1569                 layout_image_activate(lw, i);
1570                 }
1571
1572
1573         if (state & GDK_CONTROL_MASK)
1574                 {
1575                 switch (direction)
1576                         {
1577                         case GDK_SCROLL_UP:
1578                                 image_zoom_adjust_at_point(imd, get_zoom_increment(), x, y);
1579                                 break;
1580                         case GDK_SCROLL_DOWN:
1581                                 image_zoom_adjust_at_point(imd, -get_zoom_increment(), x, y);
1582                                 break;
1583                         default:
1584                                 break;
1585                         }
1586                 }
1587         else if ( (state & GDK_SHIFT_MASK) != (options->mousewheel_scrolls))
1588                 {
1589                 switch (direction)
1590                         {
1591                         case GDK_SCROLL_UP:
1592                                 image_scroll(imd, 0, -MOUSEWHEEL_SCROLL_SIZE);
1593                                 break;
1594                         case GDK_SCROLL_DOWN:
1595                                 image_scroll(imd, 0, MOUSEWHEEL_SCROLL_SIZE);
1596                                 break;
1597                         case GDK_SCROLL_LEFT:
1598                                 image_scroll(imd, -MOUSEWHEEL_SCROLL_SIZE, 0);
1599                                 break;
1600                         case GDK_SCROLL_RIGHT:
1601                                 image_scroll(imd, MOUSEWHEEL_SCROLL_SIZE, 0);
1602                                 break;
1603                         default:
1604                                 break;
1605                         }
1606                 }
1607         else
1608                 {
1609                 switch (direction)
1610                         {
1611                         case GDK_SCROLL_UP:
1612                                 layout_image_prev(lw);
1613                                 break;
1614                         case GDK_SCROLL_DOWN:
1615                                 layout_image_next(lw);
1616                                 break;
1617                         default:
1618                                 break;
1619                         }
1620                 }
1621 }
1622
1623 static void layout_image_drag_cb(ImageWindow *imd, gint button, guint32 time,
1624                                  gdouble x, gdouble y, guint state, gdouble dx, gdouble dy, gpointer data)
1625 {
1626         gint i;
1627         LayoutWindow *lw = data;
1628
1629
1630         for (i=0; i < MAX_SPLIT_IMAGES; i++)
1631                 {
1632                 if (lw->split_images[i] && lw->split_images[i] != imd)
1633                         if (lw->connect_scroll)
1634                                 {
1635                                 gdouble sx, sy;
1636                                 if (state & GDK_CONTROL_MASK)
1637                                         {
1638                                         image_get_scroll_center(imd, &sx, &sy);
1639                                         }
1640                                 else
1641                                         {
1642                                         image_get_scroll_center(lw->split_images[i], &sx, &sy);
1643                                         sx += dx;
1644                                         sy += dy;
1645                                         }
1646                                 image_set_scroll_center(lw->split_images[i], sx, sy);
1647                                 }
1648                 }
1649 }
1650
1651 static void layout_image_button_inactive_cb(ImageWindow *imd, gint button, guint32 time,
1652                                    gdouble x, gdouble y, guint state, gpointer data)
1653 {
1654         LayoutWindow *lw = data;
1655         GtkWidget *menu;
1656         gint i = image_idx(lw, imd);
1657
1658         if (i != -1)
1659                 {
1660                 layout_image_activate(lw, i);
1661                 }
1662
1663         switch (button)
1664                 {
1665                 case MOUSE_BUTTON_RIGHT:
1666                         menu = layout_image_pop_menu(lw);
1667                         if (imd == lw->image)
1668                                 {
1669                                 g_object_set_data(G_OBJECT(menu), "click_parent", imd->widget);
1670                                 }
1671                         gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, time);
1672                         break;
1673                 default:
1674                         break;
1675                 }
1676
1677 }
1678
1679 static void layout_image_drag_inactive_cb(ImageWindow *imd, gint button, guint32 time,
1680                                  gdouble x, gdouble y, guint state, gdouble dx, gdouble dy, gpointer data)
1681 {
1682         LayoutWindow *lw = data;
1683
1684         gint i = image_idx(lw, imd);
1685
1686         if (i != -1)
1687                 {
1688                 layout_image_activate(lw, i);
1689                 }
1690
1691
1692         /* continue as with active image */
1693         layout_image_drag_cb(imd, button, time, x, y, state, dx, dy, data);
1694 }
1695
1696
1697 static void layout_image_set_buttons(LayoutWindow *lw)
1698 {
1699         image_set_button_func(lw->image, layout_image_button_cb, lw);
1700         image_set_scroll_func(lw->image, layout_image_scroll_cb, lw);
1701 }
1702
1703 static void layout_image_set_buttons_inactive(LayoutWindow *lw, gint i)
1704 {
1705         image_set_button_func(lw->split_images[i], layout_image_button_inactive_cb, lw);
1706         image_set_scroll_func(lw->split_images[i], layout_image_scroll_cb, lw);
1707 }
1708
1709 /*
1710  *----------------------------------------------------------------------------
1711  * setup
1712  *----------------------------------------------------------------------------
1713  */
1714
1715 static void layout_image_update_cb(ImageWindow *imd, gpointer data)
1716 {
1717         LayoutWindow *lw = data;
1718         layout_status_update_image(lw);
1719 }
1720
1721 GtkWidget *layout_image_new(LayoutWindow *lw, gint i)
1722 {
1723         if (!lw->split_images[i])
1724                 {
1725                 lw->split_images[i] = image_new(TRUE);
1726
1727                 gtk_widget_ref(lw->split_images[i]->widget);
1728
1729                 image_background_set_color(lw->split_images[i], options->image.use_custom_border_color ? &options->image.border_color : NULL);
1730
1731                 image_auto_refresh(lw->split_images[i], 0);
1732
1733                 layout_image_dnd_init(lw, i);
1734                 image_color_profile_set(lw->split_images[i],
1735                                         options->color_profile.input_type,
1736                                         options->color_profile.screen_type,
1737                                         options->color_profile.use_image);
1738                 image_color_profile_set_use(lw->split_images[i], options->color_profile.enabled);
1739                 }
1740
1741         return lw->split_images[i]->widget;
1742 }
1743
1744 void layout_image_deactivate(LayoutWindow *lw, gint i)
1745 {
1746
1747         if (!lw->split_images[i]) return;
1748         image_set_update_func(lw->split_images[i], NULL, NULL);
1749         layout_image_set_buttons_inactive(lw, i);
1750         image_set_drag_func(lw->split_images[i], layout_image_drag_inactive_cb, lw);
1751
1752         image_attach_window(lw->split_images[i], NULL, NULL, NULL, FALSE);
1753         image_select(lw->split_images[i], FALSE);
1754 }
1755
1756
1757 void layout_image_activate(LayoutWindow *lw, gint i)
1758 {
1759         FileData *fd;
1760
1761         if (!lw->split_images[i]) return;
1762
1763         /* deactivate currently active */
1764         if (lw->active_split_image != i)
1765                 layout_image_deactivate(lw, lw->active_split_image);
1766
1767         lw->image = lw->split_images[i];
1768         lw->active_split_image = i;
1769
1770         image_set_update_func(lw->image, layout_image_update_cb, lw);
1771         layout_image_set_buttons(lw);
1772         image_set_drag_func(lw->image, layout_image_drag_cb, lw);
1773
1774         image_attach_window(lw->image, lw->window, NULL, GQ_APPNAME, FALSE);
1775
1776         /* do not hilight selected image in SPLIT_NONE */
1777         /* maybe the image should be selected always and hilight should be controled by
1778            another image option */
1779         if (lw->split_mode != SPLIT_NONE)
1780                 image_select(lw->split_images[i], TRUE);
1781         else
1782                 image_select(lw->split_images[i], FALSE);
1783
1784         fd = image_get_fd(lw->image);
1785
1786         if (fd)
1787                 {
1788 //              layout_list_sync_path(lw, path);
1789                 layout_set_path(lw, fd->path);
1790                 }
1791 }
1792
1793
1794 GtkWidget *layout_image_setup_split_none(LayoutWindow *lw)
1795 {
1796         gint i;
1797
1798         lw->split_mode = SPLIT_NONE;
1799
1800         if (!lw->split_images[0])
1801                 {
1802                 layout_image_new(lw, 0);
1803                 image_set_frame(lw->split_images[0], (!lw->tools_float && !lw->tools_hidden));
1804                 image_set_selectable(lw->split_images[0], 0);
1805                 layout_image_activate(lw, 0);
1806                 }
1807         else
1808                 {
1809                 image_set_frame(lw->split_images[0], (!lw->tools_float && !lw->tools_hidden));
1810                 image_set_selectable(lw->split_images[0], 0);
1811                 }
1812
1813         for (i=1; i < MAX_SPLIT_IMAGES; i++)
1814                 {
1815                 if (lw->split_images[i])
1816                         {
1817                         gtk_widget_unref(lw->split_images[i]->widget);
1818                         lw->split_images[i] = NULL;
1819                         }
1820                 }
1821
1822
1823         layout_image_activate(lw, 0);
1824
1825         lw->split_image_widget = lw->split_images[0]->widget;
1826
1827         return lw->split_image_widget;
1828 }
1829
1830 GtkWidget *layout_image_setup_split_hv(LayoutWindow *lw, gboolean horizontal)
1831 {
1832         GtkWidget *paned;
1833         gint i;
1834
1835         lw->split_mode = horizontal ? SPLIT_HOR : SPLIT_VERT;
1836
1837         if (!lw->split_images[0])
1838                 {
1839                 layout_image_new(lw, 0);
1840                 }
1841         image_set_frame(lw->split_images[0], 1);
1842         image_set_selectable(lw->split_images[0], 1);
1843
1844         if (!lw->split_images[1])
1845                 {
1846                 layout_image_new(lw, 1);
1847                 image_set_frame(lw->split_images[1], 1);
1848                 image_set_selectable(lw->split_images[1], 1);
1849                 if (lw->image)
1850                         {
1851                         gdouble sx, sy;
1852                         image_change_fd(lw->split_images[1],
1853                                 image_get_fd(lw->image), image_zoom_get(lw->image));
1854                         image_get_scroll_center(lw->image, &sx, &sy);
1855                         image_set_scroll_center(lw->split_images[1], sx, sy);
1856                         }
1857                 layout_image_deactivate(lw, 1);
1858                 layout_image_activate(lw, 0);
1859                 }
1860         else
1861                 {
1862                 image_set_frame(lw->split_images[1], 1);
1863                 image_set_selectable(lw->split_images[1], 1);
1864                 }
1865
1866
1867         for (i=2; i < MAX_SPLIT_IMAGES; i++)
1868                 {
1869                 if (lw->split_images[i])
1870                         {
1871                         gtk_widget_unref(lw->split_images[i]->widget);
1872                         lw->split_images[i] = NULL;
1873                         }
1874                 }
1875
1876         if (!lw->image || lw->active_split_image < 0 || lw->active_split_image > 1)
1877                 {
1878                 layout_image_activate(lw, 0);
1879                 }
1880
1881         /* horizontal split means vpaned and vice versa */
1882         if (horizontal)
1883                 paned = gtk_vpaned_new ();
1884         else
1885                 paned = gtk_hpaned_new ();
1886
1887         gtk_paned_pack1 (GTK_PANED (paned), lw->split_images[0]->widget, TRUE, TRUE);
1888         gtk_paned_pack2 (GTK_PANED (paned), lw->split_images[1]->widget, TRUE, TRUE);
1889
1890         gtk_widget_show (lw->split_images[0]->widget);
1891         gtk_widget_show (lw->split_images[1]->widget);
1892
1893
1894         lw->split_image_widget = paned;
1895
1896         return lw->split_image_widget;
1897
1898 }
1899
1900 GtkWidget *layout_image_setup_split_quad(LayoutWindow *lw)
1901 {
1902         GtkWidget *hpaned;
1903         GtkWidget *vpaned1;
1904         GtkWidget *vpaned2;
1905         gint i;
1906
1907         lw->split_mode = SPLIT_QUAD;
1908
1909         if (!lw->split_images[0])
1910                 {
1911                 layout_image_new(lw, 0);
1912                 }
1913
1914         image_set_frame(lw->split_images[0], 1);
1915         image_set_selectable(lw->split_images[0], 1);
1916
1917         if (!lw->split_images[1])
1918                 {
1919                 layout_image_activate(lw, 0);
1920                 }
1921
1922         for (i=1; i < 4; i++)
1923                 if (!lw->split_images[i])
1924                         {
1925                         layout_image_new(lw, i);
1926                         image_set_frame(lw->split_images[i], 1);
1927                         image_set_selectable(lw->split_images[i], 1);
1928                         if (lw->image)
1929                                 {
1930                                 gdouble sx, sy;
1931                                 image_change_fd(lw->split_images[i],
1932                                         image_get_fd(lw->image), image_zoom_get(lw->image));
1933                                 image_get_scroll_center(lw->image, &sx, &sy);
1934                                 image_set_scroll_center(lw->split_images[i], sx, sy);
1935                                 }
1936                         layout_image_deactivate(lw, i);
1937                         }
1938                 else
1939                         {
1940                         image_set_frame(lw->split_images[i], 1);
1941                         image_set_selectable(lw->split_images[i], 1);
1942                         }
1943
1944         for (i=4; i < MAX_SPLIT_IMAGES; i++)
1945                 {
1946                 if (lw->split_images[i])
1947                         {
1948                         gtk_widget_unref(lw->split_images[i]->widget);
1949                         lw->split_images[i] = NULL;
1950                         }
1951                 }
1952
1953
1954         if (!lw->image || lw->active_split_image < 0 || lw->active_split_image > 3)
1955                 {
1956                 layout_image_activate(lw, 0);
1957                 }
1958
1959         hpaned = gtk_hpaned_new ();
1960         vpaned1 = gtk_vpaned_new ();
1961         vpaned2 = gtk_vpaned_new ();
1962
1963         gtk_paned_pack1 (GTK_PANED (vpaned1), lw->split_images[0]->widget, TRUE, TRUE);
1964         gtk_paned_pack2 (GTK_PANED (vpaned1), lw->split_images[2]->widget, TRUE, TRUE);
1965
1966         gtk_paned_pack1 (GTK_PANED (vpaned2), lw->split_images[1]->widget, TRUE, TRUE);
1967         gtk_paned_pack2 (GTK_PANED (vpaned2), lw->split_images[3]->widget, TRUE, TRUE);
1968
1969         gtk_paned_pack1 (GTK_PANED (hpaned), vpaned1, TRUE, TRUE);
1970         gtk_paned_pack2 (GTK_PANED (hpaned), vpaned2, TRUE, TRUE);
1971
1972
1973         for (i=0; i < 4; i++)
1974                 gtk_widget_show (lw->split_images[i]->widget);
1975         gtk_widget_show (vpaned1);
1976         gtk_widget_show (vpaned2);
1977
1978
1979         lw->split_image_widget = hpaned;
1980
1981         return lw->split_image_widget;
1982
1983 }
1984
1985 GtkWidget *layout_image_setup_split(LayoutWindow *lw, ImageSplitMode mode)
1986 {
1987         switch (mode)
1988                 {
1989                 case SPLIT_HOR:
1990                         return layout_image_setup_split_hv(lw, TRUE);
1991                 case SPLIT_VERT:
1992                         return layout_image_setup_split_hv(lw, FALSE);
1993                 case SPLIT_QUAD:
1994                         return layout_image_setup_split_quad(lw);
1995                 case SPLIT_NONE:
1996                 default:
1997                         return layout_image_setup_split_none(lw);
1998                 }
1999 }
2000
2001
2002 /*
2003  *-----------------------------------------------------------------------------
2004  * maintenance (for rename, move, remove)
2005  *-----------------------------------------------------------------------------
2006  */
2007
2008 void layout_image_maint_renamed(LayoutWindow *lw, FileData *fd)
2009 {
2010         FileData *img_fd;
2011
2012         img_fd = layout_image_get_fd(lw);
2013         if (img_fd == fd)
2014                 {
2015                 image_set_fd(lw->image, fd);
2016                 layout_bars_maint_renamed(lw);
2017                 }
2018 }
2019
2020 void layout_image_maint_removed(LayoutWindow *lw, FileData *fd)
2021 {
2022         FileData *img_fd;
2023
2024         img_fd = layout_image_get_fd(lw);
2025         if (img_fd == fd)
2026                 {
2027                 CollectionData *cd;
2028                 CollectInfo *info;
2029
2030                 cd = image_get_collection(lw->image, &info);
2031                 if (cd && info)
2032                         {
2033                         CollectInfo *new;
2034
2035                         new = collection_next_by_info(cd, info);
2036                         if (!new) new = collection_prev_by_info(cd, info);
2037
2038                         if (new)
2039                                 {
2040                                 layout_image_set_collection(lw, cd, new);
2041                                 return;
2042                                 }
2043                         }
2044
2045                 layout_image_set_fd(lw, NULL);
2046                 }
2047 }
2048
2049 void layout_image_maint_moved(LayoutWindow *lw, FileData *fd)
2050 {
2051         layout_image_maint_renamed(lw, fd);
2052 }