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