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