Constrain minimum zoom level
This commit is contained in:
parent
6e2f38de56
commit
f34f9dd988
3 changed files with 51 additions and 2 deletions
|
|
@ -126,6 +126,10 @@ const SMALL_SCREEN_AREA: f64 = 1280. * 1024.;
|
||||||
/// For small monitors occupy 80% of the screen area
|
/// For small monitors occupy 80% of the screen area
|
||||||
const SMALL_OCCUPY_SCREEN: f64 = 0.8;
|
const SMALL_OCCUPY_SCREEN: f64 = 0.8;
|
||||||
|
|
||||||
|
/// The smallest edge of the image should not be rendered at a pixel size below
|
||||||
|
/// this value, unless the image itself is smaller than this.
|
||||||
|
const SMALLEST_RENDERED_PIXEL_SIZE: f64 = 16.0;
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, Copy, glib::Variant, glib::Enum, PartialEq, Eq)]
|
#[derive(Default, Debug, Clone, Copy, glib::Variant, glib::Enum, PartialEq, Eq)]
|
||||||
#[enum_type(name = "LpFitMode")]
|
#[enum_type(name = "LpFitMode")]
|
||||||
pub enum FitMode {
|
pub enum FitMode {
|
||||||
|
|
@ -206,7 +210,10 @@ mod imp {
|
||||||
/// Determines what `best-fit` does
|
/// Determines what `best-fit` does
|
||||||
#[property(get, set=Self::set_fit_mode, builder(FitMode::default()))]
|
#[property(get, set=Self::set_fit_mode, builder(FitMode::default()))]
|
||||||
pub(super) fit_mode: Cell<FitMode>,
|
pub(super) fit_mode: Cell<FitMode>,
|
||||||
/// Max zoom level is reached, stored to only send signals on change
|
/// Min zoom level is reached, stored to only send signals on change
|
||||||
|
#[property(get, set)]
|
||||||
|
pub(super) is_min_zoom: Cell<bool>,
|
||||||
|
/// Analogous to is_min_zoom
|
||||||
#[property(get, set)]
|
#[property(get, set)]
|
||||||
pub(super) is_max_zoom: Cell<bool>,
|
pub(super) is_max_zoom: Cell<bool>,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,27 @@ impl imp::LpImage {
|
||||||
decoder::tiling::zoom_normalize(zoom) / self.scaling()
|
decoder::tiling::zoom_normalize(zoom) / self.scaling()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Minimal zoom allowed for this image
|
||||||
|
pub(super) fn min_zoom(&self) -> f64 {
|
||||||
|
let (width, height) = self.untransformed_dimensions();
|
||||||
|
|
||||||
|
// If the image is smaller than the smallest rendered pixel size,
|
||||||
|
// block zooming out entirely
|
||||||
|
if (width as f64) < SMALLEST_RENDERED_PIXEL_SIZE
|
||||||
|
|| (height as f64) < SMALLEST_RENDERED_PIXEL_SIZE
|
||||||
|
{
|
||||||
|
1.0
|
||||||
|
}
|
||||||
|
// Prevent the rendered size from going below SMALLEST_RENDERED_PIXEL_SIZE
|
||||||
|
// Original size * zoom factor = rendered size
|
||||||
|
// <=> Zoom factor = rendered size / original size
|
||||||
|
else if width < height {
|
||||||
|
SMALLEST_RENDERED_PIXEL_SIZE / (width as f64)
|
||||||
|
} else {
|
||||||
|
SMALLEST_RENDERED_PIXEL_SIZE / (height as f64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Maximal zoom allowed for this image
|
/// Maximal zoom allowed for this image
|
||||||
pub(super) fn max_zoom(&self) -> f64 {
|
pub(super) fn max_zoom(&self) -> f64 {
|
||||||
let obj = self.obj();
|
let obj = self.obj();
|
||||||
|
|
@ -214,6 +235,15 @@ impl imp::LpImage {
|
||||||
|
|
||||||
tracing::trace!(zoom, animated, snap_best_fit, force_cursor_center, fit_mode=?obj.fit_mode(), "Zoom instruction");
|
tracing::trace!(zoom, animated, snap_best_fit, force_cursor_center, fit_mode=?obj.fit_mode(), "Zoom instruction");
|
||||||
|
|
||||||
|
let min_zoom = self.min_zoom();
|
||||||
|
if zoom <= min_zoom {
|
||||||
|
tracing::trace!(zoom, min_zoom, "Zoom reached minimum zoom level");
|
||||||
|
zoom = min_zoom;
|
||||||
|
obj.set_is_min_zoom(true);
|
||||||
|
} else {
|
||||||
|
obj.set_is_min_zoom(false);
|
||||||
|
}
|
||||||
|
|
||||||
let max_zoom = self.max_zoom();
|
let max_zoom = self.max_zoom();
|
||||||
if zoom >= max_zoom {
|
if zoom >= max_zoom {
|
||||||
tracing::trace!(zoom, max_zoom, "Zoom reached maximum zoom level");
|
tracing::trace!(zoom, max_zoom, "Zoom reached maximum zoom level");
|
||||||
|
|
|
||||||
|
|
@ -257,6 +257,18 @@ mod imp {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
current_image_signals.connect_closure(
|
||||||
|
"notify::is-min-zoom",
|
||||||
|
false,
|
||||||
|
glib::closure_local!(
|
||||||
|
#[watch]
|
||||||
|
obj,
|
||||||
|
move |_: &LpImage, _: &glib::ParamSpec| {
|
||||||
|
obj.update_image_actions_status();
|
||||||
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
current_image_signals.connect_closure(
|
current_image_signals.connect_closure(
|
||||||
"notify::is-max-zoom",
|
"notify::is-max-zoom",
|
||||||
false,
|
false,
|
||||||
|
|
@ -759,7 +771,7 @@ impl LpImageWindow {
|
||||||
let can_zoom_out = self
|
let can_zoom_out = self
|
||||||
.image_view()
|
.image_view()
|
||||||
.current_image()
|
.current_image()
|
||||||
.is_some_and(|image| !image.is_best_fit());
|
.is_some_and(|image| !image.is_best_fit() && !image.is_min_zoom());
|
||||||
let can_zoom_in = self
|
let can_zoom_in = self
|
||||||
.image_view()
|
.image_view()
|
||||||
.current_image()
|
.current_image()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue