window: Use GSignalGroup to watch zoom levels

This allows us to git rid of more expression code.
This commit is contained in:
Christopher Davis 2023-03-02 23:14:14 -05:00 • committed by Sophie Herold
parent aab50af31a
commit 3d445f25fe
2 changed files with 58 additions and 42 deletions

View file

@ -433,6 +433,13 @@ impl LpImageView {
self.imp().sliding_view.current_page().map(|x| x.image()) self.imp().sliding_view.current_page().map(|x| x.image())
} }
pub fn current_image_signals(&self) -> &glib::SignalGroup {
self.imp()
.current_image_signals
.get()
.expect("Signal group should be set up during construction")
}
pub fn current_page(&self) -> Option<LpImagePage> { pub fn current_page(&self) -> Option<LpImagePage> {
self.imp().sliding_view.current_page() self.imp().sliding_view.current_page()
} }

View file

@ -31,7 +31,7 @@ use std::path::{Path, PathBuf};
use crate::config; use crate::config;
use crate::util::{self, Direction, Position}; use crate::util::{self, Direction, Position};
use crate::widgets::{LpImage, LpImagePage, LpImageView, LpPropertiesView}; use crate::widgets::{LpImage, LpImageView, LpPropertiesView};
mod imp { mod imp {
use super::*; use super::*;
@ -227,50 +227,39 @@ mod imp {
gtk::WindowGroup::new().add_window(&*obj); gtk::WindowGroup::new().add_window(&*obj);
obj.set_actions_enabled(false); obj.set_actions_enabled(false);
self.image_view
.property_expression("current-page")
.chain_property::<LpImagePage>("image")
.chain_property::<LpImage>("best-fit")
.watch(
glib::Object::NONE,
// clone! is a macro from glib-rs that allows
// you to easily handle references in callbacks
// without refcycles or leaks.
//
// When you don't want the callback to keep the
// Object alive, pass as @weak. Otherwise, pass
// as @strong. Most of the time you will want
// to use @weak.
glib::clone!(@weak obj => move || {
let enabled = obj
.imp()
.image_view
.current_page()
.map(|page| !page.image().is_best_fit())
.unwrap_or_default();
obj.action_set_enabled("win.zoom-out", enabled); let signal_group = self.image_view.current_image_signals();
}), // clone! is a macro from glib-rs that allows
); // you to easily handle references in callbacks
// without refcycles or leaks.
//
// When you don't want the callback to keep the
// Object alive, pass as @weak. Otherwise, pass
// as @strong. Most of the time you will want
// to use @weak.
signal_group.connect_bind_local(glib::clone!(@weak obj => move |_, _| {
obj.on_zoom_status_changed()
}));
// disable zoom-in if at maximum zoom level let win = &*obj;
self.image_view signal_group.connect_closure(
.property_expression("current-page") "notify::best-fit",
.chain_property::<LpImagePage>("image") false,
.chain_property::<LpImage>("is-max-zoom") // `closure_local!` is similar to `clone`, but you use `@watch` instead of clone.
.watch( // `@watch` means that this signal will be disconnected when the watched object
glib::Object::NONE, // is dropped.
glib::clone!(@weak obj => move || { glib::closure_local!(@watch win => move |_: &LpImage, _: &glib::ParamSpec| {
let enabled = obj win.on_zoom_status_changed();
.imp() }),
.image_view );
.current_page()
.map(|page| !page.image().is_max_zoom())
.unwrap_or_default();
obj.action_set_enabled("win.zoom-in", enabled); signal_group.connect_closure(
}), "notify::is-max-zoom",
); false,
glib::closure_local!(@watch win => move |_: &LpImage, _: &glib::ParamSpec| {
win.on_zoom_status_changed();
}),
);
self.image_view.connect_notify_local( self.image_view.connect_notify_local(
Some("current-page"), Some("current-page"),
@ -360,6 +349,10 @@ mod imp {
}), }),
); );
} }
fn dispose(&self) {
self.obj().disconnect_present_watches();
}
} }
impl WidgetImpl for LpWindow {} impl WidgetImpl for LpWindow {}
@ -657,6 +650,22 @@ impl LpWindow {
} }
} }
fn on_zoom_status_changed(&self) {
let can_zoom_out = self
.image_view()
.current_image()
.map(|image| !image.is_best_fit())
.unwrap_or_default();
let can_zoom_in = self
.image_view()
.current_image()
.map(|image| !image.is_max_zoom())
.unwrap_or_default();
self.action_set_enabled("win.zoom-out", can_zoom_out);
self.action_set_enabled("win.zoom-in", can_zoom_in);
}
// In the LpWindow UI file we define a `gtk::Expression`s // In the LpWindow UI file we define a `gtk::Expression`s
// that is a closure. This closure takes the current `gio::File` // that is a closure. This closure takes the current `gio::File`
// and processes it to return a window title. // and processes it to return a window title.