code: Replace many uses of GtkExpressions

Closes #276, #100
This commit is contained in:
Sophie Herold 2023-12-02 22:07:33 +01:00
parent 50450ad359
commit c36e7f4eb6
6 changed files with 279 additions and 458 deletions

View file

@ -37,7 +37,7 @@ use std::path::{Path, PathBuf};
use crate::config;
use crate::util::{self, Direction, Position};
use crate::widgets::{LpDragOverlay, LpImage, LpImagePage, LpImageView, LpPropertiesView};
use crate::widgets::{LpDragOverlay, LpImage, LpImageView, LpPropertiesView};
/// Show window after X milliseconds even if image dimensions are not known yet
const SHOW_WINDOW_AFTER: u64 = 2000;
@ -81,6 +81,8 @@ mod imp {
#[template_child]
pub(super) properties_button: TemplateChild<gtk::ToggleButton>,
#[template_child]
pub(super) primary_menu: TemplateChild<gtk::MenuButton>,
#[template_child]
pub(super) toast_overlay: TemplateChild<adw::ToastOverlay>,
#[template_child]
pub(super) stack: TemplateChild<gtk::Stack>,
@ -120,7 +122,6 @@ mod imp {
// bind_template() is a function generated by the
// CompositeTemplate macro to bind all children at once.
Self::bind_template(klass);
Self::Type::bind_template_callbacks(klass);
klass.add_binding(
gdk::Key::c,
@ -262,10 +263,10 @@ mod imp {
impl ObjectImpl for LpWindow {
fn constructed(&self) {
let obj = self.obj();
self.parent_constructed();
let obj = self.obj();
self.forward_click_gesture
.connect_pressed(clone!(@weak obj => move |_,_,_,_| {
obj.image_view().navigate(Direction::Forward);
@ -294,6 +295,14 @@ mod imp {
glib::clone!(@weak obj => move |_| obj.on_current_page_changed()),
);
obj.connect_fullscreened_notify(
glib::clone!(@weak obj => move |_| obj.on_fullscreen_changed()),
);
self.properties_button.connect_active_notify(
glib::clone!(@weak obj => move |_| obj.update_headerbar_style()),
);
let gesture_click = gtk::GestureClick::new();
gesture_click
.connect_pressed(glib::clone!(@weak obj => move |_, _, _, _| obj.on_click()));
@ -449,7 +458,6 @@ glib::wrapper! {
@implements gio::ActionMap, gio::ActionGroup, gtk::Native;
}
#[gtk::template_callbacks]
impl LpWindow {
pub fn new<A: IsA<gtk::Application>>(app: &A) -> Self {
glib::Object::builder().property("application", app).build()
@ -723,6 +731,10 @@ impl LpWindow {
/// Handles change in availability of images
fn on_current_page_changed(&self) {
let imp = self.imp();
let current_page = imp.image_view.current_page();
// HeaderBar style
self.update_headerbar_style();
// Window title
let title = self
@ -734,7 +746,11 @@ impl LpWindow {
self.set_title(Some(&title));
let has_image = imp.image_view.current_page().is_some();
// Properties view
let current_image = current_page.as_ref().map(|x| x.image());
imp.properties_view.set_image(current_image.as_ref());
let has_image = current_page.is_some();
imp.properties_button.set_sensitive(has_image);
self.set_actions_enabled(has_image);
@ -806,6 +822,10 @@ impl LpWindow {
self.action_set_enabled("win.zoom-in", can_zoom_in);
}
/// Set control opacity
///
/// Also changes headerbar transparency if it flat and hides/shows cursor on
/// fullscreen
fn set_control_opacity(&self, opacity: f64, hiding: bool) {
self.image_view().controls_box_start().set_opacity(opacity);
self.image_view().controls_box_end().set_opacity(opacity);
@ -881,7 +901,7 @@ impl LpWindow {
}
}
fn is_controls_visible(&self) -> bool {
fn are_controls_visible(&self) -> bool {
if self.hide_controls_animation().state() == adw::AnimationState::Playing {
return false;
}
@ -892,7 +912,7 @@ impl LpWindow {
/// Start animation to show controls
fn show_controls(&self) {
if !self.is_controls_visible() {
if !self.are_controls_visible() {
self.hide_controls_animation().pause();
self.show_controls_animation()
.set_value_from(self.controls_opacity());
@ -902,7 +922,7 @@ impl LpWindow {
/// Start animation to hide controls
fn hide_controls(&self) {
if self.is_controls_visible() {
if self.are_controls_visible() {
self.show_controls_animation().pause();
self.hide_controls_animation()
.set_value_from(self.controls_opacity());
@ -910,12 +930,6 @@ impl LpWindow {
}
}
/// Whether or not the window is showing images
fn is_showing_image(&self) -> bool {
let imp = self.imp();
imp.stack.visible_child().as_ref() == Some(imp.image_view.upcast_ref())
}
fn on_click(&self) {
self.show_controls();
@ -946,23 +960,38 @@ impl LpWindow {
}
}
/// Returns `true` if controls can be hidden
///
/// Only hide controls if cursor not over controls and there is an image
/// shown
fn can_hide_controls(&self) -> bool {
!self
let imp = self.imp();
let controls_hovered = self
.image_view()
.controls_box_start_events()
.contains_pointer()
&& !self
|| self
.image_view()
.controls_box_end_events()
.contains_pointer()
&& self.is_showing_image()
&& (!self.is_headerbar_flat() || !self.imp().headerbar_events.contains_pointer())
.contains_pointer();
let headerbar_hideable = self.is_content_extended_to_top();
let headerbar_hovered = imp.headerbar_events.contains_pointer();
let main_menu_open = imp.primary_menu.is_active();
// Buttom controls are not hovered
!controls_hovered
// Either headerbar must not be hidden with other controls or not be hovered
&& (!headerbar_hideable || !headerbar_hovered)
// Main menu is not open
&& !main_menu_open
}
#[template_callback]
fn on_fullscreened(&self) {
fn on_fullscreen_changed(&self) {
self.update_headerbar_style();
if !self.is_fullscreened() {
self.set_cursor(None);
self.show_controls();
@ -986,25 +1015,23 @@ impl LpWindow {
}
}
#[template_callback]
fn extend_to_top(&self, fullscreened: bool, show_properties: bool, show_menu: bool) -> bool {
fullscreened && !show_properties && !show_menu
fn is_content_extended_to_top(&self) -> bool {
self.is_fullscreened() && !self.imp().properties_button.is_active()
}
#[template_callback]
fn top_bar_style(
&self,
fullscreened: bool,
show_properties: bool,
show_menu: bool,
current_image: Option<LpImage>,
) -> adw::ToolbarStyle {
fn update_headerbar_style(&self) {
let imp = self.imp();
let extend = self.is_content_extended_to_top();
imp.toolbar_view.set_extend_content_to_top_edge(extend);
// Flat headerbar for empty state and fullscreen
if current_image.is_none() || self.extend_to_top(fullscreened, show_properties, show_menu) {
let toolbar_style = if imp.image_view.current_image().is_none() || extend {
adw::ToolbarStyle::Flat
} else {
// Use the border variant of raised to avoid shadows over images
adw::ToolbarStyle::__Unknown(2)
}
adw::ToolbarStyle::RaisedBorder
};
imp.toolbar_view.set_top_bar_style(toolbar_style);
}
}