code: Use new glib::clone! syntax
This commit is contained in:
parent
44bd845be4
commit
e9dc3d810c
16 changed files with 801 additions and 464 deletions
|
|
@ -99,11 +99,13 @@ impl LpFileModel {
|
||||||
directory.monitor_directory(gio::FileMonitorFlags::WATCH_MOVES, gio::Cancellable::NONE);
|
directory.monitor_directory(gio::FileMonitorFlags::WATCH_MOVES, gio::Cancellable::NONE);
|
||||||
match monitor {
|
match monitor {
|
||||||
Ok(monitor) => {
|
Ok(monitor) => {
|
||||||
monitor.connect_changed(
|
monitor.connect_changed(glib::clone!(
|
||||||
glib::clone!(@weak self as obj => move |_monitor, file_a, file_b, event| {
|
#[weak(rename_to = obj)]
|
||||||
|
self,
|
||||||
|
move |_monitor, file_a, file_b, event| {
|
||||||
obj.file_monitor_cb(event, file_a, file_b);
|
obj.file_monitor_cb(event, file_a, file_b);
|
||||||
}),
|
}
|
||||||
);
|
));
|
||||||
self.imp().monitor.set(monitor).unwrap();
|
self.imp().monitor.set(monitor).unwrap();
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|
|
||||||
|
|
@ -98,12 +98,14 @@ mod imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_drop_target(&self, drop_target: gtk::DropTarget) {
|
pub fn set_drop_target(&self, drop_target: gtk::DropTarget) {
|
||||||
drop_target.connect_current_drop_notify(
|
drop_target.connect_current_drop_notify(glib::clone!(
|
||||||
glib::clone!(@weak self.revealer as revealer => move |target| {
|
#[weak(rename_to = revealer)]
|
||||||
|
self.revealer,
|
||||||
|
move |target| {
|
||||||
let reveal = target.current_drop().is_some();
|
let reveal = target.current_drop().is_some();
|
||||||
revealer.set_reveal_child(reveal);
|
revealer.set_reveal_child(reveal);
|
||||||
}),
|
}
|
||||||
);
|
));
|
||||||
|
|
||||||
self.drop_target.set(drop_target).unwrap();
|
self.drop_target.set(drop_target).unwrap();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,23 +70,29 @@ impl LpErrorDetails {
|
||||||
let imp = obj.imp();
|
let imp = obj.imp();
|
||||||
imp.message.buffer().set_text(text);
|
imp.message.buffer().set_text(text);
|
||||||
|
|
||||||
imp.copy
|
imp.copy.connect_clicked(glib::clone!(
|
||||||
.connect_clicked(glib::clone!(@weak obj => move |_| {
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| {
|
||||||
let buffer = obj.imp().message.buffer();
|
let buffer = obj.imp().message.buffer();
|
||||||
let (start, end) = buffer.bounds();
|
let (start, end) = buffer.bounds();
|
||||||
obj.display()
|
obj.display()
|
||||||
.clipboard()
|
.clipboard()
|
||||||
.set_text(buffer.text(&start, &end, true).as_str())
|
.set_text(buffer.text(&start, &end, true).as_str())
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
imp.report
|
imp.report.connect_clicked(glib::clone!(
|
||||||
.connect_clicked(glib::clone!(@weak obj => move |_| {
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| {
|
||||||
gtk::UriLauncher::new("https://gitlab.gnome.org/sophie-h/glycin/-/issues").launch(
|
gtk::UriLauncher::new("https://gitlab.gnome.org/sophie-h/glycin/-/issues").launch(
|
||||||
obj.root().and_downcast_ref::<gtk::Window>(),
|
obj.root().and_downcast_ref::<gtk::Window>(),
|
||||||
gio::Cancellable::NONE,
|
gio::Cancellable::NONE,
|
||||||
|_| {},
|
|_| {},
|
||||||
);
|
);
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
obj.present(Some(root));
|
obj.present(Some(root));
|
||||||
obj
|
obj
|
||||||
|
|
|
||||||
|
|
@ -289,21 +289,36 @@ mod imp {
|
||||||
|
|
||||||
surface_signals.connect_notify_local(
|
surface_signals.connect_notify_local(
|
||||||
Some("scale"),
|
Some("scale"),
|
||||||
glib::clone!(@weak obj => move |_, _| {
|
glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_, _| {
|
||||||
log::debug!("Scale changed signal");
|
log::debug!("Scale changed signal");
|
||||||
obj.queue_resize();
|
obj.queue_resize();
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
obj.connect_realize(glib::clone!(@weak surface_signals => move |obj| {
|
obj.connect_realize(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
surface_signals,
|
||||||
|
move |obj| {
|
||||||
surface_signals.set_target(obj.native().and_then(|x| x.surface()).as_ref());
|
surface_signals.set_target(obj.native().and_then(|x| x.surface()).as_ref());
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
obj.connect_unrealize(glib::clone!(@weak surface_signals => move |_| {
|
obj.connect_unrealize(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
surface_signals,
|
||||||
|
move |_| {
|
||||||
surface_signals.set_target(gdk::Surface::NONE);
|
surface_signals.set_target(gdk::Surface::NONE);
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
adw::StyleManager::default().connect_dark_notify(glib::clone!(@weak obj => move |_| {
|
adw::StyleManager::default().connect_dark_notify(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| {
|
||||||
glib::spawn_future_local(async move {
|
glib::spawn_future_local(async move {
|
||||||
let imp = obj.imp();
|
let imp = obj.imp();
|
||||||
|
|
||||||
|
|
@ -313,7 +328,8 @@ mod imp {
|
||||||
obj.queue_draw();
|
obj.queue_draw();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dispose(&self) {
|
fn dispose(&self) {
|
||||||
|
|
|
||||||
|
|
@ -29,32 +29,57 @@ impl imp::LpImage {
|
||||||
|
|
||||||
// Needed for having the current cursor position available
|
// Needed for having the current cursor position available
|
||||||
let motion_controller = gtk::EventControllerMotion::new();
|
let motion_controller = gtk::EventControllerMotion::new();
|
||||||
motion_controller.connect_enter(glib::clone!(@weak obj => move |_, x, y| {
|
motion_controller.connect_enter(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_, x, y| {
|
||||||
obj.imp().pointer_position.set(Some((x, y)));
|
obj.imp().pointer_position.set(Some((x, y)));
|
||||||
}));
|
}
|
||||||
motion_controller.connect_motion(glib::clone!(@weak obj => move |_, x, y| {
|
));
|
||||||
|
motion_controller.connect_motion(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_, x, y| {
|
||||||
obj.imp().pointer_position.set(Some((x, y)));
|
obj.imp().pointer_position.set(Some((x, y)));
|
||||||
}));
|
}
|
||||||
motion_controller.connect_leave(glib::clone!(@weak obj => move |_| {
|
));
|
||||||
|
motion_controller.connect_leave(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| {
|
||||||
obj.imp().pointer_position.set(None);
|
obj.imp().pointer_position.set(None);
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
obj.add_controller(motion_controller);
|
obj.add_controller(motion_controller);
|
||||||
|
|
||||||
// Zoom via scroll wheels etc
|
// Zoom via scroll wheels etc
|
||||||
let scroll_controller =
|
let scroll_controller =
|
||||||
gtk::EventControllerScroll::new(gtk::EventControllerScrollFlags::BOTH_AXES);
|
gtk::EventControllerScroll::new(gtk::EventControllerScrollFlags::BOTH_AXES);
|
||||||
|
|
||||||
scroll_controller.connect_scroll_end(glib::clone!(@weak obj => move |event| {
|
scroll_controller.connect_scroll_end(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |event| {
|
||||||
// Avoid kinetc scrolling in scrolled window after zooming
|
// Avoid kinetc scrolling in scrolled window after zooming
|
||||||
if event.current_event_state().contains(gdk::ModifierType::CONTROL_MASK) {
|
if event
|
||||||
|
.current_event_state()
|
||||||
|
.contains(gdk::ModifierType::CONTROL_MASK)
|
||||||
|
{
|
||||||
obj.imp().cancel_deceleration();
|
obj.imp().cancel_deceleration();
|
||||||
}
|
}
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
scroll_controller.connect_scroll(glib::clone!(@weak obj => @default-return glib::Propagation::Proceed, move |event, _, y| {
|
scroll_controller.connect_scroll(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
#[upgrade_or_else]
|
||||||
|
|| glib::Propagation::Proceed,
|
||||||
|
move |event, _, y| {
|
||||||
let imp = obj.imp();
|
let imp = obj.imp();
|
||||||
let state = event.current_event_state();
|
let state = event.current_event_state();
|
||||||
if event.current_event_device().map(|x| x.source()) == Some(gdk::InputSource::Touchpad)
|
if event.current_event_device().map(|x| x.source())
|
||||||
|
== Some(gdk::InputSource::Touchpad)
|
||||||
{
|
{
|
||||||
// Touchpads do zoom via gestures, expect when Ctrl key is pressed
|
// Touchpads do zoom via gestures, expect when Ctrl key is pressed
|
||||||
if !state.contains(gdk::ModifierType::CONTROL_MASK) {
|
if !state.contains(gdk::ModifierType::CONTROL_MASK) {
|
||||||
|
|
@ -71,8 +96,9 @@ impl imp::LpImage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use exponential scaling since zoom is always multiplicative with the existing value
|
// Use exponential scaling since zoom is always multiplicative with the existing
|
||||||
// This is the right thing since `exp(n/2)^2 == exp(n)` (two small steps are the same as one larger step)
|
// value This is the right thing since `exp(n/2)^2 == exp(n)`
|
||||||
|
// (two small steps are the same as one larger step)
|
||||||
let (zoom_factor, animated) = match event.unit() {
|
let (zoom_factor, animated) = match event.unit() {
|
||||||
gdk::ScrollUnit::Wheel => (
|
gdk::ScrollUnit::Wheel => (
|
||||||
f64::exp(-y * f64::ln(ZOOM_FACTOR_SCROLL_WHEEL)),
|
f64::exp(-y * f64::ln(ZOOM_FACTOR_SCROLL_WHEEL)),
|
||||||
|
|
@ -97,7 +123,8 @@ impl imp::LpImage {
|
||||||
|
|
||||||
// do not propagate event to scrolled window
|
// do not propagate event to scrolled window
|
||||||
glib::Propagation::Stop
|
glib::Propagation::Stop
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
obj.add_controller(scroll_controller);
|
obj.add_controller(scroll_controller);
|
||||||
}
|
}
|
||||||
|
|
@ -108,8 +135,10 @@ impl imp::LpImage {
|
||||||
// Double click for fullscreen (mouse/touchpad) or zoom (touch screen)
|
// Double click for fullscreen (mouse/touchpad) or zoom (touch screen)
|
||||||
let left_click_gesture = gtk::GestureClick::builder().button(1).build();
|
let left_click_gesture = gtk::GestureClick::builder().button(1).build();
|
||||||
obj.add_controller(left_click_gesture.clone());
|
obj.add_controller(left_click_gesture.clone());
|
||||||
left_click_gesture.connect_pressed(
|
left_click_gesture.connect_pressed(glib::clone!(
|
||||||
glib::clone!(@weak obj => move |gesture, n_press, x, y| {
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |gesture, n_press, x, y| {
|
||||||
// only handle double clicks
|
// only handle double clicks
|
||||||
if n_press != 2 {
|
if n_press != 2 {
|
||||||
return;
|
return;
|
||||||
|
|
@ -129,14 +158,17 @@ impl imp::LpImage {
|
||||||
// fullscreen
|
// fullscreen
|
||||||
obj.activate_action("win.toggle-fullscreen", None).unwrap();
|
obj.activate_action("win.toggle-fullscreen", None).unwrap();
|
||||||
}
|
}
|
||||||
}),
|
}
|
||||||
);
|
));
|
||||||
|
|
||||||
// Drag for moving image around
|
// Drag for moving image around
|
||||||
let drag_gesture = gtk::GestureDrag::builder().button(0).build();
|
let drag_gesture = gtk::GestureDrag::builder().button(0).build();
|
||||||
obj.add_controller(drag_gesture.clone());
|
obj.add_controller(drag_gesture.clone());
|
||||||
|
|
||||||
drag_gesture.connect_drag_begin(glib::clone!(@weak obj => move |gesture, _, _| {
|
drag_gesture.connect_drag_begin(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |gesture, _, _| {
|
||||||
let imp = obj.imp();
|
let imp = obj.imp();
|
||||||
|
|
||||||
// Allow only left and middle button
|
// Allow only left and middle button
|
||||||
|
|
@ -156,9 +188,13 @@ impl imp::LpImage {
|
||||||
// let drag and drop handle the events when not scrollable
|
// let drag and drop handle the events when not scrollable
|
||||||
gesture.set_state(gtk::EventSequenceState::Denied);
|
gesture.set_state(gtk::EventSequenceState::Denied);
|
||||||
}
|
}
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
drag_gesture.connect_drag_update(glib::clone!(@weak obj => move |_, x1, y1| {
|
drag_gesture.connect_drag_update(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_, x1, y1| {
|
||||||
let imp = obj.imp();
|
let imp = obj.imp();
|
||||||
if let Some((x0, y0)) = obj.imp().last_drag_value.get() {
|
if let Some((x0, y0)) = obj.imp().last_drag_value.get() {
|
||||||
imp.set_hadj_value(imp.hadj_value() - x1 + x0);
|
imp.set_hadj_value(imp.hadj_value() - x1 + x0);
|
||||||
|
|
@ -166,21 +202,32 @@ impl imp::LpImage {
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.imp().last_drag_value.set(Some((x1, y1)));
|
obj.imp().last_drag_value.set(Some((x1, y1)));
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
drag_gesture.connect_drag_end(glib::clone!(@weak obj => move |_, _, _| {
|
drag_gesture.connect_drag_end(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_, _, _| {
|
||||||
obj.set_cursor(None);
|
obj.set_cursor(None);
|
||||||
obj.imp().last_drag_value.set(None);
|
obj.imp().last_drag_value.set(None);
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
// Rotate
|
// Rotate
|
||||||
let rotation_gesture = gtk::GestureRotate::new();
|
let rotation_gesture = gtk::GestureRotate::new();
|
||||||
obj.add_controller(rotation_gesture.clone());
|
obj.add_controller(rotation_gesture.clone());
|
||||||
|
|
||||||
rotation_gesture
|
rotation_gesture.connect_begin(glib::clone!(
|
||||||
.connect_begin(glib::clone!(@weak obj => move |_, _| obj.imp().cancel_deceleration()));
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_, _| obj.imp().cancel_deceleration()
|
||||||
|
));
|
||||||
|
|
||||||
rotation_gesture.connect_angle_changed(glib::clone!(@weak obj => move |gesture, _, _| {
|
rotation_gesture.connect_angle_changed(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |gesture, _, _| {
|
||||||
let angle = gesture.angle_delta().to_degrees();
|
let angle = gesture.angle_delta().to_degrees();
|
||||||
|
|
||||||
// Only reset rotation if scale gesture is locked in
|
// Only reset rotation if scale gesture is locked in
|
||||||
|
|
@ -205,27 +252,39 @@ impl imp::LpImage {
|
||||||
};
|
};
|
||||||
|
|
||||||
obj.set_rotation(obj.imp().rotation_target.get() + angle - correction);
|
obj.set_rotation(obj.imp().rotation_target.get() + angle - correction);
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
rotation_gesture.connect_end(glib::clone!(@weak obj => move |_, _| {
|
rotation_gesture.connect_end(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_, _| {
|
||||||
log::debug!("Rotate gesture ended");
|
log::debug!("Rotate gesture ended");
|
||||||
|
|
||||||
let angle = (obj.rotation() / 90.).round() * 90. - obj.imp().rotation_target.get();
|
let angle = (obj.rotation() / 90.).round() * 90. - obj.imp().rotation_target.get();
|
||||||
obj.rotate_by(angle);
|
obj.rotate_by(angle);
|
||||||
obj.imp().locked_gestured.set(None);
|
obj.imp().locked_gestured.set(None);
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
// Zoom
|
// Zoom
|
||||||
let zoom_gesture = gtk::GestureZoom::new();
|
let zoom_gesture = gtk::GestureZoom::new();
|
||||||
obj.add_controller(zoom_gesture.clone());
|
obj.add_controller(zoom_gesture.clone());
|
||||||
|
|
||||||
zoom_gesture.connect_begin(glib::clone!(@weak obj => move |gesture, _| {
|
zoom_gesture.connect_begin(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |gesture, _| {
|
||||||
let imp = obj.imp();
|
let imp = obj.imp();
|
||||||
imp.cancel_deceleration();
|
imp.cancel_deceleration();
|
||||||
imp.zoom_gesture_center.set(gesture.bounding_box_center());
|
imp.zoom_gesture_center.set(gesture.bounding_box_center());
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
zoom_gesture.connect_scale_changed(glib::clone!(@weak obj => move |gesture, scale| {
|
zoom_gesture.connect_scale_changed(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |gesture, scale| {
|
||||||
let imp = obj.imp();
|
let imp = obj.imp();
|
||||||
|
|
||||||
let zoom = imp.zoom_target.get() * scale;
|
let zoom = imp.zoom_target.get() * scale;
|
||||||
|
|
@ -233,10 +292,9 @@ impl imp::LpImage {
|
||||||
// Move image with fingers on touchscreens
|
// Move image with fingers on touchscreens
|
||||||
if gesture.device().map(|x| x.source()) == Some(gdk::InputSource::Touchscreen) {
|
if gesture.device().map(|x| x.source()) == Some(gdk::InputSource::Touchscreen) {
|
||||||
if let p1 @ Some((x1, y1)) = gesture.bounding_box_center() {
|
if let p1 @ Some((x1, y1)) = gesture.bounding_box_center() {
|
||||||
|
|
||||||
if let Some((x0, y0)) = imp.zoom_gesture_center.get() {
|
if let Some((x0, y0)) = imp.zoom_gesture_center.get() {
|
||||||
imp.set_hadj_value(imp.hadj_value() + x0 - x1);
|
imp.set_hadj_value(imp.hadj_value() + x0 - x1);
|
||||||
imp.set_vadj_value(imp.vadj_value()+ y0 - y1);
|
imp.set_vadj_value(imp.vadj_value() + y0 - y1);
|
||||||
} else {
|
} else {
|
||||||
log::warn!("Zoom bounding box center: No previous value");
|
log::warn!("Zoom bounding box center: No previous value");
|
||||||
}
|
}
|
||||||
|
|
@ -257,9 +315,13 @@ impl imp::LpImage {
|
||||||
}
|
}
|
||||||
|
|
||||||
imp.set_zoom_aiming(zoom, imp.zoom_gesture_center.get());
|
imp.set_zoom_aiming(zoom, imp.zoom_gesture_center.get());
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
zoom_gesture.connect_end(glib::clone!(@weak obj => move |_, _| {
|
zoom_gesture.connect_end(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_, _| {
|
||||||
let imp = obj.imp();
|
let imp = obj.imp();
|
||||||
log::debug!("Zoom gesture ended");
|
log::debug!("Zoom gesture ended");
|
||||||
|
|
||||||
|
|
@ -272,7 +334,8 @@ impl imp::LpImage {
|
||||||
};
|
};
|
||||||
|
|
||||||
imp.locked_gestured.set(None);
|
imp.locked_gestured.set(None);
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
zoom_gesture.group_with(&rotation_gesture);
|
zoom_gesture.group_with(&rotation_gesture);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,9 +52,13 @@ impl imp::LpImage {
|
||||||
let monitor =
|
let monitor =
|
||||||
file.monitor_file(gio::FileMonitorFlags::WATCH_MOVES, gio::Cancellable::NONE);
|
file.monitor_file(gio::FileMonitorFlags::WATCH_MOVES, gio::Cancellable::NONE);
|
||||||
if let Ok(m) = &monitor {
|
if let Ok(m) = &monitor {
|
||||||
m.connect_changed(glib::clone!(@weak obj => move |_, file_a, file_b, event| {
|
m.connect_changed(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_, file_a, file_b, event| {
|
||||||
obj.imp().file_changed(event, file_a, file_b);
|
obj.imp().file_changed(event, file_a, file_b);
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.file_monitor.replace(monitor.ok());
|
self.file_monitor.replace(monitor.ok());
|
||||||
|
|
@ -90,7 +94,10 @@ impl imp::LpImage {
|
||||||
new_tiles
|
new_tiles
|
||||||
});
|
});
|
||||||
if self.background_color.borrow().is_none() {
|
if self.background_color.borrow().is_none() {
|
||||||
glib::spawn_future_local(glib::clone!(@weak obj => async move {
|
glib::spawn_future_local(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
async move {
|
||||||
let imp = obj.imp();
|
let imp = obj.imp();
|
||||||
|
|
||||||
let color = imp.background_color_guess().await;
|
let color = imp.background_color_guess().await;
|
||||||
|
|
@ -98,7 +105,8 @@ impl imp::LpImage {
|
||||||
if obj.is_mapped() {
|
if obj.is_mapped() {
|
||||||
obj.queue_draw();
|
obj.queue_draw();
|
||||||
}
|
}
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DecoderUpdate::Error(err) => {
|
DecoderUpdate::Error(err) => {
|
||||||
|
|
@ -109,8 +117,13 @@ impl imp::LpImage {
|
||||||
// Just load the first frame
|
// Just load the first frame
|
||||||
self.frame_buffer.next_frame();
|
self.frame_buffer.next_frame();
|
||||||
} else {
|
} else {
|
||||||
let callback_id = obj
|
let callback_id = obj.add_tick_callback(glib::clone!(
|
||||||
.add_tick_callback(glib::clone!(@weak self as obj => @default-return glib::ControlFlow::Break, move |_, clock| obj.tick_callback(clock)));
|
#[weak(rename_to = obj)]
|
||||||
|
self,
|
||||||
|
#[upgrade_or_else]
|
||||||
|
|| glib::ControlFlow::Break,
|
||||||
|
move |_, clock| obj.tick_callback(clock)
|
||||||
|
));
|
||||||
self.tick_callback.replace(Some(callback_id));
|
self.tick_callback.replace(Some(callback_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,14 @@ impl imp::LpImage {
|
||||||
|
|
||||||
let adjustment = hadjustment.unwrap_or_default();
|
let adjustment = hadjustment.unwrap_or_default();
|
||||||
|
|
||||||
adjustment.connect_value_changed(glib::clone!(@weak obj => move |_| {
|
adjustment.connect_value_changed(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| {
|
||||||
obj.imp().request_tiles();
|
obj.imp().request_tiles();
|
||||||
obj.queue_draw();
|
obj.queue_draw();
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
self.hadjustment.replace(adjustment);
|
self.hadjustment.replace(adjustment);
|
||||||
self.configure_adjustments();
|
self.configure_adjustments();
|
||||||
|
|
@ -42,10 +46,14 @@ impl imp::LpImage {
|
||||||
|
|
||||||
let adjustment = vadjustment.unwrap_or_default();
|
let adjustment = vadjustment.unwrap_or_default();
|
||||||
|
|
||||||
adjustment.connect_value_changed(glib::clone!(@weak obj => move |_| {
|
adjustment.connect_value_changed(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| {
|
||||||
obj.imp().request_tiles();
|
obj.imp().request_tiles();
|
||||||
obj.queue_draw();
|
obj.queue_draw();
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
self.vadjustment.replace(adjustment);
|
self.vadjustment.replace(adjustment);
|
||||||
self.configure_adjustments();
|
self.configure_adjustments();
|
||||||
|
|
|
||||||
|
|
@ -264,11 +264,13 @@ impl imp::LpImage {
|
||||||
let animation = self.zoom_animation();
|
let animation = self.zoom_animation();
|
||||||
|
|
||||||
if force_cursor_center {
|
if force_cursor_center {
|
||||||
animation.set_target(&adw::CallbackAnimationTarget::new(
|
animation.set_target(&adw::CallbackAnimationTarget::new(glib::clone!(
|
||||||
glib::clone!(@weak obj => move |zoom| {
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |zoom| {
|
||||||
obj.imp().set_zoom_aiming(zoom, None);
|
obj.imp().set_zoom_aiming(zoom, None);
|
||||||
}),
|
}
|
||||||
));
|
)));
|
||||||
} else {
|
} else {
|
||||||
// Set new point in image that should remain under the cursor while zooming if
|
// Set new point in image that should remain under the cursor while zooming if
|
||||||
// there isn't one already
|
// there isn't one already
|
||||||
|
|
@ -304,11 +306,15 @@ impl imp::LpImage {
|
||||||
.target(&adw::CallbackAnimationTarget::new(|_| {}))
|
.target(&adw::CallbackAnimationTarget::new(|_| {}))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
animation.connect_done(glib::clone!(@weak obj => move |_| {
|
animation.connect_done(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| {
|
||||||
let imp = obj.imp();
|
let imp = obj.imp();
|
||||||
imp.zoom_cursor_target.set(None);
|
imp.zoom_cursor_target.set(None);
|
||||||
imp.set_zoom_target(obj.imp().zoom_target.get());
|
imp.set_zoom_target(obj.imp().zoom_target.get());
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
animation
|
animation
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -94,42 +94,57 @@ mod imp {
|
||||||
|
|
||||||
self.parent_constructed();
|
self.parent_constructed();
|
||||||
|
|
||||||
self.right_click_gesture
|
self.right_click_gesture.connect_pressed(clone!(
|
||||||
.connect_pressed(clone!(@weak obj => move |gesture, _, x, y| {
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |gesture, _, x, y| {
|
||||||
obj.show_popover_at(x, y);
|
obj.show_popover_at(x, y);
|
||||||
gesture.set_state(gtk::EventSequenceState::Claimed);
|
gesture.set_state(gtk::EventSequenceState::Claimed);
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
self.press_gesture
|
self.press_gesture.connect_pressed(clone!(
|
||||||
.connect_pressed(clone!(@weak obj => move |gesture, x, y| {
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |gesture, x, y| {
|
||||||
log::debug!("Long press triggered");
|
log::debug!("Long press triggered");
|
||||||
obj.show_popover_at(x, y);
|
obj.show_popover_at(x, y);
|
||||||
gesture.set_state(gtk::EventSequenceState::Claimed);
|
gesture.set_state(gtk::EventSequenceState::Claimed);
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
self.stack
|
self.stack.connect_visible_child_notify(clone!(
|
||||||
.connect_visible_child_notify(clone!(@weak obj => move |stack| {
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |stack| {
|
||||||
let imp = obj.imp();
|
let imp = obj.imp();
|
||||||
let spinner_visible =
|
let spinner_visible =
|
||||||
stack.visible_child().as_ref() == Some(imp.spinner_page.upcast_ref());
|
stack.visible_child().as_ref() == Some(imp.spinner_page.upcast_ref());
|
||||||
// Hide spinner for crossfading into other content since it does not look great
|
// Hide spinner for crossfading into other content since it does not look great
|
||||||
imp.spinner.set_visible(spinner_visible);
|
imp.spinner.set_visible(spinner_visible);
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
obj.image()
|
obj.image().connect_is_loaded_notify(clone!(
|
||||||
.connect_is_loaded_notify(clone!(@weak obj => move |_| {
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| {
|
||||||
if obj.image().is_loaded() {
|
if obj.image().is_loaded() {
|
||||||
log::debug!("Showing image");
|
log::debug!("Showing image");
|
||||||
obj.imp()
|
obj.imp()
|
||||||
.stack
|
.stack
|
||||||
.set_visible_child(&*obj.imp().image_stack_page);
|
.set_visible_child(&*obj.imp().image_stack_page);
|
||||||
}
|
}
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
obj.image()
|
obj.image().connect_error_notify(clone!(
|
||||||
.connect_error_notify(clone!(@weak obj => move |_| {
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| {
|
||||||
glib::spawn_future_local(async move { obj.show_error().await });
|
glib::spawn_future_local(async move { obj.show_error().await });
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
// Do not waste CPU on spinner if it is not visible
|
// Do not waste CPU on spinner if it is not visible
|
||||||
self.spinner.connect_map(|s| s.start());
|
self.spinner.connect_map(|s| s.start());
|
||||||
|
|
@ -159,10 +174,16 @@ impl LpImagePage {
|
||||||
|
|
||||||
obj.imp().image.init(file);
|
obj.imp().image.init(file);
|
||||||
|
|
||||||
glib::spawn_future_local(clone!(@weak obj, @strong file => async move {
|
glib::spawn_future_local(clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
#[strong]
|
||||||
|
file,
|
||||||
|
async move {
|
||||||
let imp = obj.imp();
|
let imp = obj.imp();
|
||||||
imp.image.load(&file).await;
|
imp.image.load(&file).await;
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
obj
|
obj
|
||||||
}
|
}
|
||||||
|
|
@ -225,10 +246,13 @@ impl LpImagePage {
|
||||||
|
|
||||||
imp.stack.set_visible_child(&*imp.error_page);
|
imp.stack.set_visible_child(&*imp.error_page);
|
||||||
} else if let Some(err) = image.error() {
|
} else if let Some(err) = image.error() {
|
||||||
imp.error_more_info
|
imp.error_more_info.connect_clicked(glib::clone!(
|
||||||
.connect_clicked(glib::clone!(@weak self as obj => move |_| {
|
#[weak(rename_to = obj)]
|
||||||
|
self,
|
||||||
|
move |_| {
|
||||||
LpErrorDetails::new(&obj.root().unwrap(), &err);
|
LpErrorDetails::new(&obj.root().unwrap(), &err);
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
imp.error_page.set_description(Some(&gettext(
|
imp.error_page.set_description(Some(&gettext(
|
||||||
"Either the image file is corrupted or it contains unsupported elements.",
|
"Either the image file is corrupted or it contains unsupported elements.",
|
||||||
|
|
|
||||||
|
|
@ -136,45 +136,65 @@ mod imp {
|
||||||
// Manually manage widget layout, see `WidgetImpl` for details
|
// Manually manage widget layout, see `WidgetImpl` for details
|
||||||
obj.set_layout_manager(None::<gtk::LayoutManager>);
|
obj.set_layout_manager(None::<gtk::LayoutManager>);
|
||||||
|
|
||||||
self.sliding_view.connect_current_page_notify(
|
self.sliding_view.connect_current_page_notify(glib::clone!(
|
||||||
glib::clone!(@weak obj => move |_| obj.page_changed()),
|
#[weak]
|
||||||
);
|
obj,
|
||||||
|
move |_| obj.page_changed()
|
||||||
|
));
|
||||||
|
|
||||||
self.sliding_view.connect_target_page_reached(
|
self.sliding_view.connect_target_page_reached(glib::clone!(
|
||||||
glib::clone!(@weak obj => move || obj.target_page_reached()),
|
#[weak]
|
||||||
);
|
obj,
|
||||||
|
move || obj.target_page_reached()
|
||||||
|
));
|
||||||
|
|
||||||
let signal_group = glib::SignalGroup::new::<LpImage>();
|
let signal_group = glib::SignalGroup::new::<LpImage>();
|
||||||
obj.connect_notify_local(
|
obj.connect_notify_local(
|
||||||
Some("current-page"),
|
Some("current-page"),
|
||||||
clone!(@weak signal_group => move |obj, _| {
|
clone!(
|
||||||
|
#[weak]
|
||||||
|
signal_group,
|
||||||
|
move |obj, _| {
|
||||||
signal_group.set_target(obj.current_image().as_ref());
|
signal_group.set_target(obj.current_image().as_ref());
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
let view = &*obj;
|
let view = &*obj;
|
||||||
signal_group.connect_closure(
|
signal_group.connect_closure(
|
||||||
"notify::file",
|
"notify::file",
|
||||||
true,
|
true,
|
||||||
glib::closure_local!(@watch view => move |_: LpImage, _: glib::ParamSpec| {
|
glib::closure_local!(
|
||||||
|
#[watch]
|
||||||
|
view,
|
||||||
|
move |_: LpImage, _: glib::ParamSpec| {
|
||||||
view.current_image_path_changed();
|
view.current_image_path_changed();
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
signal_group.connect_closure(
|
signal_group.connect_closure(
|
||||||
"notify::is-deleted",
|
"notify::is-deleted",
|
||||||
true,
|
true,
|
||||||
glib::closure_local!(@watch view => move |_: LpImage, _: glib::ParamSpec| {
|
glib::closure_local!(
|
||||||
|
#[watch]
|
||||||
|
view,
|
||||||
|
move |_: LpImage, _: glib::ParamSpec| {
|
||||||
view.current_image_path_changed();
|
view.current_image_path_changed();
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
self.current_image_signals.set(signal_group).unwrap();
|
self.current_image_signals.set(signal_group).unwrap();
|
||||||
|
|
||||||
self.drag_source.set_exclusive(true);
|
self.drag_source.set_exclusive(true);
|
||||||
|
|
||||||
self.drag_source.connect_prepare(
|
self.drag_source.connect_prepare(glib::clone!(
|
||||||
glib::clone!(@weak obj => @default-return None, move |gesture, _, _| {
|
#[weak]
|
||||||
|
obj,
|
||||||
|
#[upgrade_or_else]
|
||||||
|
|| None,
|
||||||
|
move |gesture, _, _| {
|
||||||
let is_scrollable = obj
|
let is_scrollable = obj
|
||||||
.current_page()
|
.current_page()
|
||||||
.map(|p| p.image().is_hscrollable() || p.image().is_vscrollable());
|
.map(|p| p.image().is_hscrollable() || p.image().is_vscrollable());
|
||||||
|
|
@ -190,13 +210,20 @@ mod imp {
|
||||||
gesture.set_state(gtk::EventSequenceState::Claimed);
|
gesture.set_state(gtk::EventSequenceState::Claimed);
|
||||||
obj.current_page().and_then(|p| p.content_provider())
|
obj.current_page().and_then(|p| p.content_provider())
|
||||||
}
|
}
|
||||||
}),
|
}
|
||||||
);
|
));
|
||||||
|
|
||||||
self.drag_source.connect_drag_begin(glib::clone!(@weak obj => move |source, _| {
|
self.drag_source.connect_drag_begin(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |source, _| {
|
||||||
if let Some(paintable) = obj.current_image().and_then(|p| p.thumbnail()) {
|
if let Some(paintable) = obj.current_image().and_then(|p| p.thumbnail()) {
|
||||||
// -6 for cursor width, +16 for margin in .drag-icon
|
// -6 for cursor width, +16 for margin in .drag-icon
|
||||||
source.set_icon(Some(&paintable), paintable.intrinsic_width() / 2 - 6 + 16, -12);
|
source.set_icon(
|
||||||
|
Some(&paintable),
|
||||||
|
paintable.intrinsic_width() / 2 - 6 + 16,
|
||||||
|
-12,
|
||||||
|
);
|
||||||
if let Some(drag) = source.drag() {
|
if let Some(drag) = source.drag() {
|
||||||
let drag_icon = gtk::DragIcon::for_drag(&drag);
|
let drag_icon = gtk::DragIcon::for_drag(&drag);
|
||||||
// Rounds corners, adds outline and shadow
|
// Rounds corners, adds outline and shadow
|
||||||
|
|
@ -205,7 +232,8 @@ mod imp {
|
||||||
drag_icon.set_overflow(gtk::Overflow::Hidden);
|
drag_icon.set_overflow(gtk::Overflow::Hidden);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
obj.add_controller(self.drag_source.clone());
|
obj.add_controller(self.drag_source.clone());
|
||||||
}
|
}
|
||||||
|
|
@ -340,16 +368,29 @@ impl LpImageView {
|
||||||
|
|
||||||
// List other files in directory
|
// List other files in directory
|
||||||
if let Some(directory) = directory {
|
if let Some(directory) = directory {
|
||||||
glib::spawn_future_local(glib::clone!(@weak self as obj => async move {
|
glib::spawn_future_local(glib::clone!(
|
||||||
|
#[weak(rename_to = obj)]
|
||||||
|
self,
|
||||||
|
async move {
|
||||||
if let Err(err) = obj.model().load_directory(directory.clone()).await {
|
if let Err(err) = obj.model().load_directory(directory.clone()).await {
|
||||||
log::warn!("Failed to load directory: {}", err.root_cause());
|
log::warn!("Failed to load directory: {}", err.root_cause());
|
||||||
obj.activate_action("win.show-toast", Some(&(format!("{} {}", err, err.root_cause()), adw::ToastPriority::High.into_glib()).to_variant()))
|
obj.activate_action(
|
||||||
|
"win.show-toast",
|
||||||
|
Some(
|
||||||
|
&(
|
||||||
|
format!("{} {}", err, err.root_cause()),
|
||||||
|
adw::ToastPriority::High.into_glib(),
|
||||||
|
)
|
||||||
|
.to_variant(),
|
||||||
|
),
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.update_sliding_view(&file);
|
obj.update_sliding_view(&file);
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -498,7 +539,10 @@ impl LpImageView {
|
||||||
|
|
||||||
page.image().connect_notify_local(
|
page.image().connect_notify_local(
|
||||||
Some("is-unsupported"),
|
Some("is-unsupported"),
|
||||||
glib::clone!(@weak self as obj => move |image, _| {
|
glib::clone!(
|
||||||
|
#[weak(rename_to = obj)]
|
||||||
|
self,
|
||||||
|
move |image, _| {
|
||||||
if image.is_unsupported() {
|
if image.is_unsupported() {
|
||||||
if obj.current_image().as_ref() == Some(image) {
|
if obj.current_image().as_ref() == Some(image) {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
|
|
@ -515,16 +559,19 @@ impl LpImageView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
page
|
page
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_model(&self, model: LpFileModel) {
|
fn set_model(&self, model: LpFileModel) {
|
||||||
model.connect_changed(
|
model.connect_changed(glib::clone!(
|
||||||
glib::clone!(@weak self as obj => move || obj.model_content_changed_cb()),
|
#[weak(rename_to = obj)]
|
||||||
);
|
self,
|
||||||
|
move || obj.model_content_changed_cb()
|
||||||
|
));
|
||||||
self.imp().model.replace(model);
|
self.imp().model.replace(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -294,8 +294,11 @@ mod imp {
|
||||||
obj.set_modal(true);
|
obj.set_modal(true);
|
||||||
|
|
||||||
// Page alignment (center, left, ...)
|
// Page alignment (center, left, ...)
|
||||||
self.alignment
|
self.alignment.connect_selected_notify(glib::clone!(
|
||||||
.connect_selected_notify(glib::clone!(@weak obj => move |_| obj.draw_preview()));
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| obj.draw_preview()
|
||||||
|
));
|
||||||
|
|
||||||
self.alignment
|
self.alignment
|
||||||
.set_expression(Some(gtk::ClosureExpression::new::<glib::GString>(
|
.set_expression(Some(gtk::ClosureExpression::new::<glib::GString>(
|
||||||
|
|
@ -306,27 +309,45 @@ mod imp {
|
||||||
)));
|
)));
|
||||||
|
|
||||||
// Margin signals
|
// Margin signals
|
||||||
self.margin_unit.connect_selected_notify(
|
self.margin_unit.connect_selected_notify(glib::clone!(
|
||||||
glib::clone!(@weak obj => move |_| obj.on_margin_unit_changed()),
|
#[weak]
|
||||||
);
|
obj,
|
||||||
|
move |_| obj.on_margin_unit_changed()
|
||||||
|
));
|
||||||
self.margin_unit.set_expression(Some(Unit::expression()));
|
self.margin_unit.set_expression(Some(Unit::expression()));
|
||||||
self.margin_horizontal
|
self.margin_horizontal.connect_value_notify(glib::clone!(
|
||||||
.connect_value_notify(glib::clone!(@weak obj => move |_| obj.on_margin_changed()));
|
#[weak]
|
||||||
self.margin_vertical
|
obj,
|
||||||
.connect_value_notify(glib::clone!(@weak obj => move |_| obj.on_margin_changed()));
|
move |_| obj.on_margin_changed()
|
||||||
|
));
|
||||||
|
self.margin_vertical.connect_value_notify(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| obj.on_margin_changed()
|
||||||
|
));
|
||||||
|
|
||||||
// Size signals
|
// Size signals
|
||||||
self.size_unit.connect_selected_notify(
|
self.size_unit.connect_selected_notify(glib::clone!(
|
||||||
glib::clone!(@weak obj => move |_| obj.on_size_unit_changed()),
|
#[weak]
|
||||||
);
|
obj,
|
||||||
|
move |_| obj.on_size_unit_changed()
|
||||||
|
));
|
||||||
self.size_unit.set_expression(Some(Unit::expression()));
|
self.size_unit.set_expression(Some(Unit::expression()));
|
||||||
self.fill_space.connect_active_notify(
|
self.fill_space.connect_active_notify(glib::clone!(
|
||||||
glib::clone!(@weak obj => move |_| obj.on_fill_space_changed()),
|
#[weak]
|
||||||
);
|
obj,
|
||||||
self.width
|
move |_| obj.on_fill_space_changed()
|
||||||
.connect_value_notify(glib::clone!(@weak obj => move |_| obj.on_width_changed()));
|
));
|
||||||
self.height
|
self.width.connect_value_notify(glib::clone!(
|
||||||
.connect_value_notify(glib::clone!(@weak obj => move |_| obj.on_height_changed()));
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| obj.on_width_changed()
|
||||||
|
));
|
||||||
|
self.height.connect_value_notify(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| obj.on_height_changed()
|
||||||
|
));
|
||||||
|
|
||||||
let imp = self;
|
let imp = self;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -116,13 +116,26 @@ mod imp {
|
||||||
|
|
||||||
image_signals.connect_notify_local(
|
image_signals.connect_notify_local(
|
||||||
Some("image-size-available"),
|
Some("image-size-available"),
|
||||||
glib::clone!(@weak obj => move |_, _| obj.imp().update()),
|
glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_, _| obj.imp().update()
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
image_signals.connect_local(
|
image_signals.connect_local(
|
||||||
"metadata-changed",
|
"metadata-changed",
|
||||||
false,
|
false,
|
||||||
glib::clone!(@weak obj => @default-return None, move |_| { obj.imp().update(); None }),
|
glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
#[upgrade_or_else]
|
||||||
|
|| None,
|
||||||
|
move |_| {
|
||||||
|
obj.imp().update();
|
||||||
|
None
|
||||||
|
}
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
self.update();
|
self.update();
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
<child>
|
<child>
|
||||||
<object class="AdwActionRow" id="folder">
|
<object class="AdwActionRow" id="folder">
|
||||||
<property name="title" translatable="yes">Folder</property>
|
<property name="title" translatable="yes">Folder</property>
|
||||||
<property name="activatable-widget">folder_button</property>
|
|
||||||
<property name="use-markup">False</property>
|
<property name="use-markup">False</property>
|
||||||
<child type="suffix">
|
<child type="suffix">
|
||||||
<object class="GtkButton" id="folder_button">
|
<object class="GtkButton" id="folder_button">
|
||||||
|
|
|
||||||
|
|
@ -159,20 +159,32 @@ mod imp {
|
||||||
.upper_overshoot(true)
|
.upper_overshoot(true)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
swipe_tracker.connect_begin_swipe(glib::clone!(@weak obj => move |_| {
|
swipe_tracker.connect_begin_swipe(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| {
|
||||||
obj.scroll_animation().pause();
|
obj.scroll_animation().pause();
|
||||||
obj.step_animation().pause();
|
obj.step_animation().pause();
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
swipe_tracker.connect_update_swipe(glib::clone!(@weak obj => move |_, position| {
|
swipe_tracker.connect_update_swipe(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_, position| {
|
||||||
obj.set_position(position);
|
obj.set_position(position);
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
swipe_tracker.connect_end_swipe(glib::clone!(@weak obj => move |_, velocity, to| {
|
swipe_tracker.connect_end_swipe(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_, velocity, to| {
|
||||||
if let Some(page) = obj.page_at(to) {
|
if let Some(page) = obj.page_at(to) {
|
||||||
obj.scroll_to(&page, velocity);
|
obj.scroll_to(&page, velocity);
|
||||||
}
|
}
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
self.swipe_tracker.set(swipe_tracker).unwrap();
|
self.swipe_tracker.set(swipe_tracker).unwrap();
|
||||||
|
|
||||||
|
|
@ -180,8 +192,12 @@ mod imp {
|
||||||
let scroll_controller =
|
let scroll_controller =
|
||||||
gtk::EventControllerScroll::new(gtk::EventControllerScrollFlags::HORIZONTAL);
|
gtk::EventControllerScroll::new(gtk::EventControllerScrollFlags::HORIZONTAL);
|
||||||
|
|
||||||
scroll_controller.connect_scroll(
|
scroll_controller.connect_scroll(glib::clone!(
|
||||||
glib::clone!(@weak obj => @default-return glib::Propagation::Proceed, move |_, x, _| {
|
#[weak]
|
||||||
|
obj,
|
||||||
|
#[upgrade_or_else]
|
||||||
|
|| glib::Propagation::Proceed,
|
||||||
|
move |_, x, _| {
|
||||||
let direction_sign = if obj.imp().is_rtl() { -1. } else { 1. };
|
let direction_sign = if obj.imp().is_rtl() { -1. } else { 1. };
|
||||||
|
|
||||||
if x * direction_sign > 0. {
|
if x * direction_sign > 0. {
|
||||||
|
|
@ -207,8 +223,8 @@ mod imp {
|
||||||
glib::Propagation::Stop
|
glib::Propagation::Stop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}
|
||||||
);
|
));
|
||||||
|
|
||||||
obj.add_controller(scroll_controller);
|
obj.add_controller(scroll_controller);
|
||||||
}
|
}
|
||||||
|
|
@ -712,9 +728,11 @@ impl LpSlidingView {
|
||||||
|
|
||||||
fn scroll_animation(&self) -> &adw::SpringAnimation {
|
fn scroll_animation(&self) -> &adw::SpringAnimation {
|
||||||
self.imp().scroll_animation.get_or_init(|| {
|
self.imp().scroll_animation.get_or_init(|| {
|
||||||
let target = adw::CallbackAnimationTarget::new(
|
let target = adw::CallbackAnimationTarget::new(glib::clone!(
|
||||||
glib::clone!(@weak self as obj => move |position| obj.set_position(position)),
|
#[weak(rename_to = obj)]
|
||||||
);
|
self,
|
||||||
|
move |position| obj.set_position(position)
|
||||||
|
));
|
||||||
|
|
||||||
let animation = adw::SpringAnimation::builder()
|
let animation = adw::SpringAnimation::builder()
|
||||||
.spring_params(&adw::SpringParams::new(
|
.spring_params(&adw::SpringParams::new(
|
||||||
|
|
@ -726,9 +744,11 @@ impl LpSlidingView {
|
||||||
.target(&target)
|
.target(&target)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
animation.connect_done(glib::clone!(@weak self as obj => move |_| {
|
animation.connect_done(glib::clone!(
|
||||||
obj.emit_target_page_reached()
|
#[weak(rename_to = obj)]
|
||||||
}));
|
self,
|
||||||
|
move |_| obj.emit_target_page_reached()
|
||||||
|
));
|
||||||
|
|
||||||
animation
|
animation
|
||||||
})
|
})
|
||||||
|
|
@ -736,12 +756,18 @@ impl LpSlidingView {
|
||||||
|
|
||||||
fn step_animation(&self) -> &adw::TimedAnimation {
|
fn step_animation(&self) -> &adw::TimedAnimation {
|
||||||
self.imp().step_animation.get_or_init(|| {
|
self.imp().step_animation.get_or_init(|| {
|
||||||
let target: adw::CallbackAnimationTarget = adw::CallbackAnimationTarget::new(
|
let target: adw::CallbackAnimationTarget =
|
||||||
glib::clone!(@weak self as obj => move |progress| {
|
adw::CallbackAnimationTarget::new(glib::clone!(
|
||||||
obj.imp().position_tracking.borrow_mut().set_progress(progress);
|
#[weak(rename_to = obj)]
|
||||||
|
self,
|
||||||
|
move |progress| {
|
||||||
|
obj.imp()
|
||||||
|
.position_tracking
|
||||||
|
.borrow_mut()
|
||||||
|
.set_progress(progress);
|
||||||
obj.queue_allocate();
|
obj.queue_allocate();
|
||||||
}),
|
}
|
||||||
);
|
));
|
||||||
|
|
||||||
let animation = adw::TimedAnimation::builder()
|
let animation = adw::TimedAnimation::builder()
|
||||||
.duration(STEP_DURATION)
|
.duration(STEP_DURATION)
|
||||||
|
|
@ -751,17 +777,23 @@ impl LpSlidingView {
|
||||||
.target(&target)
|
.target(&target)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
animation.connect_done(glib::clone!(@weak self as obj => move |_| {
|
animation.connect_done(glib::clone!(
|
||||||
|
#[weak(rename_to = obj)]
|
||||||
|
self,
|
||||||
|
move |_| {
|
||||||
if let Some(current_index) = obj.current_index() {
|
if let Some(current_index) = obj.current_index() {
|
||||||
let imp = obj.imp();
|
let imp = obj.imp();
|
||||||
imp.position_tracking.borrow_mut().set_progress(1.);
|
imp.position_tracking.borrow_mut().set_progress(1.);
|
||||||
imp.position_tracking.borrow_mut().set_position(current_index as f64 - obj.position_shift());
|
imp.position_tracking
|
||||||
|
.borrow_mut()
|
||||||
|
.set_position(current_index as f64 - obj.position_shift());
|
||||||
obj.queue_allocate();
|
obj.queue_allocate();
|
||||||
} else {
|
} else {
|
||||||
error!("No current page at end of animation");
|
error!("No current page at end of animation");
|
||||||
}
|
}
|
||||||
obj.emit_target_page_reached();
|
obj.emit_target_page_reached();
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
animation
|
animation
|
||||||
})
|
})
|
||||||
|
|
|
||||||
207
src/window.rs
207
src/window.rs
|
|
@ -172,18 +172,27 @@ mod imp {
|
||||||
|
|
||||||
let obj = self.obj();
|
let obj = self.obj();
|
||||||
|
|
||||||
self.forward_click_gesture
|
self.forward_click_gesture.connect_pressed(clone!(
|
||||||
.connect_pressed(clone!(@weak obj => move |_,_,_,_| {
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_, _, _, _| {
|
||||||
obj.image_view().navigate(Direction::Forward, false);
|
obj.image_view().navigate(Direction::Forward, false);
|
||||||
}));
|
}
|
||||||
self.backward_click_gesture
|
));
|
||||||
.connect_pressed(clone!(@weak obj => move |_,_,_,_| {
|
self.backward_click_gesture.connect_pressed(clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_, _, _, _| {
|
||||||
obj.image_view().navigate(Direction::Back, false);
|
obj.image_view().navigate(Direction::Back, false);
|
||||||
}));
|
}
|
||||||
self.properties_button
|
));
|
||||||
.connect_toggled(clone!(@weak obj => move |_| {
|
self.properties_button.connect_toggled(clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| {
|
||||||
obj.on_properties_button_toggled();
|
obj.on_properties_button_toggled();
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
if config::PROFILE == ".Devel" {
|
if config::PROFILE == ".Devel" {
|
||||||
obj.add_css_class("devel");
|
obj.add_css_class("devel");
|
||||||
|
|
@ -195,37 +204,58 @@ mod imp {
|
||||||
|
|
||||||
glib::timeout_add_local_once(
|
glib::timeout_add_local_once(
|
||||||
std::time::Duration::from_millis(SHOW_WINDOW_AFTER),
|
std::time::Duration::from_millis(SHOW_WINDOW_AFTER),
|
||||||
glib::clone!(@weak obj => move || if !obj.is_visible() { obj.present() }),
|
glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move || if !obj.is_visible() {
|
||||||
|
obj.present()
|
||||||
|
}
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
obj.on_current_page_changed();
|
obj.on_current_page_changed();
|
||||||
obj.on_fullscreen_changed();
|
obj.on_fullscreen_changed();
|
||||||
|
|
||||||
self.image_view.connect_current_page_notify(
|
self.image_view.connect_current_page_notify(glib::clone!(
|
||||||
glib::clone!(@weak obj => move |_| obj.on_current_page_changed()),
|
#[weak]
|
||||||
);
|
obj,
|
||||||
|
move |_| obj.on_current_page_changed()
|
||||||
|
));
|
||||||
|
|
||||||
obj.connect_fullscreened_notify(
|
obj.connect_fullscreened_notify(glib::clone!(
|
||||||
glib::clone!(@weak obj => move |_| obj.on_fullscreen_changed()),
|
#[weak]
|
||||||
);
|
obj,
|
||||||
|
move |_| obj.on_fullscreen_changed()
|
||||||
|
));
|
||||||
|
|
||||||
obj.connect_map(|win| {
|
obj.connect_map(|win| {
|
||||||
win.resize_default();
|
win.resize_default();
|
||||||
});
|
});
|
||||||
|
|
||||||
self.properties_button.connect_active_notify(
|
self.properties_button.connect_active_notify(glib::clone!(
|
||||||
glib::clone!(@weak obj => move |_| obj.update_headerbar_style()),
|
#[weak]
|
||||||
);
|
obj,
|
||||||
|
move |_| obj.update_headerbar_style()
|
||||||
|
));
|
||||||
|
|
||||||
let gesture_click = gtk::GestureClick::new();
|
let gesture_click = gtk::GestureClick::new();
|
||||||
gesture_click
|
gesture_click.connect_pressed(glib::clone!(
|
||||||
.connect_pressed(glib::clone!(@weak obj => move |_, _, _, _| obj.on_click()));
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_, _, _, _| obj.on_click()
|
||||||
|
));
|
||||||
obj.add_controller(gesture_click);
|
obj.add_controller(gesture_click);
|
||||||
|
|
||||||
self.motion_controller
|
self.motion_controller.connect_motion(glib::clone!(
|
||||||
.connect_motion(glib::clone!(@weak obj => move |_, x, y| obj.on_motion((x,y))));
|
#[weak]
|
||||||
self.motion_controller
|
obj,
|
||||||
.connect_enter(glib::clone!(@weak obj => move |_, x, y| obj.on_motion((x,y))));
|
move |_, x, y| obj.on_motion((x, y))
|
||||||
|
));
|
||||||
|
self.motion_controller.connect_enter(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_, x, y| obj.on_motion((x, y))
|
||||||
|
));
|
||||||
obj.add_controller(self.motion_controller.clone());
|
obj.add_controller(self.motion_controller.clone());
|
||||||
|
|
||||||
let current_image_signals = self.image_view.current_image_signals();
|
let current_image_signals = self.image_view.current_image_signals();
|
||||||
|
|
@ -237,17 +267,25 @@ mod imp {
|
||||||
// Object alive, pass as @weak. Otherwise, pass
|
// Object alive, pass as @weak. Otherwise, pass
|
||||||
// as @strong. Most of the time you will want
|
// as @strong. Most of the time you will want
|
||||||
// to use @weak.
|
// to use @weak.
|
||||||
current_image_signals.connect_bind_local(glib::clone!(@weak obj => move |_, _| {
|
current_image_signals.connect_bind_local(glib::clone!(
|
||||||
obj.on_zoom_status_changed()
|
#[weak]
|
||||||
}));
|
obj,
|
||||||
|
move |_, _| obj.on_zoom_status_changed()
|
||||||
|
));
|
||||||
|
|
||||||
current_image_signals.connect_local(
|
current_image_signals.connect_local(
|
||||||
"metadata-changed",
|
"metadata-changed",
|
||||||
true,
|
true,
|
||||||
glib::clone!(@weak obj => @default-return None, move |_| {
|
glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
#[upgrade_or_else]
|
||||||
|
|| None,
|
||||||
|
move |_| {
|
||||||
obj.update_title();
|
obj.update_title();
|
||||||
None
|
None
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
current_image_signals.connect_closure(
|
current_image_signals.connect_closure(
|
||||||
|
|
@ -256,57 +294,82 @@ mod imp {
|
||||||
// `closure_local!` is similar to `clone`, but you use `@watch` instead of clone.
|
// `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
|
// `@watch` means that this signal will be disconnected when the watched object
|
||||||
// is dropped.
|
// is dropped.
|
||||||
glib::closure_local!(@watch obj => move |_: &LpImage, _: &glib::ParamSpec| {
|
glib::closure_local!(
|
||||||
|
#[watch]
|
||||||
|
obj,
|
||||||
|
move |_: &LpImage, _: &glib::ParamSpec| {
|
||||||
obj.on_zoom_status_changed();
|
obj.on_zoom_status_changed();
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
current_image_signals.connect_closure(
|
current_image_signals.connect_closure(
|
||||||
"notify::is-max-zoom",
|
"notify::is-max-zoom",
|
||||||
false,
|
false,
|
||||||
glib::closure_local!(@watch obj => move |_: &LpImage, _: &glib::ParamSpec| {
|
glib::closure_local!(
|
||||||
|
#[watch]
|
||||||
|
obj,
|
||||||
|
move |_: &LpImage, _: &glib::ParamSpec| {
|
||||||
obj.on_zoom_status_changed();
|
obj.on_zoom_status_changed();
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
current_image_signals.connect_closure(
|
current_image_signals.connect_closure(
|
||||||
"notify::image-size-available",
|
"notify::image-size-available",
|
||||||
false,
|
false,
|
||||||
glib::closure_local!(@watch obj => move |_: &LpImage, _: &glib::ParamSpec| {
|
glib::closure_local!(
|
||||||
|
#[watch]
|
||||||
|
obj,
|
||||||
|
move |_: &LpImage, _: &glib::ParamSpec| {
|
||||||
obj.image_size_available();
|
obj.image_size_available();
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
current_image_signals.connect_closure(
|
current_image_signals.connect_closure(
|
||||||
"notify::error",
|
"notify::error",
|
||||||
false,
|
false,
|
||||||
glib::closure_local!(@watch obj => move |_: &LpImage, _: &glib::ParamSpec| {
|
glib::closure_local!(
|
||||||
|
#[watch]
|
||||||
|
obj,
|
||||||
|
move |_: &LpImage, _: &glib::ParamSpec| {
|
||||||
obj.image_error();
|
obj.image_error();
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
self.toolbar_view.connect_top_bar_style_notify(
|
self.toolbar_view.connect_top_bar_style_notify(glib::clone!(
|
||||||
glib::clone!(@weak obj => move |_| obj.on_top_bar_style_notify()),
|
#[weak]
|
||||||
);
|
obj,
|
||||||
|
move |_| obj.on_top_bar_style_notify()
|
||||||
|
));
|
||||||
|
|
||||||
// action win.previous status
|
// action win.previous status
|
||||||
self.image_view.connect_is_previous_available_notify(
|
self.image_view
|
||||||
glib::clone!(@weak obj => move |_| {
|
.connect_is_previous_available_notify(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| {
|
||||||
obj.action_set_enabled(
|
obj.action_set_enabled(
|
||||||
"win.previous",
|
"win.previous",
|
||||||
obj.imp().image_view.is_previous_available(),
|
obj.imp().image_view.is_previous_available(),
|
||||||
);
|
);
|
||||||
}),
|
}
|
||||||
);
|
));
|
||||||
|
|
||||||
// action win.next status
|
// action win.next status
|
||||||
self.image_view
|
self.image_view
|
||||||
.connect_is_next_available_notify(glib::clone!(@weak obj => move |_| {
|
.connect_is_next_available_notify(glib::clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| {
|
||||||
obj.action_set_enabled(
|
obj.action_set_enabled(
|
||||||
"win.next",
|
"win.next",
|
||||||
obj.imp().image_view.is_next_available(),
|
obj.imp().image_view.is_next_available(),
|
||||||
);
|
);
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
|
|
||||||
// Make widgets visible when the focus moves
|
// Make widgets visible when the focus moves
|
||||||
obj.connect_move_focus(|obj, _| {
|
obj.connect_move_focus(|obj, _| {
|
||||||
|
|
@ -323,31 +386,41 @@ mod imp {
|
||||||
|
|
||||||
self.drop_target.set_types(&[gdk::FileList::static_type()]);
|
self.drop_target.set_types(&[gdk::FileList::static_type()]);
|
||||||
|
|
||||||
self.drop_target.connect_accept(
|
self.drop_target.connect_accept(clone!(
|
||||||
clone!(@weak obj => @default-return false, move |_drop_target, drop| {
|
#[weak]
|
||||||
|
obj,
|
||||||
|
#[upgrade_or_else]
|
||||||
|
|| false,
|
||||||
|
move |_drop_target, drop| {
|
||||||
// Only accept drops from external sources or different windows
|
// Only accept drops from external sources or different windows
|
||||||
let different_source = drop.drag().is_none() || drop.drag() != obj.image_view().drag_source().drag();
|
let different_source = drop.drag().is_none()
|
||||||
|
|| drop.drag() != obj.image_view().drag_source().drag();
|
||||||
// We have to do this manually since we are overwriting the default handler
|
// We have to do this manually since we are overwriting the default handler
|
||||||
let correct_format = drop.formats().contains_type(gdk::FileList::static_type());
|
let correct_format = drop.formats().contains_type(gdk::FileList::static_type());
|
||||||
|
|
||||||
different_source && correct_format
|
different_source && correct_format
|
||||||
}),
|
}
|
||||||
);
|
));
|
||||||
|
|
||||||
// For callbacks, you will want to reference the GTK docs on
|
// For callbacks, you will want to reference the GTK docs on
|
||||||
// the relevant signal to see which parameters you need.
|
// the relevant signal to see which parameters you need.
|
||||||
// In this case, we need only need the GValue,
|
// In this case, we need only need the GValue,
|
||||||
// so we name it `value` then use `_` for the other spots.
|
// so we name it `value` then use `_` for the other spots.
|
||||||
self.drop_target.connect_drop(
|
self.drop_target.connect_drop(clone!(
|
||||||
clone!(@weak obj => @default-return false, move |_, value, _, _| {
|
#[weak]
|
||||||
|
obj,
|
||||||
// Here we use a GValue, which is a dynamic object that can hold different types,
|
#[upgrade_or_else]
|
||||||
// e.g. strings, numbers, or in this case objects. In order to get the GdkFileList
|
|| false,
|
||||||
// from the GValue, we need to use the `get()` method.
|
move |_, value, _, _| {
|
||||||
|
// Here we use a GValue, which is a dynamic object that can hold different
|
||||||
|
// types, e.g. strings, numbers, or in this case objects. In
|
||||||
|
// order to get the GdkFileList from the GValue, we need to
|
||||||
|
// use the `get()` method.
|
||||||
//
|
//
|
||||||
// We've added type annotations here, and written it as `let list: gdk::FileList = ...`,
|
// We've added type annotations here, and written it as `let list: gdk::FileList
|
||||||
// but you might also see places where type arguments are used.
|
// = ...`, but you might also see places where type
|
||||||
// This line could have been written as `let list = value.get::<gdk::FileList>().unwrap()`.
|
// arguments are used. This line could have been written as
|
||||||
|
// `let list = value.get::<gdk::FileList>().unwrap()`.
|
||||||
let files = match value.get::<gdk::FileList>() {
|
let files = match value.get::<gdk::FileList>() {
|
||||||
Ok(list) => list.files(),
|
Ok(list) => list.files(),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|
@ -367,8 +440,8 @@ mod imp {
|
||||||
obj.present();
|
obj.present();
|
||||||
|
|
||||||
true
|
true
|
||||||
}),
|
}
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -563,7 +636,10 @@ impl LpWindow {
|
||||||
.button_label(gettext("Undo"))
|
.button_label(gettext("Undo"))
|
||||||
.priority(adw::ToastPriority::High)
|
.priority(adw::ToastPriority::High)
|
||||||
.build();
|
.build();
|
||||||
toast.connect_button_clicked(glib::clone!(@weak self as win => move |_| {
|
toast.connect_button_clicked(glib::clone!(
|
||||||
|
#[weak(rename_to = win)]
|
||||||
|
self,
|
||||||
|
move |_| {
|
||||||
let path = path.clone();
|
let path = path.clone();
|
||||||
glib::spawn_future_local(async move {
|
glib::spawn_future_local(async move {
|
||||||
win.image_view()
|
win.image_view()
|
||||||
|
|
@ -577,7 +653,8 @@ impl LpWindow {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}));
|
}
|
||||||
|
));
|
||||||
self.imp().toast_overlay.add_toast(toast);
|
self.imp().toast_overlay.add_toast(toast);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,9 @@ impl LpWindow {
|
||||||
fn show_controls_animation(&self) -> &adw::TimedAnimation {
|
fn show_controls_animation(&self) -> &adw::TimedAnimation {
|
||||||
self.imp().show_controls_animation.get_or_init(|| {
|
self.imp().show_controls_animation.get_or_init(|| {
|
||||||
let target = adw::CallbackAnimationTarget::new(glib::clone!(
|
let target = adw::CallbackAnimationTarget::new(glib::clone!(
|
||||||
@weak self as obj => move |opacity| obj.set_control_opacity(opacity, false)
|
#[weak(rename_to = obj)]
|
||||||
|
self,
|
||||||
|
move |opacity| obj.set_control_opacity(opacity, false)
|
||||||
));
|
));
|
||||||
|
|
||||||
adw::TimedAnimation::builder()
|
adw::TimedAnimation::builder()
|
||||||
|
|
@ -66,7 +68,9 @@ impl LpWindow {
|
||||||
fn hide_controls_animation(&self) -> &adw::TimedAnimation {
|
fn hide_controls_animation(&self) -> &adw::TimedAnimation {
|
||||||
self.imp().hide_controls_animation.get_or_init(|| {
|
self.imp().hide_controls_animation.get_or_init(|| {
|
||||||
let target = adw::CallbackAnimationTarget::new(glib::clone!(
|
let target = adw::CallbackAnimationTarget::new(glib::clone!(
|
||||||
@weak self as obj => move |opacity| obj.set_control_opacity(opacity, true)
|
#[weak(rename_to = obj)]
|
||||||
|
self,
|
||||||
|
move |opacity| obj.set_control_opacity(opacity, true)
|
||||||
));
|
));
|
||||||
|
|
||||||
adw::TimedAnimation::builder()
|
adw::TimedAnimation::builder()
|
||||||
|
|
@ -85,10 +89,14 @@ impl LpWindow {
|
||||||
|
|
||||||
let new_timeout = glib::timeout_add_local_once(
|
let new_timeout = glib::timeout_add_local_once(
|
||||||
std::time::Duration::from_millis(HIDE_CONTROLS_IDLE_TIMEOUT),
|
std::time::Duration::from_millis(HIDE_CONTROLS_IDLE_TIMEOUT),
|
||||||
glib::clone!(@weak self as win => move || {
|
glib::clone!(
|
||||||
|
#[weak(rename_to = win)]
|
||||||
|
self,
|
||||||
|
move || {
|
||||||
win.imp().hide_controls_timeout.take();
|
win.imp().hide_controls_timeout.take();
|
||||||
win.hide_controls();
|
win.hide_controls();
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
self.imp().hide_controls_timeout.replace(Some(new_timeout));
|
self.imp().hide_controls_timeout.replace(Some(new_timeout));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue