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

@ -31,7 +31,7 @@ use std::path::{Path, PathBuf};
use crate::config;
use crate::util::{self, Direction, Position};
use crate::widgets::{LpImage, LpImagePage, LpImageView, LpPropertiesView};
use crate::widgets::{LpImage, LpImageView, LpPropertiesView};
mod imp {
use super::*;
@ -227,50 +227,39 @@ mod imp {
gtk::WindowGroup::new().add_window(&*obj);
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
self.image_view
.property_expression("current-page")
.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();
let win = &*obj;
signal_group.connect_closure(
"notify::best-fit",
false,
// `closure_local!` is similar to `clone`, but you use `@watch` instead of clone.
// `@watch` means that this signal will be disconnected when the watched object
// is dropped.
glib::closure_local!(@watch win => move |_: &LpImage, _: &glib::ParamSpec| {
win.on_zoom_status_changed();
}),
);
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(
Some("current-page"),
@ -360,6 +349,10 @@ mod imp {
}),
);
}
fn dispose(&self) {
self.obj().disconnect_present_watches();
}
}
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
// that is a closure. This closure takes the current `gio::File`
// and processes it to return a window title.