From bbcd874d9c01a7336d5e64ddac8c1c8e1c6d1a6f Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Tue, 15 Apr 2025 09:41:01 -0400 Subject: [PATCH] refactor: responsive headers should allow some options --- examples/application/src/main.rs | 40 +++---- src/app/cosmic.rs | 9 +- src/widget/mod.rs | 2 +- src/widget/responsive_menu_bar.rs | 177 +++++++++++++++++++----------- 4 files changed, 142 insertions(+), 86 deletions(-) diff --git a/examples/application/src/main.rs b/examples/application/src/main.rs index 50329298..92c2c242 100644 --- a/examples/application/src/main.rs +++ b/examples/application/src/main.rs @@ -168,8 +168,10 @@ impl cosmic::Application for App { Message::ToggleHide => { self.hidden = !self.hidden; } - Message::Surface(_) => { - // unimplemented!() + Message::Surface(a) => { + return cosmic::task::message(cosmic::Action::Cosmic( + cosmic::app::Action::Surface(a), + )); } Message::Hi => { dbg!("hi"); @@ -280,49 +282,49 @@ impl cosmic::Application for App { } #[cfg(feature = "wayland")] { - vec![cosmic::widget::responsive_menu_bar( + vec![cosmic::widget::responsive_menu_bar().into_element( self.core(), &self.keybinds, MENU_ID.clone(), Message::Surface, vec![ ( - "hiiiiiiiiiiiiiiiiiii 1".into(), - vec![menu::Item::Button("hi 1".into(), None, Action::Hi)], + "hiiiiiiiiiiiiiiiiiii 1", + vec![menu::Item::Button("hi 1", None, Action::Hi)], ), ( "hiiiiiiiiiiiiiiiiiii 2".into(), vec![ - menu::Item::Button("hi 2".into(), None, Action::Hi), - menu::Item::Button("hi 22".into(), None, Action::Hi), + menu::Item::Button("hi 2", None, Action::Hi), + menu::Item::Button("hi 22", None, Action::Hi), ], ), ( "hiiiiiiiiiiiiiiiiiii 3".into(), vec![ - menu::Item::Button("hi 3".into(), None, Action::Hi), - menu::Item::Button("hi 33".into(), None, Action::Hi), - menu::Item::Button("hi 333".into(), None, Action::Hi), + menu::Item::Button("hi 3", None, Action::Hi), + menu::Item::Button("hi 33", None, Action::Hi), + menu::Item::Button("hi 333", None, Action::Hi), ], ), ( "hiiiiiiiiiiiiiiiiiii 4".into(), vec![ - menu::Item::Button("hi 4".into(), None, Action::Hi), - menu::Item::Button("hi 44".into(), None, Action::Hi), - menu::Item::Button("hi 444".into(), None, Action::Hi), + menu::Item::Button("hi 4", None, Action::Hi), + menu::Item::Button("hi 44", None, Action::Hi), + menu::Item::Button("hi 444", None, Action::Hi), menu::Item::Folder( "nest 4".into(), vec![ - menu::Item::Button("hi 4".into(), None, Action::Hi), - menu::Item::Button("hi 44".into(), None, Action::Hi), - menu::Item::Button("hi 444".into(), None, Action::Hi), + menu::Item::Button("hi 4", None, Action::Hi), + menu::Item::Button("hi 44", None, Action::Hi), + menu::Item::Button("hi 444", None, Action::Hi), menu::Item::Folder( "nest 2 4".into(), vec![ - menu::Item::Button("hi 4".into(), None, Action::Hi), - menu::Item::Button("hi 44".into(), None, Action::Hi), - menu::Item::Button("hi 444".into(), None, Action::Hi), + menu::Item::Button("hi 4", None, Action::Hi), + menu::Item::Button("hi 44", None, Action::Hi), + menu::Item::Button("hi 444", None, Action::Hi), ], ), ], diff --git a/src/app/cosmic.rs b/src/app/cosmic.rs index ec129d33..40748473 100644 --- a/src/app/cosmic.rs +++ b/src/app/cosmic.rs @@ -61,8 +61,9 @@ where &mut self, _surface_message: crate::surface::Action, ) -> iced::Task> { - #[cfg(feature = "wayland")] + #[cfg(feature = "surface-message")] match _surface_message { + #[cfg(feature = "wayland")] crate::surface::Action::AppSubsurface(settings, view) => { let Some(settings) = std::sync::Arc::try_unwrap(settings) .ok() @@ -91,6 +92,7 @@ where iced_winit::commands::subsurface::get_subsurface(settings(&mut self.app)) } } + #[cfg(feature = "wayland")] crate::surface::Action::Subsurface(settings, view) => { let Some(settings) = std::sync::Arc::try_unwrap(settings) .ok() @@ -117,6 +119,7 @@ where iced_winit::commands::subsurface::get_subsurface(settings()) } } + #[cfg(feature = "wayland")] crate::surface::Action::AppPopup(settings, view) => { let Some(settings) = std::sync::Arc::try_unwrap(settings) .ok() @@ -162,6 +165,7 @@ where core.menu_bars.insert(menu_bar, (limits, size)); iced::Task::none() } + #[cfg(feature = "wayland")] crate::surface::Action::Popup(settings, view) => { let Some(settings) = std::sync::Arc::try_unwrap(settings) .ok() @@ -192,9 +196,10 @@ where crate::surface::Action::Task(f) => { f().map(|sm| crate::Action::Cosmic(Action::Surface(sm))) } + _ => iced::Task::none(), } - #[cfg(not(feature = "wayland"))] + #[cfg(not(feature = "surface-message"))] iced::Task::none() } diff --git a/src/widget/mod.rs b/src/widget/mod.rs index 746292d3..f212906a 100644 --- a/src/widget/mod.rs +++ b/src/widget/mod.rs @@ -103,7 +103,7 @@ pub(crate) mod responsive_container; mod responsive_menu_bar; #[cfg(feature = "surface-message")] #[doc(inline)] -pub use responsive_menu_bar::responsive_menu_bar; +pub use responsive_menu_bar::{ResponsiveMenuBar, responsive_menu_bar}; pub mod button; #[doc(inline)] diff --git a/src/widget/responsive_menu_bar.rs b/src/widget/responsive_menu_bar.rs index 41f9eae8..c2ee1308 100644 --- a/src/widget/responsive_menu_bar.rs +++ b/src/widget/responsive_menu_bar.rs @@ -7,72 +7,121 @@ use crate::{ widget::{button, icon, responsive_container}, }; -use super::menu; +use super::menu::{self, ItemHeight, ItemWidth}; -/// # Panics -/// -/// Will panic if the menu bar collapses without tracking the size -pub fn responsive_menu_bar<'a, Message: Clone + 'static, A: menu::Action>( - core: &Core, - key_binds: &HashMap, - id: crate::widget::Id, - action_message: impl Fn(crate::surface::Action) -> Message + 'static, - trees: Vec<( - std::borrow::Cow<'static, str>, - Vec>>, - )>, -) -> Element<'a, Message> { - use crate::widget::id_container; +pub fn responsive_menu_bar() -> ResponsiveMenuBar { + ResponsiveMenuBar::default() +} - let menu_bar_size = core.menu_bars.get(&id); +pub struct ResponsiveMenuBar { + item_width: ItemWidth, + item_height: ItemHeight, + spacing: f32, +} - #[allow(clippy::if_not_else)] - if !menu_bar_size.is_some_and(|(limits, size)| { - let max_size = limits.max(); - max_size.width < size.width - }) { - responsive_container::responsive_container( - id_container( - menu::bar( - trees - .into_iter() - .map(|mt| { - menu::Tree::<_>::with_children( - menu::root(mt.0), - menu::items(key_binds, mt.1), - ) - }) - .collect(), - ), - crate::widget::Id::new(format!("menu_bar_expanded_{id}")), - ), - id, - action_message, - ) - .apply(Element::from) - } else { - responsive_container::responsive_container( - id_container( - menu::bar(vec![menu::Tree::<_>::with_children( - Element::from( - button::icon(icon::from_name("open-menu-symbolic")) - .padding([4, 12]) - .class(crate::theme::Button::MenuRoot), - ), - menu::items( - key_binds, - trees - .into_iter() - .map(|mt| menu::Item::Folder(mt.0, mt.1)) - .collect(), - ), - )]), - crate::widget::Id::new(format!("menu_bar_collapsed_{id}")), - ), - id, - action_message, - ) - .size(menu_bar_size.unwrap().1) - .apply(Element::from) +impl Default for ResponsiveMenuBar { + fn default() -> ResponsiveMenuBar { + ResponsiveMenuBar { + item_width: ItemWidth::Uniform(150), + item_height: ItemHeight::Uniform(30), + spacing: 0., + } + } +} + +impl ResponsiveMenuBar { + /// Set the item width + pub fn item_width(mut self, item_width: ItemWidth) -> Self { + self.item_width = item_width; + self + } + + /// Set the item height + pub fn item_height(mut self, item_height: ItemHeight) -> Self { + self.item_height = item_height; + self + } + + /// Set the spacing + pub fn spacing(mut self, spacing: f32) -> Self { + self.spacing = spacing; + self + } + + /// # Panics + /// + /// Will panic if the menu bar collapses without tracking the size + pub fn into_element< + 'a, + Message: Clone + 'static, + A: menu::Action, + S: Into> + 'static, + >( + self, + core: &Core, + key_binds: &HashMap, + id: crate::widget::Id, + action_message: impl Fn(crate::surface::Action) -> Message + 'static, + trees: Vec<(S, Vec>)>, + ) -> Element<'a, Message> { + use crate::widget::id_container; + + let menu_bar_size = core.menu_bars.get(&id); + + #[allow(clippy::if_not_else)] + if !menu_bar_size.is_some_and(|(limits, size)| { + let max_size = limits.max(); + max_size.width < size.width + }) { + responsive_container::responsive_container( + id_container( + menu::bar( + trees + .into_iter() + .map(|mt| { + menu::Tree::<_>::with_children( + menu::root(mt.0), + menu::items(key_binds, mt.1.into()), + ) + }) + .collect(), + ) + .item_width(self.item_width) + .item_height(self.item_height) + .spacing(self.spacing), + crate::widget::Id::new(format!("menu_bar_expanded_{id}")), + ), + id, + action_message, + ) + .apply(Element::from) + } else { + responsive_container::responsive_container( + id_container( + menu::bar(vec![menu::Tree::<_>::with_children( + Element::from( + button::icon(icon::from_name("open-menu-symbolic")) + .padding([4, 12]) + .class(crate::theme::Button::MenuRoot), + ), + menu::items( + key_binds, + trees + .into_iter() + .map(|mt| menu::Item::Folder(mt.0, mt.1.into())) + .collect(), + ), + )]) + .item_height(self.item_height) + .item_width(self.item_width) + .spacing(self.spacing), + crate::widget::Id::new(format!("menu_bar_collapsed_{id}")), + ), + id, + action_message, + ) + .size(menu_bar_size.unwrap().1) + .apply(Element::from) + } } }