From bd2e929b77b4bbf9eae7b96986fa441380140d92 Mon Sep 17 00:00:00 2001 From: Přemysl Eric Janouch
Date: Sun, 17 Jul 2022 12:37:32 +0200
Subject: Add ability to keep zoom/position when browsing
---
README.adoc | 2 +
fiv-view.c | 29 +++++++-
fiv-view.h | 3 +-
fiv.c | 6 +-
resources/pin2-symbolic.svg | 152 ++++++++++++++++++++++++++++++++++++++
resources/resources.gresource.xml | 1 +
6 files changed, 189 insertions(+), 4 deletions(-)
create mode 100644 resources/pin2-symbolic.svg
diff --git a/README.adoc b/README.adoc
index d245a0f..965cb62 100644
--- a/README.adoc
+++ b/README.adoc
@@ -14,6 +14,8 @@ Features
- Employs high-performance file format libraries: Wuffs and libjpeg-turbo.
- Makes use of 30-bit X.org visuals, whenever it's possible and appropriate.
- Has a notion of pages, and tries to load all included content within files.
+ - Can keep the zoom and position when browsing, to help with comparing
+ zoomed-in images.
Explicit non-goals
------------------
diff --git a/fiv-view.c b/fiv-view.c
index 01bedc8..8a42d04 100644
--- a/fiv-view.c
+++ b/fiv-view.c
@@ -67,6 +67,7 @@ struct _FivView {
bool checkerboard : 1; ///< Show checkerboard background
bool enhance : 1; ///< Try to enhance picture data
bool scale_to_fit : 1; ///< Image no larger than the allocation
+ bool fixate : 1; ///< Keep zoom and position
double scale; ///< Scaling factor
double drag_start[2]; ///< Adjustment values for drag origin
@@ -125,6 +126,7 @@ enum {
PROP_MESSAGES = 1,
PROP_SCALE,
PROP_SCALE_TO_FIT,
+ PROP_FIXATE,
PROP_ENABLE_CMS,
PROP_FILTER,
PROP_CHECKERBOARD,
@@ -254,6 +256,9 @@ fiv_view_get_property(
case PROP_SCALE_TO_FIT:
g_value_set_boolean(value, self->scale_to_fit);
break;
+ case PROP_FIXATE:
+ g_value_set_boolean(value, self->fixate);
+ break;
case PROP_ENABLE_CMS:
g_value_set_boolean(value, self->enable_cms);
break;
@@ -311,6 +316,10 @@ fiv_view_set_property(
if (self->scale_to_fit != g_value_get_boolean(value))
fiv_view_command(self, FIV_VIEW_COMMAND_TOGGLE_SCALE_TO_FIT);
break;
+ case PROP_FIXATE:
+ if (self->fixate != g_value_get_boolean(value))
+ fiv_view_command(self, FIV_VIEW_COMMAND_TOGGLE_FIXATE);
+ break;
case PROP_ENABLE_CMS:
if (self->enable_cms != g_value_get_boolean(value))
fiv_view_command(self, FIV_VIEW_COMMAND_TOGGLE_CMS);
@@ -636,7 +645,12 @@ static gboolean
set_scale_to_fit(FivView *self, bool scale_to_fit)
{
if (self->scale_to_fit != scale_to_fit) {
- self->scale_to_fit = scale_to_fit;
+ if ((self->scale_to_fit = scale_to_fit)) {
+ self->fixate = false;
+ g_object_notify_by_pspec(
+ G_OBJECT(self), view_properties[PROP_FIXATE]);
+ }
+
g_object_notify_by_pspec(
G_OBJECT(self), view_properties[PROP_SCALE_TO_FIT]);
gtk_widget_queue_resize(GTK_WIDGET(self));
@@ -1270,6 +1284,9 @@ fiv_view_class_init(FivViewClass *klass)
view_properties[PROP_SCALE_TO_FIT] = g_param_spec_boolean(
"scale-to-fit", "Scale to fit", "Scale images down to fit the window",
TRUE, G_PARAM_READWRITE);
+ view_properties[PROP_FIXATE] = g_param_spec_boolean(
+ "fixate", "Fixate", "Keep zoom and position",
+ FALSE, G_PARAM_READWRITE);
view_properties[PROP_ENABLE_CMS] = g_param_spec_boolean(
"enable-cms", "Enable CMS", "Enable color management",
TRUE, G_PARAM_READWRITE);
@@ -1443,7 +1460,10 @@ fiv_view_set_uri(FivView *self, const char *uri)
self->frame = self->page = NULL;
self->image = surface;
switch_page(self, self->image);
- set_scale_to_fit(self, true);
+
+ // Otherwise, adjustment values and zoom are retained implicitly.
+ if (!self->fixate)
+ set_scale_to_fit(self, true);
g_free(self->uri);
self->uri = g_strdup(uri);
@@ -1592,5 +1612,10 @@ fiv_view_command(FivView *self, FivViewCommand command)
set_scale_to_fit_height(self);
break; case FIV_VIEW_COMMAND_TOGGLE_SCALE_TO_FIT:
set_scale_to_fit(self, !self->scale_to_fit);
+ break; case FIV_VIEW_COMMAND_TOGGLE_FIXATE:
+ if ((self->fixate = !self->fixate))
+ set_scale_to_fit(self, false);
+ g_object_notify_by_pspec(
+ G_OBJECT(self), view_properties[PROP_FIXATE]);
}
}
diff --git a/fiv-view.h b/fiv-view.h
index c2d8b8b..7f4e3a3 100644
--- a/fiv-view.h
+++ b/fiv-view.h
@@ -60,7 +60,8 @@ typedef enum _FivViewCommand {
XX(FIV_VIEW_COMMAND_ZOOM_1, "zoom-1") \
XX(FIV_VIEW_COMMAND_FIT_WIDTH, "fit-width") \
XX(FIV_VIEW_COMMAND_FIT_HEIGHT, "fit-height") \
- XX(FIV_VIEW_COMMAND_TOGGLE_SCALE_TO_FIT, "toggle-scale-to-fit")
+ XX(FIV_VIEW_COMMAND_TOGGLE_SCALE_TO_FIT, "toggle-scale-to-fit") \
+ XX(FIV_VIEW_COMMAND_TOGGLE_FIXATE, "toggle-fixate")
#define XX(constant, name) constant,
FIV_VIEW_COMMANDS(XX)
#undef XX
diff --git a/fiv.c b/fiv.c
index dccc85f..73a996b 100644
--- a/fiv.c
+++ b/fiv.c
@@ -497,13 +497,13 @@ show_about_dialog(GtkWidget *parent)
XX(PLAY_PAUSE, B("media-playback-start-symbolic", "Pause")) \
XX(SEEK_FORWARD, B("media-seek-forward-symbolic", "Next frame")) \
XX(S3, gtk_separator_new(GTK_ORIENTATION_HORIZONTAL)) \
+ XX(FIXATE, T("pin2-symbolic", "Keep zoom and position")) \
XX(MINUS, B("zoom-out-symbolic", "Zoom out")) \
XX(SCALE, gtk_label_new("")) \
XX(PLUS, B("zoom-in-symbolic", "Zoom in")) \
XX(ONE, B("zoom-original-symbolic", "Original size")) \
XX(FIT, T("zoom-fit-best-symbolic", "Scale to fit")) \
XX(S4, gtk_separator_new(GTK_ORIENTATION_HORIZONTAL)) \
- /* XX(PIN, B("view-pin-symbolic", "Keep view configuration")) */ \
/* Or perhaps "blur-symbolic", also in the extended set. */ \
XX(COLOR, T("preferences-color-symbolic", "Color management")) \
XX(SMOOTH, T("blend-tool-symbolic", "Smooth scaling")) \
@@ -1523,6 +1523,7 @@ make_view_toolbar(void)
toolbar_command(TOOLBAR_PLUS, FIV_VIEW_COMMAND_ZOOM_IN);
toolbar_command(TOOLBAR_ONE, FIV_VIEW_COMMAND_ZOOM_1);
toolbar_toggler(TOOLBAR_FIT, "scale-to-fit");
+ toolbar_toggler(TOOLBAR_FIXATE, "fixate");
toolbar_toggler(TOOLBAR_COLOR, "enable-cms");
toolbar_toggler(TOOLBAR_SMOOTH, "filter");
toolbar_toggler(TOOLBAR_CHECKERBOARD, "checkerboard");
@@ -1541,6 +1542,8 @@ make_view_toolbar(void)
G_CALLBACK(on_notify_view_playing), NULL);
g_signal_connect(g.view, "notify::scale-to-fit",
G_CALLBACK(on_notify_view_boolean), g.toolbar[TOOLBAR_FIT]);
+ g_signal_connect(g.view, "notify::fixate",
+ G_CALLBACK(on_notify_view_boolean), g.toolbar[TOOLBAR_FIXATE]);
g_signal_connect(g.view, "notify::enable-cms",
G_CALLBACK(on_notify_view_boolean), g.toolbar[TOOLBAR_COLOR]);
g_signal_connect(g.view, "notify::filter",
@@ -1553,6 +1556,7 @@ make_view_toolbar(void)
g_object_notify(G_OBJECT(g.view), "scale");
g_object_notify(G_OBJECT(g.view), "playing");
g_object_notify(G_OBJECT(g.view), "scale-to-fit");
+ g_object_notify(G_OBJECT(g.view), "fixate");
g_object_notify(G_OBJECT(g.view), "enable-cms");
g_object_notify(G_OBJECT(g.view), "filter");
g_object_notify(G_OBJECT(g.view), "checkerboard");
diff --git a/resources/pin2-symbolic.svg b/resources/pin2-symbolic.svg
new file mode 100644
index 0000000..5b5fdab
--- /dev/null
+++ b/resources/pin2-symbolic.svg
@@ -0,0 +1,152 @@
+
+
diff --git a/resources/resources.gresource.xml b/resources/resources.gresource.xml
index 092aed1..f52bb76 100644
--- a/resources/resources.gresource.xml
+++ b/resources/resources.gresource.xml
@@ -10,5 +10,6 @@