1
0
Fork 0
mirror of https://github.com/Zedfrigg/ironbar.git synced 2025-07-01 02:31:04 +02:00

feat: wrap modules in a revealer to support animated show/hide

Resolves #72.
This commit is contained in:
Jake Stanger 2023-04-22 14:49:15 +01:00
parent 1855416db4
commit 83f44fd92f
No known key found for this signature in database
GPG key ID: C51FC8F9CB0BEA61
5 changed files with 83 additions and 19 deletions

View file

@ -190,11 +190,13 @@ fn add_modules(
let popup = Popup::new(info, popup_gap); let popup = Popup::new(info, popup_gap);
let popup = Arc::new(RwLock::new(popup)); let popup = Arc::new(RwLock::new(popup));
let orientation = info.bar_position.get_orientation();
macro_rules! add_module { macro_rules! add_module {
($module:expr, $id:expr) => {{ ($module:expr, $id:expr) => {{
let common = $module.common.take().expect("Common config did not exist"); let common = $module.common.take().expect("Common config did not exist");
let widget = create_module(*$module, $id, &info, &Arc::clone(&popup))?; 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); content.add(&container);
}}; }};
} }

View file

@ -3,7 +3,7 @@ use crate::script::{Script, ScriptInput};
use crate::send; use crate::send;
use gtk::gdk::ScrollDirection; use gtk::gdk::ScrollDirection;
use gtk::prelude::*; use gtk::prelude::*;
use gtk::EventBox; use gtk::{EventBox, Orientation, Revealer, RevealerTransitionType};
use serde::Deserialize; use serde::Deserialize;
use tokio::spawn; use tokio::spawn;
use tracing::trace; use tracing::trace;
@ -13,6 +13,8 @@ use tracing::trace;
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
pub struct CommonConfig { pub struct CommonConfig {
pub show_if: Option<ScriptInput>, pub show_if: Option<ScriptInput>,
pub transition_type: Option<TransitionType>,
pub transition_duration: Option<u32>,
pub on_click_left: Option<ScriptInput>, pub on_click_left: Option<ScriptInput>,
pub on_click_right: Option<ScriptInput>, pub on_click_right: Option<ScriptInput>,
@ -25,10 +27,36 @@ pub struct CommonConfig {
pub tooltip: Option<String>, pub tooltip: Option<String>,
} }
#[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 { impl CommonConfig {
/// Configures the module's container according to the common config options. /// Configures the module's container according to the common config options.
pub fn install(mut self, container: &EventBox) { pub fn install(mut self, container: &EventBox, revealer: &Revealer) {
self.install_show_if(container); self.install_show_if(container, revealer);
let left_click_script = self.on_click_left.map(Script::new_polling); let left_click_script = self.on_click_left.map(Script::new_polling);
let middle_click_script = self.on_click_middle.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( self.show_if.take().map_or_else(
|| { || {
container.show_all(); container.show_all();
@ -100,6 +128,7 @@ impl CommonConfig {
let script = Script::new_polling(show_if); let script = Script::new_polling(show_if);
let container = container.clone(); let container = container.clone();
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT); let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
spawn(async move { spawn(async move {
script script
.run(None, |_, success| { .run(None, |_, success| {
@ -107,13 +136,24 @@ impl CommonConfig {
}) })
.await; .await;
}); });
rx.attach(None, move |success| {
if success { {
container.show_all(); let revealer = revealer.clone();
} else { let container = container.clone();
container.hide();
}; rx.attach(None, move |success| {
Continue(true) 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()
}
}); });
}, },
); );

View file

@ -22,7 +22,7 @@ use crate::modules::workspaces::WorkspacesModule;
use serde::Deserialize; use serde::Deserialize;
use std::collections::HashMap; use std::collections::HashMap;
pub use self::common::CommonConfig; pub use self::common::{CommonConfig, TransitionType};
pub use self::truncate::{EllipsizeMode, TruncateMode}; pub use self::truncate::{EllipsizeMode, TruncateMode};
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]

View file

@ -120,7 +120,11 @@ impl Widget {
fn add_to(self, parent: &gtk::Box, context: CustomWidgetContext, common: CommonConfig) { fn add_to(self, parent: &gtk::Box, context: CustomWidgetContext, common: CommonConfig) {
macro_rules! create { macro_rules! create {
($widget:expr) => { ($widget:expr) => {
wrap_widget(&$widget.into_widget(context), common) wrap_widget(
&$widget.into_widget(context),
common,
context.bar_orientation,
)
}; };
} }

View file

@ -23,14 +23,14 @@ pub mod tray;
pub mod workspaces; pub mod workspaces;
use crate::bridge_channel::BridgeChannel; use crate::bridge_channel::BridgeChannel;
use crate::config::{BarPosition, CommonConfig}; use crate::config::{BarPosition, CommonConfig, TransitionType};
use crate::popup::{Popup, WidgetGeometry}; use crate::popup::{Popup, WidgetGeometry};
use crate::{read_lock, send, write_lock}; use crate::{read_lock, send, write_lock};
use color_eyre::Result; use color_eyre::Result;
use glib::IsA; use glib::IsA;
use gtk::gdk::{EventMask, Monitor}; use gtk::gdk::{EventMask, Monitor};
use gtk::prelude::*; use gtk::prelude::*;
use gtk::{Application, EventBox, IconTheme, Widget}; use gtk::{Application, EventBox, IconTheme, Orientation, Revealer, Widget};
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use tokio::sync::mpsc; use tokio::sync::mpsc;
use tracing::debug; use tracing::debug;
@ -234,12 +234,30 @@ fn setup_receiver<TSend>(
/// Takes a widget and adds it into a new `gtk::EventBox`. /// Takes a widget and adds it into a new `gtk::EventBox`.
/// The event box container is returned. /// The event box container is returned.
pub fn wrap_widget<W: IsA<Widget>>(widget: &W, common: CommonConfig) -> EventBox { pub fn wrap_widget<W: IsA<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(); let container = EventBox::new();
container.add_events(EventMask::SCROLL_MASK); container.add_events(EventMask::SCROLL_MASK);
container.add(widget); container.add(&revealer);
common.install(&container); common.install(&container, &revealer);
container container
} }