Fix #767: twin file-panels with ability to move to next image simultaneously
authorColin Clark <colin.clark@cclark.uk>
Sun, 12 Apr 2020 12:09:34 +0000 (13:09 +0100)
committerColin Clark <colin.clark@cclark.uk>
Sun, 12 Apr 2020 12:09:34 +0000 (13:09 +0100)
https://github.com/BestImageViewer/geeqie/issues/767

New menu option: View/Split/Split Pane Sync

src/icons/Makefile.am
src/icons/icon_split_pane_sync.png [new file with mode: 0644]
src/image.c
src/layout_util.c
src/options.c
src/pixbuf_util.c
src/pixbuf_util.h
src/preferences.c
src/toolbar.c
src/typedefs.h

index 2ecc437..f8009e9 100644 (file)
@@ -50,7 +50,8 @@ ICONS_INLINE = \
        icon_trash.png \
        icon_heic.png \
        icon_grayscale.png \
-       icon_exposure.png
+       icon_exposure.png \
+       icon_split_pane_sync.png
 
 ICONS_INLINE_PAIRS = \
        folder_closed           $(srcdir)/folder_closed.png     \
@@ -99,7 +100,8 @@ ICONS_INLINE_PAIRS = \
        icon_trash      $(srcdir)/icon_trash.png \
        icon_heic       $(srcdir)/icon_heic.png \
        icon_grayscale  $(srcdir)/icon_grayscale.png \
-       icon_exposure   $(srcdir)/icon_exposure.png
+       icon_exposure   $(srcdir)/icon_exposure.png \
+       icon_split_pane_sync    $(srcdir)/icon_split_pane_sync.png
 
 icons_inline.h: $(ICONS_INLINE) Makefile.in
        @sh -ec "echo '/* Auto generated file, do not edit */'; echo; \
diff --git a/src/icons/icon_split_pane_sync.png b/src/icons/icon_split_pane_sync.png
new file mode 100644 (file)
index 0000000..e9049bc
Binary files /dev/null and b/src/icons/icon_split_pane_sync.png differ
index ad474d6..522e8bd 100644 (file)
@@ -1152,12 +1152,47 @@ static gboolean image_focus_in_cb(GtkWidget *widget, GdkEventFocus *event, gpoin
 static gboolean image_scroll_cb(GtkWidget *widget, GdkEventScroll *event, gpointer data)
 {
        ImageWindow *imd = data;
+       gboolean in_lw = FALSE;
+       gint i = 0;
+       LayoutWindow *lw = NULL;
 
-       if (imd->func_scroll &&
-           event && event->type == GDK_SCROLL)
+       if (imd->func_scroll && event && event->type == GDK_SCROLL)
                {
-               imd->func_scroll(imd, event, imd->data_scroll);
-               return TRUE;
+               layout_valid(&lw);
+               /* check if the image is in a layout window */
+               for (i = 0; i < MAX_SPLIT_IMAGES; i++)
+                       {
+                       if (imd == lw->split_images[i])
+                               {
+                               in_lw = TRUE;
+                               break;
+                               }
+                       }
+
+               if (in_lw)
+                       {
+                       if (lw->options.split_pane_sync)
+                               {
+                               for (i = 0; i < MAX_SPLIT_IMAGES; i++)
+                                       {
+                                       if (lw->split_images[i])
+                                               {
+                                               layout_image_activate(lw, i, FALSE);
+                                               imd->func_scroll(lw->split_images[i], event, lw->split_images[i]->data_scroll);
+                                               }
+                                       }
+                               }
+                       else
+                               {
+                               imd->func_scroll(imd, event, imd->data_scroll);
+                               }
+                       return TRUE;
+                       }
+               else
+                       {
+                       imd->func_scroll(imd, event, imd->data_scroll);
+                       return TRUE;
+                       }
                }
 
        return FALSE;
index 38b065e..af480da 100644 (file)
@@ -532,6 +532,13 @@ static void layout_menu_select_rectangle_cb(GtkToggleAction *action, gpointer da
        options->draw_rectangle = gtk_toggle_action_get_active(action);
 }
 
+static void layout_menu_split_pane_sync_cb(GtkToggleAction *action, gpointer data)
+{
+       LayoutWindow *lw = data;
+
+       lw->options.split_pane_sync = gtk_toggle_action_get_active(action);
+}
+
 static void layout_menu_select_overunderexposed_cb(GtkToggleAction *action, gpointer data)
 {
        LayoutWindow *lw = data;
@@ -1527,13 +1534,53 @@ static void layout_menu_image_first_cb(GtkAction *action, gpointer data)
 static void layout_menu_image_prev_cb(GtkAction *action, gpointer data)
 {
        LayoutWindow *lw = data;
-       layout_image_prev(lw);
+       gint i;
+
+       if (lw->options.split_pane_sync)
+               {
+               for (i = 0; i < MAX_SPLIT_IMAGES; i++)
+                       {
+                       if (lw->split_images[i])
+                               {
+                               if (i != -1)
+                                       {
+                                       DEBUG_1("image activate scroll %d", i);
+                                       layout_image_activate(lw, i, FALSE);
+                                       layout_image_prev(lw);
+                                       }
+                               }
+                       }
+               }
+       else
+               {
+               layout_image_prev(lw);
+               }
 }
 
 static void layout_menu_image_next_cb(GtkAction *action, gpointer data)
 {
        LayoutWindow *lw = data;
-       layout_image_next(lw);
+       gint i;
+
+       if (lw->options.split_pane_sync)
+               {
+               for (i = 0; i < MAX_SPLIT_IMAGES; i++)
+                       {
+                       if (lw->split_images[i])
+                               {
+                               if (i != -1)
+                                       {
+                                       DEBUG_1("image activate scroll %d", i);
+                                       layout_image_activate(lw, i, FALSE);
+                                       layout_image_next(lw);
+                                       }
+                               }
+                       }
+               }
+       else
+               {
+               layout_image_next(lw);
+               }
 }
 
 static void layout_menu_page_first_cb(GtkAction *action, gpointer data)
@@ -2547,6 +2594,7 @@ static GtkToggleActionEntry menu_toggle_entries[] = {
   { "ExifRotate",      GTK_STOCK_ORIENTATION_PORTRAIT,                 N_("_Exif rotate"),             "<alt>X",               N_("Exif rotate"),                      CB(layout_menu_exif_rotate_cb), FALSE },
   { "DrawRectangle",   PIXBUF_INLINE_ICON_DRAW_RECTANGLE,                      N_("Draw Rectangle"),           NULL,           N_("Draw Rectangle"),                   CB(layout_menu_select_rectangle_cb), FALSE },
   { "OverUnderExposed",        PIXBUF_INLINE_ICON_EXPOSURE,    N_("Over/Under Exposed"),       "<shift>E",             N_("Over/Under Exposed"),               CB(layout_menu_select_overunderexposed_cb), FALSE },
+  { "SplitPaneSync",   PIXBUF_INLINE_SPLIT_PANE_SYNC,                  N_("Split Pane Sync"),  NULL,           N_("Split Pane Sync"),  CB(layout_menu_split_pane_sync_cb) },
 };
 
 static GtkRadioActionEntry menu_radio_entries[] = {
@@ -2767,6 +2815,8 @@ static const gchar *menu_ui_description =
 "        <menuitem action='SplitPreviousPane'/>"
 "        <menuitem action='SplitUpPane'/>"
 "        <menuitem action='SplitDownPane'/>"
+"        <separator/>"
+"        <menuitem action='SplitPaneSync'/>"
 "      </menu>"
 "      <menu action='StereoMenu'>"
 "        <menuitem action='StereoAuto'/>"
@@ -3696,6 +3746,9 @@ static void layout_util_sync_views(LayoutWindow *lw)
        action = gtk_action_group_get_action(lw->action_group, "SplitDownPane");
        gtk_action_set_sensitive(action, !(lw->split_mode == SPLIT_NONE));
 
+       action = gtk_action_group_get_action(lw->action_group, "SplitPaneSync");
+       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.split_pane_sync);
+
        action = gtk_action_group_get_action(lw->action_group, "ViewIcons");
        gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), lw->options.file_view_type);
 
index a28b7f5..ccdefe1 100644 (file)
@@ -314,6 +314,7 @@ LayoutOptions *init_layout_options(LayoutOptions *options)
        options->bars_state.hidden = FALSE;
        options->log_window.w = 520;
        options->log_window.h = 400;
+       options->split_pane_sync = FALSE;
        return options;
 }
 
