wip: popup
This commit is contained in:
parent
8642a92270
commit
a372ce800f
8 changed files with 469 additions and 159 deletions
|
|
@ -46,13 +46,19 @@ impl Page {
|
|||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum Action {
|
||||
Hi,
|
||||
Hi2,
|
||||
Hi3,
|
||||
}
|
||||
|
||||
impl MenuAction for Action {
|
||||
type Message = Message;
|
||||
|
||||
fn message(&self) -> Message {
|
||||
Message::Hi
|
||||
match self {
|
||||
Action::Hi => Message::Hi,
|
||||
Action::Hi2 => Message::Hi2,
|
||||
Action::Hi3 => Message::Hi3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -86,6 +92,8 @@ pub enum Message {
|
|||
ToggleHide,
|
||||
Surface(cosmic::surface::Action),
|
||||
Hi,
|
||||
Hi2,
|
||||
Hi3,
|
||||
}
|
||||
|
||||
/// The [`App`] stores application-specific state.
|
||||
|
|
@ -176,6 +184,12 @@ impl cosmic::Application for App {
|
|||
Message::Hi => {
|
||||
dbg!("hi");
|
||||
}
|
||||
Message::Hi2 => {
|
||||
dbg!("hi 2");
|
||||
}
|
||||
Message::Hi3 => {
|
||||
dbg!("hi 3");
|
||||
}
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
|
@ -222,123 +236,60 @@ impl cosmic::Application for App {
|
|||
|
||||
fn header_start(&self) -> Vec<Element<Self::Message>> {
|
||||
use cosmic::widget::menu::Tree;
|
||||
#[cfg(not(feature = "wayland"))]
|
||||
{
|
||||
|
||||
vec![cosmic::widget::responsive_menu_bar(
|
||||
self.core(),
|
||||
&self.keybinds,
|
||||
MENU_ID.clone(),
|
||||
Message::Surface,
|
||||
vec![
|
||||
cosmic::widget::menu::bar(vec![
|
||||
Tree::with_children(
|
||||
menu::root("hiiiiiiiiiiiiiiiiiii 1"),
|
||||
menu::items(
|
||||
&self.keybinds,
|
||||
vec![menu::Item::Button("hi", None, Action::Hi)],
|
||||
),
|
||||
),
|
||||
Tree::with_children(
|
||||
menu::root("hiiiiiiiiiiiiiiiiii 2"),
|
||||
menu::items(
|
||||
&self.keybinds,
|
||||
vec![menu::Item::Button("hi 2", None, Action::Hi)],
|
||||
),
|
||||
),
|
||||
Tree::with_children(
|
||||
menu::root("hiiiiiiiiiiiiiiiiiiiii 3"),
|
||||
menu::items(
|
||||
&self.keybinds,
|
||||
vec![
|
||||
menu::Item::Button("hi 3", None, Action::Hi),
|
||||
menu::Item::Button("hi 3 #2", None, Action::Hi),
|
||||
],
|
||||
),
|
||||
),
|
||||
Tree::with_children(
|
||||
menu::root("hi 3"),
|
||||
menu::items(
|
||||
&self.keybinds,
|
||||
vec![
|
||||
menu::Item::Button("hi 3", None, Action::Hi),
|
||||
menu::Item::Button("hi 3 #2", None, Action::Hi),
|
||||
menu::Item::Button("hi 3 #3", None, Action::Hi),
|
||||
],
|
||||
),
|
||||
),
|
||||
Tree::with_children(
|
||||
menu::root("hi 4"),
|
||||
menu::items(
|
||||
&self.keybinds,
|
||||
(
|
||||
"hi 1".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 12".into(), None, Action::Hi),
|
||||
menu::Item::Button("hi 13".into(), None, Action::Hi2),
|
||||
],
|
||||
),
|
||||
(
|
||||
"hi 2".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 21".into(), None, Action::Hi),
|
||||
menu::Item::Button("hi 22".into(), None, Action::Hi2),
|
||||
],
|
||||
),
|
||||
(
|
||||
"hi 3".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 33".into(), None, Action::Hi),
|
||||
menu::Item::Button("hi 333".into(), None, Action::Hi2),
|
||||
menu::Item::Button("hi 3333".into(), None, Action::Hi3),
|
||||
],
|
||||
),
|
||||
(
|
||||
"hiiiiiiiiiiiiiiiiiii 4".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 4".into(), None, Action::Hi),
|
||||
menu::Item::Button("hi 44".into(), None, Action::Hi2),
|
||||
menu::Item::Button("hi 444".into(), None, Action::Hi3),
|
||||
menu::Item::Folder(
|
||||
"nest 4".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 41".into(), None, Action::Hi),
|
||||
menu::Item::Button("hi 442".into(), None, Action::Hi2),
|
||||
menu::Item::Button("hi 4443".into(), None, Action::Hi3),
|
||||
menu::Item::Folder(
|
||||
"hi 41 extra root",
|
||||
vec![menu::Item::Button("hi 3", None, Action::Hi)],
|
||||
"nest 2 4".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 443".into(), None, Action::Hi2),
|
||||
menu::Item::Button("hi 4444".into(), None, Action::Hi),
|
||||
],
|
||||
),
|
||||
menu::Item::Button("hi 42", None, Action::Hi),
|
||||
menu::Item::Button("hi 43", None, Action::Hi),
|
||||
menu::Item::Button("hi 44", None, Action::Hi),
|
||||
menu::Item::Button("hi 45", None, Action::Hi),
|
||||
menu::Item::Button("hi 46", None, Action::Hi),
|
||||
],
|
||||
),
|
||||
),
|
||||
])
|
||||
.into(),
|
||||
]
|
||||
}
|
||||
#[cfg(feature = "wayland")]
|
||||
{
|
||||
vec![cosmic::widget::responsive_menu_bar().into_element(
|
||||
self.core(),
|
||||
&self.keybinds,
|
||||
MENU_ID.clone(),
|
||||
Message::Surface,
|
||||
vec![
|
||||
(
|
||||
"hi 1".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 1".into(), None, Action::Hi),
|
||||
menu::Item::Button("hi 1 2".into(), None, Action::Hi),
|
||||
],
|
||||
),
|
||||
(
|
||||
"hi 2".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 2", None, Action::Hi),
|
||||
menu::Item::Button("hi 22", None, Action::Hi),
|
||||
],
|
||||
),
|
||||
(
|
||||
"hi 3".into(),
|
||||
vec![
|
||||
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", 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", 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", None, Action::Hi),
|
||||
menu::Item::Button("hi 44", None, Action::Hi),
|
||||
menu::Item::Button("hi 444", None, Action::Hi),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
)]
|
||||
}
|
||||
],
|
||||
),
|
||||
],
|
||||
)]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ pub fn simple_subsurface<Message: 'static, V>(
|
|||
/// Used to create a popup message from within a widget.
|
||||
#[cfg(all(feature = "wayland", feature = "winit"))]
|
||||
#[must_use]
|
||||
pub fn simple_popup<Message: 'static, V>(
|
||||
pub fn simple_popup<Message: 'static>(
|
||||
settings: impl Fn() -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings
|
||||
+ Send
|
||||
+ Sync
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ pub enum MenuBarStyle {
|
|||
#[default]
|
||||
Default,
|
||||
/// A [`Theme`] that uses a `Custom` palette.
|
||||
Custom(Arc<dyn StyleSheet<Style = Theme>>),
|
||||
Custom(Arc<dyn StyleSheet<Style = Theme> + Send + Sync>),
|
||||
}
|
||||
|
||||
impl From<fn(&Theme) -> Appearance> for MenuBarStyle {
|
||||
|
|
|
|||
|
|
@ -536,15 +536,7 @@ pub fn update<
|
|||
let on_close = surface::action::destroy_popup(id);
|
||||
let on_surface_action_clone = on_surface_action.clone();
|
||||
let translation = layout.virtual_offset();
|
||||
let get_popup_action = surface::action::simple_popup::<
|
||||
AppMessage,
|
||||
Box<
|
||||
dyn Fn() -> Element<'static, crate::Action<AppMessage>>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>,
|
||||
>(
|
||||
let get_popup_action = surface::action::simple_popup::<AppMessage>(
|
||||
move || {
|
||||
SctkPopupSettings {
|
||||
parent,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use crate::{
|
|||
widget::{
|
||||
RcWrapper,
|
||||
dropdown::menu::{self, State},
|
||||
menu::menu_inner::init_root_menu,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -57,6 +58,7 @@ pub(crate) struct MenuBarStateInner {
|
|||
pub(crate) menu_states: Vec<Vec<MenuState>>,
|
||||
}
|
||||
impl MenuBarStateInner {
|
||||
/// get the list of indices hovered for the menu
|
||||
pub(super) fn get_trimmed_indices(&self, index: usize) -> impl Iterator<Item = usize> + '_ {
|
||||
self.menu_states
|
||||
.get(index)
|
||||
|
|
@ -188,7 +190,7 @@ pub struct MenuBar<Message> {
|
|||
menu_roots: Vec<MenuTree<Message>>,
|
||||
style: <crate::Theme as StyleSheet>::Style,
|
||||
window_id: window::Id,
|
||||
#[cfg(feature = "wayland")]
|
||||
#[cfg(all(feature = "wayland", feature = "winit"))]
|
||||
positioner: iced_runtime::platform_specific::wayland::popup::SctkPositioner,
|
||||
pub(crate) on_surface_action: Option<Box<dyn Fn(crate::surface::Action) -> Message>>,
|
||||
}
|
||||
|
|
@ -228,7 +230,7 @@ where
|
|||
menu_roots,
|
||||
style: <crate::Theme as StyleSheet>::Style::default(),
|
||||
window_id: window::Id::NONE,
|
||||
#[cfg(feature = "wayland")]
|
||||
#[cfg(all(feature = "wayland", feature = "winit"))]
|
||||
positioner: iced_runtime::platform_specific::wayland::popup::SctkPositioner::default(),
|
||||
on_surface_action: None,
|
||||
}
|
||||
|
|
@ -322,7 +324,8 @@ where
|
|||
self
|
||||
}
|
||||
|
||||
#[cfg(feature = "wayland")]
|
||||
#[cfg(all(feature = "wayland", feature = "winit"))]
|
||||
|
||||
pub fn with_positioner(
|
||||
mut self,
|
||||
positioner: iced_runtime::platform_specific::wayland::popup::SctkPositioner,
|
||||
|
|
@ -405,6 +408,7 @@ where
|
|||
)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn on_event(
|
||||
&mut self,
|
||||
tree: &mut Tree,
|
||||
|
|
@ -441,28 +445,170 @@ where
|
|||
if reset {
|
||||
if let Some(popup_id) = state.popup_id.get(&self.window_id).copied() {
|
||||
dbg!("reset destroy");
|
||||
// TODO emit message
|
||||
if let Some(handler) = self.on_surface_action.as_ref() {
|
||||
shell.publish((handler)(crate::surface::Action::DestroyPopup(popup_id)));
|
||||
state.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let tree = &mut state.tree;
|
||||
// let tree: &mut _ = &mut state.tree;
|
||||
|
||||
match event {
|
||||
Mouse(ButtonReleased(Left)) | Touch(FingerLifted { .. } | FingerLost { .. }) => {
|
||||
match event {
|
||||
Mouse(ButtonReleased(Left)) | Touch(FingerLifted { .. } | FingerLost { .. }) => {
|
||||
my_state.inner.with_data_mut(|state| {
|
||||
if state.menu_states.is_empty() && view_cursor.is_over(layout.bounds()) {
|
||||
state.view_cursor = view_cursor;
|
||||
state.open = true;
|
||||
// #[cfg(feature = "wayland")]
|
||||
// TODO emit Message to open menu
|
||||
}
|
||||
});
|
||||
#[cfg(all(feature = "wayland", feature = "winit"))]
|
||||
|
||||
dbg!(
|
||||
self.window_id != window::Id::NONE,
|
||||
self.on_surface_action.is_some()
|
||||
);
|
||||
// TODO emit Message to open menu
|
||||
if self.window_id != window::Id::NONE && self.on_surface_action.is_some() {
|
||||
use crate::surface::action::destroy_popup;
|
||||
use iced_runtime::platform_specific::wayland::popup::{
|
||||
SctkPopupSettings, SctkPositioner,
|
||||
};
|
||||
|
||||
let surface_action = self.on_surface_action.as_ref().unwrap();
|
||||
let old_active_root = my_state.inner.with_data(|state| {
|
||||
state
|
||||
.active_root
|
||||
.get(0)
|
||||
.filter(|r| r.len() == 1)
|
||||
.map(|r| r[0])
|
||||
});
|
||||
|
||||
// if position is not on menu bar button skip.
|
||||
let position = view_cursor.position();
|
||||
let hovered_root = layout
|
||||
.children()
|
||||
.position(|lo| view_cursor.is_over(lo.bounds()));
|
||||
dbg!(old_active_root);
|
||||
// TODO why exit here?
|
||||
// if hovered_root
|
||||
// .zip(old_active_root.as_ref())
|
||||
// .is_none_or(|r| r.0 != *r.1)
|
||||
// {
|
||||
// panic!();
|
||||
// }
|
||||
|
||||
let (id, root_list) = my_state.inner.with_data_mut(|state| {
|
||||
if let Some(id) = state.popup_id.get(&self.window_id).copied() {
|
||||
// close existing popups
|
||||
state.menu_states.clear();
|
||||
state.active_root.clear();
|
||||
shell.publish(surface_action(destroy_popup(id)));
|
||||
state.view_cursor = view_cursor;
|
||||
(id, layout.children().map(|lo| lo.bounds()).collect())
|
||||
} else {
|
||||
(
|
||||
window::Id::unique(),
|
||||
layout.children().map(|lo| lo.bounds()).collect(),
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
let mut popup_menu: Menu<'static, _> = Menu {
|
||||
tree: my_state.clone(),
|
||||
menu_roots: std::borrow::Cow::Owned(self.menu_roots.clone()),
|
||||
bounds_expand: self.bounds_expand,
|
||||
menu_overlays_parent: false,
|
||||
close_condition: self.close_condition,
|
||||
item_width: self.item_width,
|
||||
item_height: self.item_height,
|
||||
bar_bounds: layout.bounds(),
|
||||
main_offset: self.main_offset,
|
||||
cross_offset: self.cross_offset,
|
||||
root_bounds_list: root_list,
|
||||
path_highlight: self.path_highlight,
|
||||
style: std::borrow::Cow::Owned(self.style.clone()),
|
||||
position: Point::new(0., 0.),
|
||||
is_overlay: false,
|
||||
window_id: id,
|
||||
depth: 0,
|
||||
};
|
||||
|
||||
init_root_menu(
|
||||
&mut popup_menu,
|
||||
renderer,
|
||||
shell,
|
||||
view_cursor.position().unwrap(),
|
||||
viewport.size(),
|
||||
Vector::new(0., 0.),
|
||||
layout.bounds(),
|
||||
self.main_offset as f32,
|
||||
);
|
||||
let anchor_rect = my_state.inner.with_data(|state| {
|
||||
state.menu_states[0]
|
||||
.iter()
|
||||
.find(|s| s.index.is_none())
|
||||
.map(|s| s.menu_bounds.parent_bounds)
|
||||
.map_or_else(
|
||||
|| {
|
||||
let bounds = layout.bounds();
|
||||
Rectangle {
|
||||
x: bounds.x as i32,
|
||||
y: bounds.y as i32,
|
||||
width: bounds.width as i32,
|
||||
height: bounds.height as i32,
|
||||
}
|
||||
},
|
||||
|r| Rectangle {
|
||||
x: r.x as i32,
|
||||
y: r.y as i32,
|
||||
width: r.width as i32,
|
||||
height: r.height as i32,
|
||||
},
|
||||
)
|
||||
});
|
||||
|
||||
let menu_node =
|
||||
popup_menu.layout(renderer, Limits::NONE.min_width(1.).min_height(1.));
|
||||
let popup_size = menu_node.size();
|
||||
let positioner = SctkPositioner {
|
||||
size: Some((popup_size.width.ceil() as u32 + 2, popup_size.height.ceil() as u32 + 2)),
|
||||
anchor_rect,
|
||||
anchor: cctk::wayland_protocols::xdg::shell::client::xdg_positioner::Anchor::BottomLeft,
|
||||
gravity:cctk::wayland_protocols::xdg::shell::client::xdg_positioner::Gravity::BottomRight,
|
||||
reactive: true,
|
||||
..Default::default()
|
||||
};
|
||||
let parent = self.window_id;
|
||||
shell.publish((surface_action)(crate::surface::action::simple_popup(
|
||||
move || SctkPopupSettings {
|
||||
parent,
|
||||
id,
|
||||
positioner: positioner.clone(),
|
||||
parent_size: None,
|
||||
grab: true,
|
||||
close_with_children: true,
|
||||
input_zone: None,
|
||||
},
|
||||
Some(move || {
|
||||
Element::from(
|
||||
crate::widget::container(popup_menu.clone()).center(Length::Fill),
|
||||
)
|
||||
.map(crate::action::app)
|
||||
}),
|
||||
)));
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
});
|
||||
// Window(Focused) => {
|
||||
// if let Some(popup_id) = state.popup_id.get(&self.window_id).copied() {
|
||||
// dbg!("window focused");
|
||||
// shell.publish(Message::from(SurfaceMessage::DestroyPopup(popup_id)));
|
||||
// }
|
||||
// state.reset();
|
||||
// }
|
||||
_ => (),
|
||||
}
|
||||
|
||||
root_status
|
||||
}
|
||||
|
|
@ -533,8 +679,8 @@ where
|
|||
_renderer: &Renderer,
|
||||
translation: Vector,
|
||||
) -> Option<overlay::Element<'b, Message, crate::Theme, Renderer>> {
|
||||
//#[cfg(feature = "wayland")]
|
||||
//return None;
|
||||
#[cfg(all(feature = "wayland", feature = "winit"))]
|
||||
return None;
|
||||
|
||||
let state = tree.state.downcast_ref::<MenuBarState>();
|
||||
if state
|
||||
|
|
|
|||
|
|
@ -232,11 +232,11 @@ pub(super) struct MenuSlice {
|
|||
|
||||
#[derive(Clone)]
|
||||
/// Menu bounds in overlay space
|
||||
struct MenuBounds {
|
||||
pub struct MenuBounds {
|
||||
child_positions: Vec<f32>,
|
||||
child_sizes: Vec<Size>,
|
||||
children_bounds: Rectangle,
|
||||
parent_bounds: Rectangle,
|
||||
pub parent_bounds: Rectangle,
|
||||
check_bounds: Rectangle,
|
||||
offset_bounds: Rectangle,
|
||||
}
|
||||
|
|
@ -299,7 +299,7 @@ pub(crate) struct MenuState {
|
|||
/// The index of the active menu item
|
||||
pub(super) index: Option<usize>,
|
||||
scroll_offset: f32,
|
||||
menu_bounds: MenuBounds,
|
||||
pub menu_bounds: MenuBounds,
|
||||
}
|
||||
impl MenuState {
|
||||
pub(super) fn layout<Message>(
|
||||
|
|
@ -444,6 +444,7 @@ impl MenuState {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct Menu<'b, Message: std::clone::Clone> {
|
||||
pub(crate) tree: MenuBarState,
|
||||
// Flattened menu tree
|
||||
|
|
@ -471,7 +472,7 @@ impl<'b, Message: Clone + 'static> Menu<'b, Message> {
|
|||
overlay::Element::new(Box::new(self))
|
||||
}
|
||||
|
||||
fn layout(&mut self, renderer: &crate::Renderer, limits: Limits) -> Node {
|
||||
pub(crate) fn layout(&self, renderer: &crate::Renderer, limits: Limits) -> Node {
|
||||
// layout children;
|
||||
let position = self.position;
|
||||
let mut intrinsic_size = Size::ZERO;
|
||||
|
|
@ -889,6 +890,207 @@ impl<Message: Clone + 'static> overlay::Overlay<Message, crate::Theme, crate::Re
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, Message: std::clone::Clone + 'static> Widget<Message, crate::Theme, crate::Renderer>
|
||||
for Menu<'a, Message>
|
||||
{
|
||||
fn size(&self) -> Size<Length> {
|
||||
Size {
|
||||
width: Length::Shrink,
|
||||
height: Length::Shrink,
|
||||
}
|
||||
}
|
||||
|
||||
fn layout(
|
||||
&self,
|
||||
_tree: &mut Tree,
|
||||
renderer: &crate::Renderer,
|
||||
limits: &iced_core::layout::Limits,
|
||||
) -> iced_core::layout::Node {
|
||||
// dbg!(self.window_id, limits);
|
||||
Menu::layout(self, renderer, *limits)
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&self,
|
||||
_tree: &Tree,
|
||||
renderer: &mut crate::Renderer,
|
||||
theme: &crate::Theme,
|
||||
style: &renderer::Style,
|
||||
layout: Layout<'_>,
|
||||
cursor: mouse::Cursor,
|
||||
_viewport: &Rectangle,
|
||||
) {
|
||||
Menu::draw(self, renderer, theme, style, layout, cursor);
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
_tree: &mut Tree,
|
||||
event: iced::Event,
|
||||
layout: Layout<'_>,
|
||||
cursor: mouse::Cursor,
|
||||
renderer: &crate::Renderer,
|
||||
clipboard: &mut dyn Clipboard,
|
||||
shell: &mut Shell<'_, Message>,
|
||||
_viewport: &Rectangle,
|
||||
) -> event::Status {
|
||||
let (new_root, status) = self.on_event(event, layout, cursor, renderer, clipboard, shell);
|
||||
// #[cfg(feature = "wayland")]
|
||||
// if let Some((new_root, new_ms)) = new_root {
|
||||
// use iced_runtime::platform_specific::wayland::popup::{
|
||||
// SctkPopupSettings, SctkPositioner,
|
||||
// };
|
||||
// let mut guard = self.tree.inner.lock().unwrap();
|
||||
// let popup_id = *guard
|
||||
// .popup_id
|
||||
// .entry(self.window_id)
|
||||
// .or_insert_with(window::Id::unique);
|
||||
// let active_roots = &guard.active_root[&self.window_id];
|
||||
// // dbg!(active_roots);
|
||||
// let root_bounds_list = active_roots
|
||||
// .into_iter()
|
||||
// .fold(layout, |l, active_root| {
|
||||
// // dbg!(active_root);
|
||||
// l.children().nth(*active_root).unwrap()
|
||||
// })
|
||||
// .children()
|
||||
// .map(|c| c.bounds())
|
||||
// .collect();
|
||||
// drop(guard);
|
||||
|
||||
// // dbg!(&root_bounds_list);
|
||||
// // dbg!(self.menu_roots.clone().len());
|
||||
// // dbg!(self
|
||||
// // .menu_roots
|
||||
// // .clone()
|
||||
// // .iter()
|
||||
// // .map(|r| r.index)
|
||||
// // .collect::<Vec<_>>());
|
||||
// let mut popup_menu = Menu {
|
||||
// tree: self.tree.clone(),
|
||||
// menu_roots: Cow::Owned(Cow::into_owned(self.menu_roots.clone())),
|
||||
// bounds_expand: self.bounds_expand,
|
||||
// menu_overlays_parent: false,
|
||||
// close_condition: self.close_condition,
|
||||
// item_width: self.item_width,
|
||||
// item_height: self.item_height,
|
||||
// bar_bounds: layout.bounds(),
|
||||
// main_offset: self.main_offset,
|
||||
// cross_offset: self.cross_offset,
|
||||
// root_bounds_list,
|
||||
// path_highlight: self.path_highlight,
|
||||
// style: Cow::Owned(Cow::into_owned(self.style.clone())),
|
||||
// position: Point::new(0., 0.),
|
||||
// is_overlay: false,
|
||||
// window_id: popup_id,
|
||||
// depth: self.depth + 1,
|
||||
// };
|
||||
// let mut guard = self.tree.inner.lock().unwrap();
|
||||
// // dbg!(guard.menu_states.keys());
|
||||
// let Some(parent_root) = guard.active_root.get(&self.window_id) else {
|
||||
// // TODO log warning
|
||||
// return status;
|
||||
// };
|
||||
// let mut roots = parent_root.clone();
|
||||
// roots.push(new_root);
|
||||
// // dbg!(&roots);
|
||||
// guard.active_root.insert(popup_id, roots);
|
||||
// _ = guard.menu_states.remove(&popup_id);
|
||||
// drop(guard);
|
||||
// init_root_popup_menu(
|
||||
// &mut popup_menu,
|
||||
// renderer,
|
||||
// shell,
|
||||
// cursor.position().unwrap(),
|
||||
// layout.bounds().size(),
|
||||
// Vector::new(0., 0.),
|
||||
// layout.bounds(),
|
||||
// self.main_offset as f32,
|
||||
// );
|
||||
// let mut guard = self.tree.inner.lock().unwrap();
|
||||
|
||||
// guard
|
||||
// .menu_states
|
||||
// .get_mut(&self.window_id)
|
||||
// .unwrap()
|
||||
// .push(new_ms);
|
||||
|
||||
// let anchor_rect = guard.menu_states[&self.window_id]
|
||||
// .iter()
|
||||
// .find(|s| s.index.is_none())
|
||||
// .map(|s| s.menu_bounds.parent_bounds)
|
||||
// .map_or_else(
|
||||
// || {
|
||||
// let bounds = layout.bounds();
|
||||
// Rectangle {
|
||||
// x: bounds.x as i32,
|
||||
// y: bounds.y as i32,
|
||||
// width: bounds.width as i32,
|
||||
// height: bounds.height as i32,
|
||||
// }
|
||||
// },
|
||||
// |r| Rectangle {
|
||||
// x: r.x as i32,
|
||||
// y: r.y as i32,
|
||||
// width: r.width as i32,
|
||||
// height: r.height as i32,
|
||||
// },
|
||||
// );
|
||||
// // dbg!(&anchor_rect);
|
||||
|
||||
// drop(guard);
|
||||
// let menu_node = Widget::layout(
|
||||
// &popup_menu,
|
||||
// &mut Tree::empty(),
|
||||
// renderer,
|
||||
// &Limits::NONE.min_width(1.).min_height(1.),
|
||||
// );
|
||||
// // dbg!(menu_node.size());
|
||||
|
||||
// // dbg!(&menu_node);
|
||||
|
||||
// let popup_size = menu_node.size();
|
||||
// let positioner = SctkPositioner {
|
||||
// size: Some((popup_size.width.ceil() as u32 + 2, popup_size.height.ceil() as u32 + 2)),
|
||||
// anchor_rect,
|
||||
// anchor: cctk::wayland_protocols::xdg::shell::client::xdg_positioner::Anchor::TopRight,
|
||||
// gravity:cctk::wayland_protocols::xdg::shell::client::xdg_positioner::Gravity::BottomRight,
|
||||
// reactive: true,
|
||||
// ..Default::default()
|
||||
// };
|
||||
// let parent = self.window_id;
|
||||
// // dbg!(&positioner);
|
||||
// shell.publish(crate::app::message::simple_popup(
|
||||
// move || SctkPopupSettings {
|
||||
// parent,
|
||||
// id: popup_id,
|
||||
// positioner: positioner.clone(),
|
||||
// parent_size: None,
|
||||
// grab: true,
|
||||
// close_with_children: true,
|
||||
// },
|
||||
// Some(move || {
|
||||
// crate::Element::from(
|
||||
// crate::widget::container(popup_menu.clone()).center(Length::Fill),
|
||||
// )
|
||||
// .map(crate::app::Message::App)
|
||||
// }),
|
||||
// ));
|
||||
// }
|
||||
status
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message> From<Menu<'a, Message>>
|
||||
for iced::Element<'a, Message, crate::Theme, crate::Renderer>
|
||||
where
|
||||
Message: std::clone::Clone + 'static,
|
||||
{
|
||||
fn from(value: Menu<'a, Message>) -> Self {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
fn pad_rectangle(rect: Rectangle, padding: Padding) -> Rectangle {
|
||||
Rectangle {
|
||||
x: rect.x - padding.left,
|
||||
|
|
@ -1194,34 +1396,48 @@ fn process_menu_events<'b, Message: std::clone::Clone>(
|
|||
Cow::Owned(o) => o.as_mut_slice(),
|
||||
};
|
||||
my_state.inner.with_data_mut(|state| {
|
||||
dbg!(&state.active_root);
|
||||
let Some(active_root) = state.active_root.get(menu.depth).cloned() else {
|
||||
return Status::Ignored;
|
||||
};
|
||||
dbg!("got the active root");
|
||||
|
||||
let indices = state.get_trimmed_indices(menu.depth);
|
||||
|
||||
let indices = if is_overlay {
|
||||
indices.collect::<Vec<_>>()
|
||||
} else {
|
||||
indices.take(1).collect::<Vec<_>>()
|
||||
};
|
||||
let indices = indices.collect::<Vec<_>>();
|
||||
// if is_overlay {
|
||||
// indices.collect::<Vec<_>>()
|
||||
// } else {
|
||||
// indices.take(1).collect::<Vec<_>>()
|
||||
// };
|
||||
|
||||
if indices.is_empty() {
|
||||
return Status::Ignored;
|
||||
}
|
||||
dbg!(&active_root, &indices);
|
||||
|
||||
// get active item
|
||||
// let mt = indices.iter().fold(root | mt, &i | &mut mt.children[i]);
|
||||
let (tree, mt) = active_root.iter().take(menu.depth).fold(
|
||||
let (tree, mt) = indices.iter().take(indices.len()).fold(
|
||||
(
|
||||
&mut state.tree.children[active_root[0]].children,
|
||||
&mut menu_roots[active_root[0]],
|
||||
),
|
||||
|(tree, mt), next_active_root| (tree, &mut mt.children[*next_active_root]),
|
||||
);
|
||||
dbg!(mt.children.len(), mt.index,);
|
||||
// let Some(i) = state.menu_states[menu.depth].iter().position(|ms| {
|
||||
// ms.menu_bounds
|
||||
// .check_bounds
|
||||
// .contains(view_cursor.position().unwrap_or(Point { x: -1., y: -1. }))
|
||||
// }) else {
|
||||
// return Status::Ignored;
|
||||
// };
|
||||
// let mt = &mut mt.children[indices[indices.len() - 1]];
|
||||
|
||||
// widget tree
|
||||
let tree = &mut tree[mt.index];
|
||||
dbg!(tree.children.len());
|
||||
|
||||
// get layout
|
||||
let last_ms = &state.menu_states[menu.depth][indices.len() - 1];
|
||||
|
|
@ -1234,7 +1450,9 @@ fn process_menu_events<'b, Message: std::clone::Clone>(
|
|||
);
|
||||
let child_layout = Layout::new(&child_node);
|
||||
|
||||
dbg!("item on event handler...");
|
||||
// process only the last widget
|
||||
dbg!(&event);
|
||||
mt.item.on_event(
|
||||
tree,
|
||||
event,
|
||||
|
|
@ -1369,13 +1587,7 @@ where
|
|||
- (last_children_bounds.y + last_menu_state.scroll_offset))
|
||||
.clamp(0.0, last_children_bounds.height - 0.001);
|
||||
// dbg!(height_diff);
|
||||
// let (tree, active_menu_root) = active_root.iter().skip(1).fold(
|
||||
// (
|
||||
// &mut state.tree.children[active_root[0]].children,
|
||||
// &menu.menu_roots[active_root[0]],
|
||||
// ),
|
||||
// |(tree, mr), next_active_root| (tree, &mr.children[*next_active_root]),
|
||||
// );
|
||||
|
||||
let (active_tree, roots) = active_root.iter().take(menu.depth).fold(
|
||||
(
|
||||
&mut state.tree.children[active_root[0]].children,
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ where
|
|||
pub fn menu_items<
|
||||
A: MenuAction<Message = Message>,
|
||||
L: Into<Cow<'static, str>> + 'static,
|
||||
Message: 'static + std::clone::Clone,
|
||||
Message: 'static + std::clone::Clone + std::fmt::Debug,
|
||||
>(
|
||||
key_binds: &HashMap<KeyBind, A>,
|
||||
children: Vec<MenuItem<A, L>>,
|
||||
|
|
@ -238,9 +238,10 @@ pub fn menu_items<
|
|||
|
||||
match item {
|
||||
MenuItem::Button(label, icon, action) => {
|
||||
let l: Cow<'static, str> = label.into();
|
||||
let key = find_key(&action, key_binds);
|
||||
let mut items = vec![
|
||||
widget::text(label).into(),
|
||||
widget::text(l.clone()).into(),
|
||||
widget::horizontal_space().into(),
|
||||
widget::text(key).into(),
|
||||
];
|
||||
|
|
@ -250,15 +251,18 @@ pub fn menu_items<
|
|||
items.insert(1, widget::Space::with_width(spacing.space_xxs).into());
|
||||
}
|
||||
|
||||
let menu_button = menu_button(items).on_press(action.message());
|
||||
// dbg!("button with action...", action.message());
|
||||
let menu_button = menu_button(items).on_press(action.message()).description(l);
|
||||
|
||||
trees.push(MenuTree::<Message>::from(Element::from(menu_button)));
|
||||
}
|
||||
MenuItem::ButtonDisabled(label, icon, action) => {
|
||||
let l: Cow<'static, str> = label.into();
|
||||
|
||||
let key = find_key(&action, key_binds);
|
||||
|
||||
let mut items = vec![
|
||||
widget::text(label).into(),
|
||||
widget::text(l.clone()).into(),
|
||||
widget::horizontal_space().into(),
|
||||
widget::text(key).into(),
|
||||
];
|
||||
|
|
@ -268,7 +272,7 @@ pub fn menu_items<
|
|||
items.insert(1, widget::Space::with_width(spacing.space_xxs).into());
|
||||
}
|
||||
|
||||
let menu_button = menu_button(items);
|
||||
let menu_button = menu_button(items).description((l.clone()));
|
||||
|
||||
trees.push(MenuTree::<Message>::from(Element::from(menu_button)));
|
||||
}
|
||||
|
|
@ -305,16 +309,19 @@ pub fn menu_items<
|
|||
)));
|
||||
}
|
||||
MenuItem::Folder(label, children) => {
|
||||
let l: Cow<'static, str> = label.into();
|
||||
|
||||
trees.push(MenuTree::<Message>::with_children(
|
||||
RcElementWrapper::new(crate::Element::from(
|
||||
menu_button::<'static, _>(vec![
|
||||
widget::text(label).into(),
|
||||
widget::text(l.clone()).into(),
|
||||
widget::horizontal_space().into(),
|
||||
widget::icon::from_name("pan-end-symbolic")
|
||||
.size(16)
|
||||
.icon()
|
||||
.into(),
|
||||
])
|
||||
.description(l.clone())
|
||||
.class(
|
||||
// Menu folders have no on_press so they take on the disabled style by default
|
||||
if children.is_empty() {
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ impl ResponsiveMenuBar {
|
|||
.item_width(self.item_width)
|
||||
.item_height(self.item_height)
|
||||
.spacing(self.spacing)
|
||||
.on_surface_action(action_message.clone())
|
||||
.window_id_maybe(core.main_window_id()),
|
||||
crate::widget::Id::new(format!("menu_bar_expanded_{id}")),
|
||||
),
|
||||
|
|
@ -131,6 +132,7 @@ impl ResponsiveMenuBar {
|
|||
.item_height(self.item_height)
|
||||
.item_width(self.collapsed_item_width)
|
||||
.spacing(self.spacing)
|
||||
.on_surface_action(action_message.clone())
|
||||
.window_id_maybe(core.main_window_id()),
|
||||
crate::widget::Id::new(format!("menu_bar_collapsed_{id}")),
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue