From 577de6bfb72b499b5d317d954ac27e251ebd605b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Eric=20Janouch?= Date: Thu, 20 Nov 2025 11:21:32 +0100 Subject: [PATCH] Add a dialog to set precise image scale --- fiv-view.c | 37 +++++++++++++++++++++++++++++++++++++ fiv-view.h | 1 + fiv.c | 20 +++++++++++--------- 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/fiv-view.c b/fiv-view.c index cd3cc51..f13c757 100644 --- a/fiv-view.c +++ b/fiv-view.c @@ -1438,6 +1438,41 @@ get_toplevel(GtkWidget *widget) return NULL; } +static void +zoom_ask(FivView *self) +{ + GtkWidget *dialog = gtk_dialog_new_with_buttons("Set zoom level", + get_toplevel(GTK_WIDGET(self)), + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL | + GTK_DIALOG_USE_HEADER_BAR, + "_OK", GTK_RESPONSE_ACCEPT, "_Cancel", GTK_RESPONSE_CANCEL, NULL); + + GtkAdjustment *adjustment = gtk_adjustment_new( + self->scale * 100, 0., 100000., 1., 10., 0.); + GtkWidget *spin = gtk_spin_button_new(adjustment, 1., 0); + gtk_entry_set_activates_default(GTK_ENTRY(spin), TRUE); + + GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6); + gtk_box_pack_start(GTK_BOX(box), gtk_label_new("Zoom:"), FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(box), spin, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(box), gtk_label_new("%"), FALSE, FALSE, 0); + + GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + g_object_set(content, "margin", 12, NULL); + gtk_box_set_spacing(GTK_BOX(content), 6); + gtk_container_add(GTK_CONTAINER(content), box); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); + gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), TRUE); + gtk_widget_show_all(dialog); + + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { + double value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)); + if (value > 0) + set_scale(self, value / 100., NULL); + } + gtk_widget_destroy(dialog); +} + static void copy(FivView *self) { @@ -2028,6 +2063,8 @@ fiv_view_command(FivView *self, FivViewCommand command) set_scale(self, self->scale / SCALE_STEP, NULL); break; case FIV_VIEW_COMMAND_ZOOM_1: set_scale(self, 1.0, NULL); + break; case FIV_VIEW_COMMAND_ZOOM_ASK: + zoom_ask(self); break; case FIV_VIEW_COMMAND_FIT_WIDTH: set_scale_to_fit_width(self); break; case FIV_VIEW_COMMAND_FIT_HEIGHT: diff --git a/fiv-view.h b/fiv-view.h index d43480b..768d988 100644 --- a/fiv-view.h +++ b/fiv-view.h @@ -59,6 +59,7 @@ typedef enum _FivViewCommand { XX(FIV_VIEW_COMMAND_ZOOM_IN, "zoom-in") \ XX(FIV_VIEW_COMMAND_ZOOM_OUT, "zoom-out") \ XX(FIV_VIEW_COMMAND_ZOOM_1, "zoom-1") \ + XX(FIV_VIEW_COMMAND_ZOOM_ASK, "zoom-ask") \ 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") \ diff --git a/fiv.c b/fiv.c index cab6c1f..bb192db 100644 --- a/fiv.c +++ b/fiv.c @@ -799,7 +799,7 @@ enum { 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(SCALE, B(NULL, "Set zoom level")) \ 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")) \ @@ -1815,8 +1815,10 @@ static GtkWidget * make_toolbar_button(const char *symbolic, const char *tooltip) { GtkWidget *button = gtk_button_new(); - gtk_button_set_image(GTK_BUTTON(button), - gtk_image_new_from_icon_name(symbolic, GTK_ICON_SIZE_BUTTON)); + if (symbolic) { + gtk_button_set_image(GTK_BUTTON(button), + gtk_image_new_from_icon_name(symbolic, GTK_ICON_SIZE_BUTTON)); + } gtk_widget_set_tooltip_text(button, tooltip); gtk_widget_set_focus_on_click(button, FALSE); gtk_style_context_add_class( @@ -1962,7 +1964,8 @@ on_notify_view_scale( g_object_get(object, g_param_spec_get_name(param_spec), &scale, NULL); gchar *scale_str = g_strdup_printf("%.0f%%", round(scale * 100)); - gtk_label_set_text(GTK_LABEL(g.toolbar[TOOLBAR_SCALE]), scale_str); + gtk_label_set_text(GTK_LABEL( + gtk_bin_get_child(GTK_BIN(g.toolbar[TOOLBAR_SCALE]))), scale_str); g_free(scale_str); // FIXME: The label doesn't immediately assume its new width. @@ -2047,13 +2050,11 @@ make_view_toolbar(void) TOOLBAR(XX) #undef XX - gtk_widget_set_margin_start(g.toolbar[TOOLBAR_SCALE], 5); - gtk_widget_set_margin_end(g.toolbar[TOOLBAR_SCALE], 5); - + GtkWidget *scale_label = gtk_label_new(""); + gtk_container_add(GTK_CONTAINER(g.toolbar[TOOLBAR_SCALE]), scale_label); // So that the width doesn't jump around in the usual zoom range. // Ideally, we'd measure the widest digit and use width(NNN%). - gtk_label_set_width_chars(GTK_LABEL(g.toolbar[TOOLBAR_SCALE]), 5); - gtk_widget_set_halign(g.toolbar[TOOLBAR_SCALE], GTK_ALIGN_CENTER); + gtk_label_set_width_chars(GTK_LABEL(scale_label), 5); // GtkStatusBar solves a problem we do not have here. GtkWidget *view_toolbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); @@ -2084,6 +2085,7 @@ make_view_toolbar(void) toolbar_command(TOOLBAR_PLAY_PAUSE, FIV_VIEW_COMMAND_TOGGLE_PLAYBACK); toolbar_command(TOOLBAR_SEEK_FORWARD, FIV_VIEW_COMMAND_FRAME_NEXT); toolbar_command(TOOLBAR_MINUS, FIV_VIEW_COMMAND_ZOOM_OUT); + toolbar_command(TOOLBAR_SCALE, FIV_VIEW_COMMAND_ZOOM_ASK); 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");