diff --git a/src/bar.rs b/src/bar.rs index bf51721..dce013c 100644 --- a/src/bar.rs +++ b/src/bar.rs @@ -190,11 +190,13 @@ fn add_modules( let popup = Popup::new(info, popup_gap); let popup = Arc::new(RwLock::new(popup)); + let orientation = info.bar_position.get_orientation(); + macro_rules! add_module { ($module:expr, $id:expr) => {{ let common = $module.common.take().expect("Common config did not exist"); let widget = create_module(*$module, $id, &info, &Arc::clone(&popup))?; - let container = wrap_widget(&widget, common); + let container = wrap_widget(&widget, common, orientation); content.add(&container); }}; } diff --git a/src/config/common.rs b/src/config/common.rs index eb65c2d..e0f97b5 100644 --- a/src/config/common.rs +++ b/src/config/common.rs @@ -3,7 +3,7 @@ use crate::script::{Script, ScriptInput}; use crate::send; use gtk::gdk::ScrollDirection; use gtk::prelude::*; -use gtk::EventBox; +use gtk::{EventBox, Orientation, Revealer, RevealerTransitionType}; use serde::Deserialize; use tokio::spawn; use tracing::trace; @@ -13,6 +13,8 @@ use tracing::trace; #[derive(Debug, Deserialize, Clone)] pub struct CommonConfig { pub show_if: Option, + pub transition_type: Option, + pub transition_duration: Option, pub on_click_left: Option, pub on_click_right: Option, @@ -25,10 +27,36 @@ pub struct CommonConfig { pub tooltip: Option, } +#[derive(Debug, Deserialize, Clone)] +#[serde(rename_all = "snake_case")] +pub enum TransitionType { + None, + Crossfade, + SlideStart, + SlideEnd, +} + +impl TransitionType { + pub fn to_revealer_transition_type(&self, orientation: Orientation) -> RevealerTransitionType { + match (self, orientation) { + (TransitionType::SlideStart, Orientation::Horizontal) => { + RevealerTransitionType::SlideLeft + } + (TransitionType::SlideStart, Orientation::Vertical) => RevealerTransitionType::SlideUp, + (TransitionType::SlideEnd, Orientation::Horizontal) => { + RevealerTransitionType::SlideRight + } + (TransitionType::SlideEnd, Orientation::Vertical) => RevealerTransitionType::SlideDown, + (TransitionType::Crossfade, _) => RevealerTransitionType::Crossfade, + _ => RevealerTransitionType::None, + } + } +} + impl CommonConfig { /// Configures the module's container according to the common config options. - pub fn install(mut self, container: &EventBox) { - self.install_show_if(container); + pub fn install(mut self, container: &EventBox, revealer: &Revealer) { + self.install_show_if(container, revealer); let left_click_script = self.on_click_left.map(Script::new_polling); let middle_click_script = self.on_click_middle.map(Script::new_polling); @@ -91,7 +119,7 @@ impl CommonConfig { } } - fn install_show_if(&mut self, container: &EventBox) { + fn install_show_if(&mut self, container: &EventBox, revealer: &Revealer) { self.show_if.take().map_or_else( || { container.show_all(); @@ -100,6 +128,7 @@ impl CommonConfig { let script = Script::new_polling(show_if); let container = container.clone(); let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT); + spawn(async move { script .run(None, |_, success| { @@ -107,13 +136,24 @@ impl CommonConfig { }) .await; }); - rx.attach(None, move |success| { - if success { - container.show_all(); - } else { - container.hide(); - }; - Continue(true) + + { + let revealer = revealer.clone(); + let container = container.clone(); + + rx.attach(None, move |success| { + if success { + container.show_all(); + } + revealer.set_reveal_child(success); + Continue(true) + }); + } + + revealer.connect_child_revealed_notify(move |revealer| { + if !revealer.reveals_child() { + container.hide() + } }); }, ); diff --git a/src/config/mod.rs b/src/config/mod.rs index a55570d..276c262 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -22,7 +22,7 @@ use crate::modules::workspaces::WorkspacesModule; use serde::Deserialize; use std::collections::HashMap; -pub use self::common::CommonConfig; +pub use self::common::{CommonConfig, TransitionType}; pub use self::truncate::{EllipsizeMode, TruncateMode}; #[derive(Debug, Deserialize, Clone)] diff --git a/src/modules/custom/mod.rs b/src/modules/custom/mod.rs index 182c37a..4c49624 100644 --- a/src/modules/custom/mod.rs +++ b/src/modules/custom/mod.rs @@ -120,7 +120,11 @@ impl Widget { fn add_to(self, parent: >k::Box, context: CustomWidgetContext, common: CommonConfig) { macro_rules! create { ($widget:expr) => { - wrap_widget(&$widget.into_widget(context), common) + wrap_widget( + &$widget.into_widget(context), + common, + context.bar_orientation, + ) }; } diff --git a/src/modules/mod.rs b/src/modules/mod.rs index be995d7..c0c6fd7 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -23,14 +23,14 @@ pub mod tray; pub mod workspaces; use crate::bridge_channel::BridgeChannel; -use crate::config::{BarPosition, CommonConfig}; +use crate::config::{BarPosition, CommonConfig, TransitionType}; use crate::popup::{Popup, WidgetGeometry}; use crate::{read_lock, send, write_lock}; use color_eyre::Result; use glib::IsA; use gtk::gdk::{EventMask, Monitor}; use gtk::prelude::*; -use gtk::{Application, EventBox, IconTheme, Widget}; +use gtk::{Application, EventBox, IconTheme, Orientation, Revealer, Widget}; use std::sync::{Arc, RwLock}; use tokio::sync::mpsc; use tracing::debug; @@ -234,12 +234,30 @@ fn setup_receiver( /// Takes a widget and adds it into a new `gtk::EventBox`. /// The event box container is returned. -pub fn wrap_widget>(widget: &W, common: CommonConfig) -> EventBox { +pub fn wrap_widget>( + widget: &W, + common: CommonConfig, + orientation: Orientation, +) -> EventBox { + let revealer = Revealer::builder() + .transition_type( + common + .transition_type + .as_ref() + .unwrap_or(&TransitionType::SlideStart) + .to_revealer_transition_type(orientation), + ) + .transition_duration(common.transition_duration.unwrap_or(250)) + .build(); + + revealer.add(widget); + revealer.set_reveal_child(true); + let container = EventBox::new(); container.add_events(EventMask::SCROLL_MASK); - container.add(widget); + container.add(&revealer); - common.install(&container); + common.install(&container, &revealer); container }