diff --git a/src/app/core.rs b/src/app/core.rs index 02223bf40f5..9c78625450f 100644 --- a/src/app/core.rs +++ b/src/app/core.rs @@ -32,6 +32,7 @@ pub struct Window { pub header_title: String, pub use_template: bool, pub content_container: bool, + pub context_is_overlay: bool, pub sharp_corners: bool, pub show_context: bool, pub show_headerbar: bool, @@ -126,6 +127,7 @@ impl Default for Core { header_title: String::new(), use_template: true, content_container: true, + context_is_overlay: true, sharp_corners: false, show_context: false, show_headerbar: true, @@ -198,10 +200,34 @@ impl Core { /// Call this whenever the scaling factor or window width has changed. #[allow(clippy::cast_precision_loss)] fn is_condensed_update(&mut self) { - self.is_condensed = (600.0 * self.scale_factor) > self.window.width as f32; + //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 + }; + self.is_condensed = (breakpoint * self.scale_factor) > self.window.width as f32; self.nav_bar_update(); } + fn condensed_conflict(&self) -> bool { + // There is a conflict if the view is condensed and both the nav bar and context drawer are open on the same layer + self.is_condensed + && self.nav_bar.toggled_condensed + && self.window.show_context + && !self.window.context_is_overlay + } + + pub fn set_show_context(&mut self, show: bool) { + self.window.show_context = show; + self.is_condensed_update(); + // Ensure nav bar is closed if condensed view and context drawer is opened + if self.condensed_conflict() { + self.nav_bar.toggled_condensed = false; + self.is_condensed_update(); + } + } + /// Whether the nav panel is visible or not #[must_use] pub fn nav_bar_active(&self) -> bool { @@ -233,6 +259,16 @@ impl Core { pub(crate) fn nav_bar_set_toggled_condensed(&mut self, toggled: bool) { self.nav_bar.toggled_condensed = toggled; self.nav_bar_update(); + // Ensure context drawer is closed if condensed view and nav bar is opened + if self.condensed_conflict() { + self.window.show_context = false; + self.is_condensed_update(); + // Sync nav bar state if the view is no longer condensed after closing the context drawer + if !self.is_condensed { + self.nav_bar.toggled = toggled; + self.nav_bar_update(); + } + } } pub(crate) fn nav_bar_update(&mut self) { diff --git a/src/app/cosmic.rs b/src/app/cosmic.rs index 25f0075e804..1a62713e006 100644 --- a/src/app/cosmic.rs +++ b/src/app/cosmic.rs @@ -385,7 +385,7 @@ impl Cosmic { }, Message::ContextDrawer(show) => { - self.app.core_mut().window.show_context = show; + self.app.core_mut().set_show_context(show); return self.app.on_context_drawer(); } diff --git a/src/app/mod.rs b/src/app/mod.rs index 5a56f23ae3e..095dd66a888 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -50,13 +50,13 @@ pub use self::core::Core; pub use self::settings::Settings; use crate::prelude::*; use crate::theme::THEME; -use crate::widget::{context_drawer, id_container, menu, nav_bar, popover}; +use crate::widget::{context_drawer, horizontal_space, id_container, menu, nav_bar, popover}; use apply::Apply; -use iced::Subscription; #[cfg(all(feature = "winit", feature = "multi-window"))] use iced::{multi_window::Application as IcedApplication, window}; #[cfg(any(not(feature = "winit"), not(feature = "multi-window")))] use iced::{window, Application as IcedApplication}; +use iced::{Length, Subscription}; pub use message::Message; use url::Url; #[cfg(feature = "single-instance")] @@ -581,6 +581,11 @@ pub trait ApplicationExt: Application { self.core_mut().set_context_title(title); } + /// Set the context drawer visibility. + fn set_show_context(&mut self, show: bool) { + self.core_mut().set_show_context(show); + } + /// Set the header bar title. fn set_header_title(&mut self, title: String) { self.core_mut().set_header_title(title); @@ -648,7 +653,7 @@ impl ApplicationExt for App { .is_some_and(|i| i == self.main_window_id()); let content_row = crate::widget::row::with_children({ - let mut widgets = Vec::with_capacity(2); + let mut widgets = Vec::with_capacity(3); // Insert nav bar onto the left side of the window. if let Some(nav) = self @@ -659,24 +664,33 @@ impl ApplicationExt for App { } if self.nav_model().is_none() || core.show_content() { - let main_content = self.view().map(Message::App); - - widgets.push(if let Some(context) = self.context_drawer() { - context_drawer( - &core.window.context_title, - Message::Cosmic(cosmic::Message::ContextDrawer(false)), - main_content, - context.map(Message::App), - ) - .apply(|drawer| { - Element::from(id_container( - drawer, - iced_core::id::Id::new("COSMIC_context_drawer"), - )) - }) + widgets.push(self.view().map(Message::App)); + + if let Some(context) = self.context_drawer() { + widgets.push( + context_drawer( + &core.window.context_title, + Message::Cosmic(cosmic::Message::ContextDrawer(false)), + //TODO: this is a hack to allow toggling overlay + horizontal_space(if core.window.context_is_overlay { + Length::Shrink + } else { + //TODO: this width must be synced with the context drawer width + Length::Fixed(480.0) + }), + context.map(Message::App), + ) + .apply(|drawer| { + Element::from(id_container( + drawer, + iced_core::id::Id::new("COSMIC_context_drawer"), + )) + }), + ); } else { - main_content - }); + //TODO: this element is added to prevent state issues + widgets.push(horizontal_space(Length::Shrink).into()); + } } widgets