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