index 2a6f79d..fc41487 100644 (file)
@@ -149,6 +149,7 @@ static PixbufInline inline_pixbuf_data[] = {
        { PIXBUF_INLINE_ICON_HEIF,      icon_heic },
        { PIXBUF_INLINE_ICON_GRAYSCALE, icon_grayscale },
        { PIXBUF_INLINE_ICON_EXPOSURE,  icon_exposure },
+       { PIXBUF_INLINE_SPLIT_PANE_SYNC, icon_split_pane_sync },
        { NULL, NULL }
 };
 
index bcec3ae..0a6fc35 100644 (file)
@@ -77,6 +77,7 @@ gboolean pixbuf_scale_aspect(gint req_w, gint req_h, gint old_w, gint old_h, gin
 #define PIXBUF_INLINE_ICON_HEIF        "icon_heic"
 #define PIXBUF_INLINE_ICON_GRAYSCALE   "icon_grayscale"
 #define PIXBUF_INLINE_ICON_EXPOSURE            "icon_exposure"
+#define PIXBUF_INLINE_SPLIT_PANE_SYNC  "icon_split_pane_sync"
 
 #define PIXBUF_INLINE_ICON_CW  "icon_rotate_clockwise"
 #define PIXBUF_INLINE_ICON_CCW "icon_rotate_counter_clockwise"
index e584749..040537e 100644 (file)
@@ -732,6 +732,7 @@ static const UseableMouseItems useable_mouse_items[] = {
        {"Zoom33",      N_("Zoom1:3"), GTK_STOCK_FILE},
        {"Zoom25",      N_("Zoom 1:4"), GTK_STOCK_FILE},
        {"ConnectZoomIn",       N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
+       {"SplitPaneSync",       N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
        {"Grayscale",   N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
        {"OverUnderExposed",    N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
        {"HideTools",   N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
index 20f0565..d4076d5 100644 (file)
@@ -125,6 +125,7 @@ static const UseableToolbarItems useable_toolbar_items[] = {
        {"Zoom33",      N_("Zoom1:3"), GTK_STOCK_FILE},
        {"Zoom25",      N_("Zoom 1:4"), GTK_STOCK_FILE},
        {"ConnectZoomIn",       N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
+       {"SplitPaneSync",       N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
        {"Grayscale",   N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
        {"OverUnderExposed",    N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
        {"ShowInfoPixel",       N_("Pixel Info"),       GTK_STOCK_COLOR_PICKER},
index 9a4dfdb..fcc6817 100644 (file)
@@ -662,6 +662,7 @@ struct _LayoutOptions
        gboolean show_file_filter;
        gboolean show_directory_date;
        gboolean show_info_pixel;
+       gboolean split_pane_sync;
 
        struct {
                gint w;