diff --git a/data/gtk/help_overlay.ui b/data/gtk/help_overlay.ui index a457927..9a5c3e6 100644 --- a/data/gtk/help_overlay.ui +++ b/data/gtk/help_overlay.ui @@ -156,6 +156,35 @@ + + + Pan View + + + Pan Left + win.pan-left + + + + + Pan Right + win.pan-right + + + + + Pan Up + win.pan-up + + + + + Pan Down + win.pan-down + + + + Gestures diff --git a/src/application.rs b/src/application.rs index dc5fc90..1bb6a78 100644 --- a/src/application.rs +++ b/src/application.rs @@ -195,6 +195,12 @@ impl LpApplication { "win.zoom-out", &["minus", "minus", "KP_Subtract", "KP_Subtract"], ); + + self.set_accels_for_action("win.pan-left", &["Left"]); + self.set_accels_for_action("win.pan-right", &["Right"]); + self.set_accels_for_action("win.pan-up", &["Up"]); + self.set_accels_for_action("win.pan-down", &["Down"]); + self.set_accels_for_action("win.rotate(90.0)", &["R"]); self.set_accels_for_action("win.rotate(-90.0)", &["R"]); diff --git a/src/widgets/image.rs b/src/widgets/image.rs index a895134..8109c37 100644 --- a/src/widgets/image.rs +++ b/src/widgets/image.rs @@ -1053,6 +1053,35 @@ impl LpImage { } } + /// Stepwise scrolls inside an image when zoomed in + pub fn pan(&self, direction: >k::PanDirection) { + let sign = match direction { + gtk::PanDirection::Left | gtk::PanDirection::Up => -1., + gtk::PanDirection::Right | gtk::PanDirection::Down => 1., + _ => { + log::error!("Unkown pan direction {direction:?}"); + return; + } + }; + + let (adjustment, max) = match direction { + gtk::PanDirection::Left | gtk::PanDirection::Right => { + (self.hadjustment(), self.max_hadjustment_value()) + } + gtk::PanDirection::Up | gtk::PanDirection::Down => { + (self.vadjustment(), self.max_vadjustment_value()) + } + _ => { + log::error!("Unkown pan direction {direction:?}"); + return; + } + }; + + let value = (adjustment.value() + sign * adjustment.step_increment()).clamp(0., max); + + adjustment.set_value(value); + } + fn hadjustment(&self) -> gtk::Adjustment { if let Some(adj) = self.imp().hadjustment.borrow().as_ref() { adj.clone() @@ -1109,7 +1138,7 @@ impl LpImage { 0., // upper content_width, - // arrow button step (probably irrelevant) + // arrow button and shortcut step widget_width * 0.1, // page up/down step widget_width * 0.9, @@ -1128,7 +1157,7 @@ impl LpImage { 0., // upper content_height, - // arrow button step (probably irrelevant) + // arrow button and shortcut step widget_height * 0.1, // page up/down step widget_height * 0.9, diff --git a/src/widgets/image_view.rs b/src/widgets/image_view.rs index d805459..44327ec 100644 --- a/src/widgets/image_view.rs +++ b/src/widgets/image_view.rs @@ -408,6 +408,10 @@ impl LpImageView { } } + pub fn current_image(&self) -> Option { + self.imp().sliding_view.current_page().map(|x| x.image()) + } + pub fn current_page(&self) -> Option { self.imp().sliding_view.current_page() } diff --git a/src/window.rs b/src/window.rs index 7d66afe..26ff70b 100644 --- a/src/window.rs +++ b/src/window.rs @@ -125,6 +125,22 @@ mod imp { win.zoom_best_fit(); }); + klass.install_action("win.pan-up", None, move |win, _, _| { + win.pan(>k::PanDirection::Up); + }); + + klass.install_action("win.pan-down", None, move |win, _, _| { + win.pan(>k::PanDirection::Down); + }); + + klass.install_action("win.pan-left", None, move |win, _, _| { + win.pan(>k::PanDirection::Left); + }); + + klass.install_action("win.pan-right", None, move |win, _, _| { + win.pan(>k::PanDirection::Right); + }); + klass.install_action("win.leave-fullscreen", None, move |win, _, _| { win.toggle_fullscreen(false); }); @@ -367,6 +383,12 @@ impl LpWindow { } } + fn pan(&self, direction: >k::PanDirection) { + if let Some(image) = self.imp().image_view.current_image() { + image.pan(direction); + } + } + async fn pick_file(&self) { let filter_store = gio::ListStore::new(gtk::FileFilter::static_type());