window: Use GSignalGroup to watch zoom levels
This allows us to git rid of more expression code.
This commit is contained in:
parent
aab50af31a
commit
3d445f25fe
2 changed files with 58 additions and 42 deletions
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue