image: Limit zoom to 2000%

This commit is contained in:
Sophie Herold 2022-11-28 03:23:06 +01:00
parent d6ab100062
commit c1a3cc353d
2 changed files with 58 additions and 11 deletions

View file

@ -27,12 +27,14 @@ use std::cell::{Cell, RefCell};
use crate::image_metadata::ImageMetadata;
static ZOOM_ANIMATION_DURATION: u32 = 200;
static ROTATION_ANIMATION_DURATION: u32 = 200;
const ZOOM_ANIMATION_DURATION: u32 = 200;
const ROTATION_ANIMATION_DURATION: u32 = 200;
static ZOOM_FACTOR_BUTTON: f64 = 1.5;
static ZOOM_FACTOR_WHEEL: f64 = 1.3;
static ZOOM_FACTOR_WHEEL_HI_RES: f64 = 0.1;
const ZOOM_FACTOR_BUTTON: f64 = 1.5;
const ZOOM_FACTOR_WHEEL: f64 = 1.3;
const ZOOM_FACTOR_WHEEL_HI_RES: f64 = 0.1;
const MAX_ZOOM_LEVEL: f64 = 20.0;
mod imp {
use super::*;
@ -63,6 +65,8 @@ mod imp {
/// Always fit image into window, causes `zoom` to change automatically
pub best_fit: Cell<bool>,
/// Max zoom level is reached, stored to only send signals on change
pub max_zoom: Cell<bool>,
/// Horizontal scrolling
pub hadjustment: RefCell<Option<gtk::Adjustment>>,
@ -113,6 +117,9 @@ mod imp {
glib::ParamSpecBoolean::builder("best-fit")
.explicit_notify()
.build(),
glib::ParamSpecBoolean::builder("is-max-zoom")
.read_only()
.build(),
glib::ParamSpecOverride::for_interface::<gtk::Scrollable>("hadjustment"),
glib::ParamSpecOverride::for_interface::<gtk::Scrollable>("vadjustment"),
glib::ParamSpecOverride::for_interface::<gtk::Scrollable>("hscroll-policy"),
@ -131,6 +138,7 @@ mod imp {
"mirrored" => obj.mirrored().to_value(),
"zoom" => obj.zoom().to_value(),
"best-fit" => obj.is_best_fit().to_value(),
"is-max-zoom" => obj.is_max_zoom().to_value(),
// don't use getter functions here sicne they can return a fake adjustment
"hadjustment" => self.hadjustment.borrow().to_value(),
"vadjustment" => self.vadjustment.borrow().to_value(),
@ -358,7 +366,8 @@ mod imp {
obj.zoom_to(obj.zoom_level_best_fit_for_rotation(rotation_target));
} else {
obj.set_best_fit(false);
obj.imp().zoom_target.set(obj.zoom());
// rubberband if over highest zoom level and sets `zoom_target`
obj.zoom_to(obj.zoom());
};
}));
@ -612,6 +621,19 @@ impl LpImage {
self.set_zoom_aiming(zoom, self.imp().pointer_position.get())
}
pub fn is_max_zoom(&self) -> bool {
self.imp().max_zoom.get()
}
fn set_max_zoom(&self, value: bool) {
if self.is_max_zoom() == value {
return;
}
self.imp().max_zoom.set(value);
self.notify("is-max-zoom");
}
/// Set zoom level aiming for given position or center if not available
fn set_zoom_aiming(&self, zoom: f64, aiming: Option<(f64, f64)>) {
if zoom == self.zoom() || zoom <= 0. {
@ -739,11 +761,20 @@ impl LpImage {
}
/// Zoom to specific level with animation
pub fn zoom_to(&self, zoom: f64) {
pub fn zoom_to(&self, mut zoom: f64) {
if zoom >= MAX_ZOOM_LEVEL {
zoom = MAX_ZOOM_LEVEL;
self.set_max_zoom(true);
} else {
self.set_max_zoom(false);
}
log::debug!("Zoom to {zoom:.3}");
self.imp().zoom_target.set(zoom);
// abort if already at correct zoom level
if zoom == self.zoom() && zoom == self.imp().zoom_target.get() {
if zoom == self.zoom() {
log::debug!("Already at correct zoom level");
return;
}
@ -767,8 +798,6 @@ impl LpImage {
let animation = self.zoom_animation();
self.imp().zoom_target.set(zoom);
animation.set_value_from(self.zoom());
animation.set_value_to(zoom);
animation.play();

View file

@ -195,6 +195,25 @@ mod imp {
}),
);
// disable zoom-in if at maximum zoom level
self.image_view
.property_expression("current-page-strict")
.chain_property::<LpImagePage>("image")
.chain_property::<LpImage>("is-max-zoom")
.watch(
glib::Object::NONE,
glib::clone!(@weak obj => move || {
let enabled = obj
.imp()
.image_view
.current_page()
.map(|page| !page.image().is_max_zoom())
.unwrap_or_default();
obj.action_set_enabled("win.zoom-in", enabled);
}),
);
self.status_page
.set_icon_name(Some(&format!("{}-symbolic", config::APP_ID)));
@ -426,7 +445,6 @@ impl LpWindow {
self.action_set_enabled("win.rotate", enabled);
self.action_set_enabled("win.copy", enabled);
self.action_set_enabled("win.zoom-best-fit", enabled);
self.action_set_enabled("win.zoom-in", enabled);
self.action_set_enabled("win.zoom-to", enabled);
self.action_set_enabled("win.toggle-properties", enabled);
}