From 10f02d9d6b629a58e0298edc5a7dea27e7a86098 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 23 Sep 2024 10:02:34 -0600 Subject: [PATCH] Responsive context drawer width --- src/app/core.rs | 25 +++++++++++++++++++++---- src/app/mod.rs | 15 +++++++++++---- src/widget/context_drawer/mod.rs | 3 ++- src/widget/context_drawer/widget.rs | 3 ++- 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/app/core.rs b/src/app/core.rs index 9c78625450f..ad9ca2a7de8 100644 --- a/src/app/core.rs +++ b/src/app/core.rs @@ -200,11 +200,12 @@ impl Core { /// Call this whenever the scaling factor or window width has changed. #[allow(clippy::cast_precision_loss)] fn is_condensed_update(&mut self) { + // Nav bar (280px) + padding (8px) + content (360px) + let mut breakpoint = 280.0 + 8.0 + 360.0; //TODO: the app may return None from the context_drawer function even if show_context is true - let breakpoint = if self.window.show_context && !self.window.context_is_overlay { - 1136.0 - } else { - 648.0 + if self.window.show_context && !self.window.context_is_overlay { + // Context drawer min width (344px) + padding (8px) + breakpoint += 344.0 + 8.0; }; self.is_condensed = (breakpoint * self.scale_factor) > self.window.width as f32; self.nav_bar_update(); @@ -218,6 +219,22 @@ impl Core { && !self.window.context_is_overlay } + pub(crate) fn context_width(&self, has_nav: bool) -> f32 { + let window_width = (self.window.width as f32) / self.scale_factor; + + // Content width (360px) + padding (8px) + let mut reserved_width = 360.0 + 8.0; + if has_nav { + // Navbar width (280px) + padding (8px) + reserved_width += 280.0 + 8.0; + } + + // This logic is to ensure the context drawer does not take up too much of the content's space + // The minimum width is 344px and the maximum with is 480px + // We want to keep the content at least 360px until going down to the minimum width + (window_width - reserved_width).min(480.0).max(344.0) + } + pub fn set_show_context(&mut self, show: bool) { self.window.show_context = show; self.is_condensed_update(); diff --git a/src/app/mod.rs b/src/app/mod.rs index a7a0665e69f..c703b32caaf 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -656,22 +656,26 @@ impl ApplicationExt for App { let mut widgets = Vec::with_capacity(4); // Insert nav bar onto the left side of the window. - if let Some(nav) = self + let has_nav = if let Some(nav) = self .nav_bar() .map(|nav| id_container(nav, iced_core::id::Id::new("COSMIC_nav_bar"))) { widgets.push(nav.into()); - } + true + } else { + false + }; if self.nav_model().is_none() || core.show_content() { // Manual spacing must be used due to state workarounds below - if !widgets.is_empty() { + if has_nav { widgets.push(horizontal_space(Length::Fixed(8.0)).into()); } let main_content = self.view().map(Message::App); //TODO: reduce duplication + let context_width = core.context_width(has_nav); if core.window.context_is_overlay { if let Some(context) = self.context_drawer() { widgets.push( @@ -680,6 +684,7 @@ impl ApplicationExt for App { Message::Cosmic(cosmic::Message::ContextDrawer(false)), main_content, context.map(Message::App), + context_width, ) .apply(|drawer| { Element::from(id_container( @@ -692,6 +697,7 @@ impl ApplicationExt for App { widgets.push(main_content); } } else { + //TODO: hide content when out of space widgets.push(main_content); if let Some(context) = self.context_drawer() { widgets.push( @@ -702,9 +708,10 @@ impl ApplicationExt for App { horizontal_space( //TODO: this width must be synced with the context drawer width // Manual spacing must be used due to state workarounds below - Length::Fixed(480.0 + 8.0), + Length::Fixed(context_width + 8.0), ), context.map(Message::App), + context_width, ) .apply(|drawer| { Element::from(id_container( diff --git a/src/widget/context_drawer/mod.rs b/src/widget/context_drawer/mod.rs index 258b4f88920..52b9a0072f7 100644 --- a/src/widget/context_drawer/mod.rs +++ b/src/widget/context_drawer/mod.rs @@ -16,10 +16,11 @@ pub fn context_drawer<'a, Message: Clone + 'static, Content, Drawer>( on_close: Message, content: Content, drawer: Drawer, + max_width: f32, ) -> ContextDrawer<'a, Message> where Content: Into>, Drawer: Into>, { - ContextDrawer::new(header, content, drawer, on_close) + ContextDrawer::new(header, content, drawer, on_close, max_width) } diff --git a/src/widget/context_drawer/widget.rs b/src/widget/context_drawer/widget.rs index 7aba4b69846..98056266584 100644 --- a/src/widget/context_drawer/widget.rs +++ b/src/widget/context_drawer/widget.rs @@ -33,6 +33,7 @@ impl<'a, Message: Clone + 'static> ContextDrawer<'a, Message> { content: Content, drawer: Drawer, on_close: Message, + max_width: f32, ) -> Self where Content: Into>, @@ -92,7 +93,7 @@ impl<'a, Message: Clone + 'static> ContextDrawer<'a, Message> { .style(crate::style::Container::ContextDrawer) .width(Length::Fill) .height(Length::Fill) - .max_width(480.0), + .max_width(max_width), ) .width(Length::Fill) .height(Length::Fill)