parent
50450ad359
commit
c36e7f4eb6
6 changed files with 279 additions and 458 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue