wip: menus
This commit is contained in:
parent
a406859e65
commit
93e3d4fd42
25 changed files with 1358 additions and 243 deletions
|
|
@ -3,17 +3,24 @@
|
|||
|
||||
use std::{cell::OnceCell, collections::HashMap};
|
||||
|
||||
use crate::widget::nav_bar;
|
||||
use crate::{
|
||||
theme::menu_bar,
|
||||
widget::{
|
||||
button, icon,
|
||||
menu::{self, Tree},
|
||||
nav_bar, responsive_container,
|
||||
},
|
||||
};
|
||||
use cosmic_config::CosmicConfigEntry;
|
||||
use cosmic_theme::ThemeMode;
|
||||
use iced::window;
|
||||
use iced_core::window::Id;
|
||||
use iced::{window, Limits, Size};
|
||||
use iced_core::{window::Id, Element};
|
||||
use palette::Srgba;
|
||||
use slotmap::Key;
|
||||
|
||||
use crate::Theme;
|
||||
|
||||
use super::{Element, Task};
|
||||
use super::{message::SurfaceMessage, Renderer, Task};
|
||||
|
||||
/// Status of the nav bar and its panels.
|
||||
#[derive(Clone)]
|
||||
|
|
@ -97,6 +104,8 @@ pub struct Core {
|
|||
pub(crate) main_window: Option<window::Id>,
|
||||
|
||||
pub(crate) exit_on_main_window_closed: bool,
|
||||
|
||||
pub(crate) menu_bars: HashMap<crate::widget::Id, (Limits, Size)>,
|
||||
}
|
||||
|
||||
impl Default for Core {
|
||||
|
|
@ -153,6 +162,7 @@ impl Default for Core {
|
|||
portal_is_high_contrast: None,
|
||||
main_window: None,
|
||||
exit_on_main_window_closed: true,
|
||||
menu_bars: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -376,4 +386,35 @@ impl Core {
|
|||
std::mem::swap(&mut self.main_window, &mut id);
|
||||
id
|
||||
}
|
||||
|
||||
pub fn responsive_menu_bar<'a, Message: Clone + From<SurfaceMessage> + 'static>(
|
||||
&self,
|
||||
id: crate::widget::Id,
|
||||
roots: Vec<Tree<'a, Message, Renderer>>,
|
||||
) -> crate::Element<'a, Message> {
|
||||
let menu_bar_size = self.menu_bars.get(&id);
|
||||
if !menu_bar_size.is_some_and(|(limits, size)| {
|
||||
let max_size = limits.max();
|
||||
|
||||
max_size.width < size.width
|
||||
}) {
|
||||
crate::Element::from(responsive_container::responsive_container(
|
||||
menu::bar(roots),
|
||||
id,
|
||||
))
|
||||
} else {
|
||||
crate::Element::from(
|
||||
responsive_container::responsive_container(
|
||||
menu::bar(vec![menu::Tree::<'a, _, _>::with_children(
|
||||
button::icon(icon::from_name("open-menu-symbolic"))
|
||||
.padding([4, 12])
|
||||
.class(crate::theme::Button::MenuRoot),
|
||||
roots,
|
||||
)]),
|
||||
id,
|
||||
)
|
||||
.size(menu_bar_size.unwrap().1),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,8 +124,7 @@ where
|
|||
let message = match message {
|
||||
super::Message::App(message) => {
|
||||
match super::message::SurfaceMessageHandler::to_surface_message(message) {
|
||||
super::message::MessageWrapper::Surface(surface_message) =>
|
||||
{
|
||||
super::message::MessageWrapper::Surface(surface_message) => {
|
||||
#[cfg(feature = "wayland")]
|
||||
match surface_message {
|
||||
super::message::SurfaceMessage::Subsurface(settings, view) => {
|
||||
|
|
@ -160,7 +159,6 @@ where
|
|||
))
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "wayland")]
|
||||
super::message::SurfaceMessage::Popup(settings, view) => {
|
||||
let Some(settings) = std::sync::Arc::try_unwrap(settings)
|
||||
.ok()
|
||||
|
|
@ -200,7 +198,18 @@ where
|
|||
super::message::SurfaceMessage::DestroySubsurface(id) => {
|
||||
iced_winit::commands::subsurface::destroy_subsurface(id)
|
||||
}
|
||||
super::message::SurfaceMessage::ResponsiveMenuBar {
|
||||
menu_bar,
|
||||
limits,
|
||||
size,
|
||||
} => {
|
||||
let core = self.app.core_mut();
|
||||
core.menu_bars.insert(menu_bar, (limits, size));
|
||||
iced::Task::none()
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "wayland"))]
|
||||
iced::Task::none()
|
||||
}
|
||||
super::message::MessageWrapper::Message(message) => self.app.update(message),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ pub(crate) mod multi_window;
|
|||
pub mod settings;
|
||||
|
||||
pub mod message {
|
||||
use iced::{Limits, Size};
|
||||
|
||||
pub enum MessageWrapper<M> {
|
||||
Surface(SurfaceMessage),
|
||||
Message(M),
|
||||
|
|
@ -31,6 +33,7 @@ pub mod message {
|
|||
}
|
||||
}
|
||||
|
||||
/// Ignore this message in your application. It will be intercepted.
|
||||
#[derive(Clone)]
|
||||
pub enum SurfaceMessage {
|
||||
/// Create a subsurface with a view function
|
||||
|
|
@ -47,20 +50,39 @@ pub mod message {
|
|||
),
|
||||
/// Destroy a subsurface with a view function
|
||||
DestroyPopup(iced::window::Id),
|
||||
/// Responsive menu bar update
|
||||
ResponsiveMenuBar {
|
||||
/// Id of the menu bar
|
||||
menu_bar: crate::widget::Id,
|
||||
/// Limits of the menu bar
|
||||
limits: Limits,
|
||||
/// Requested Full Size for expanded menu bar
|
||||
size: Size,
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(feature = "wayland")]
|
||||
impl std::fmt::Debug for SurfaceMessage {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
SurfaceMessage::Subsurface(any, any1) => f.debug_tuple("Subsurface").finish(),
|
||||
SurfaceMessage::DestroySubsurface(id) => {
|
||||
f.debug_tuple("DestroySubsurface").field(id).finish()
|
||||
Self::Subsurface(arg0, arg1) => {
|
||||
f.debug_tuple("Subsurface").field(arg0).field(arg1).finish()
|
||||
}
|
||||
SurfaceMessage::Popup(any, any1) => f.debug_tuple("Popup").finish(),
|
||||
SurfaceMessage::DestroyPopup(id) => {
|
||||
f.debug_tuple("DestroyPopup").field(id).finish()
|
||||
Self::DestroySubsurface(arg0) => {
|
||||
f.debug_tuple("DestroySubsurface").field(arg0).finish()
|
||||
}
|
||||
Self::Popup(arg0, arg1) => f.debug_tuple("Popup").field(arg0).field(arg1).finish(),
|
||||
Self::DestroyPopup(arg0) => f.debug_tuple("DestroyPopup").field(arg0).finish(),
|
||||
Self::ResponsiveMenuBar {
|
||||
menu_bar,
|
||||
limits,
|
||||
size,
|
||||
} => f
|
||||
.debug_struct("ResponsiveMenuBar")
|
||||
.field("menu_bar", menu_bar)
|
||||
.field("limits", limits)
|
||||
.field("size", size)
|
||||
.finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -149,6 +171,20 @@ pub mod message {
|
|||
))
|
||||
}
|
||||
|
||||
// TODO could this somehow be used by widgets? It is the wrong message type though.
|
||||
// #[cfg(feature = "wayland")]
|
||||
// pub fn get_simple_popup<App: super::Application>(
|
||||
// settings: iced_runtime::platform_specific::wayland::popup::SctkPopupSettings,
|
||||
// view: Option<
|
||||
// impl Fn() -> crate::Element<'static, super::Message<App::Message>> + Send + Sync + 'static,
|
||||
// >,
|
||||
// ) -> App::Message
|
||||
// where
|
||||
// App::Message: SurfaceMessageHandler + From<SurfaceMessage>,
|
||||
// {
|
||||
// todo!()
|
||||
// }
|
||||
|
||||
#[cfg(feature = "wayland")]
|
||||
pub fn get_subsurface<App: super::Application>(
|
||||
settings: impl Fn(&mut App) -> iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings + Send + Sync + 'static,
|
||||
|
|
@ -477,7 +513,7 @@ impl DbusActivation {
|
|||
pub fn run_single_instance<App: Application>(settings: Settings, flags: App::Flags) -> iced::Result
|
||||
where
|
||||
App::Flags: CosmicFlags,
|
||||
App::Message: Clone + std::fmt::Debug + Send + 'static,
|
||||
App::Message: Clone + std::fmt::Debug + Send + SurfaceMessageHandler + 'static,
|
||||
{
|
||||
let activation_token = std::env::var("XDG_ACTIVATION_TOKEN").ok();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue