popup refactor
This commit is contained in:
parent
51c391a656
commit
3fd6c4f6bc
6 changed files with 180 additions and 485 deletions
|
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
default = ["wayland"]
|
||||
wayland = ["libcosmic/wayland"]
|
||||
|
||||
[dependencies]
|
||||
|
|
|
|||
|
|
@ -257,16 +257,16 @@ impl cosmic::Application for App {
|
|||
menu::Item::Button("hi 21", None, Action::Hi),
|
||||
menu::Item::Button("hi 22", None, Action::Hi2),
|
||||
menu::Item::Folder(
|
||||
"nest 3 2".into(),
|
||||
"nest 3 2 >".into(),
|
||||
vec![
|
||||
menu::Item::Button("31", None, Action::Hi),
|
||||
menu::Item::Button("342", None, Action::Hi2),
|
||||
menu::Item::Button("3443", None, Action::Hi3),
|
||||
menu::Item::Button("21", None, Action::Hi),
|
||||
menu::Item::Button("242", None, Action::Hi2),
|
||||
menu::Item::Button("2443", None, Action::Hi3),
|
||||
menu::Item::Folder(
|
||||
"nest 4 2".into(),
|
||||
"nest 4 2 >".into(),
|
||||
vec![
|
||||
menu::Item::Button("343", None, Action::Hi2),
|
||||
menu::Item::Button("3444", None, Action::Hi),
|
||||
menu::Item::Button("243", None, Action::Hi2),
|
||||
menu::Item::Button("2444", None, Action::Hi),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
@ -276,9 +276,12 @@ impl cosmic::Application for App {
|
|||
(
|
||||
"hi 3".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 33", None, Action::Hi),
|
||||
menu::Item::Button("hi 333", None, Action::Hi2),
|
||||
menu::Item::Button("hi 31", None, Action::Hi),
|
||||
menu::Item::Button("hi 332", None, Action::Hi2),
|
||||
menu::Item::Button("hi 3333", None, Action::Hi3),
|
||||
menu::Item::Button("hi 33334", None, Action::Hi3),
|
||||
menu::Item::Button("hi 333335", None, Action::Hi3),
|
||||
menu::Item::Button("hi 3333336", None, Action::Hi3),
|
||||
],
|
||||
),
|
||||
(
|
||||
|
|
@ -288,13 +291,12 @@ impl cosmic::Application for App {
|
|||
menu::Item::Button("hi 44", None, Action::Hi2),
|
||||
menu::Item::Button("hi 444", None, Action::Hi3),
|
||||
menu::Item::Folder(
|
||||
"nest 4".into(),
|
||||
"nest 4 >".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 41", None, Action::Hi),
|
||||
menu::Item::Button("hi 442", None, Action::Hi2),
|
||||
menu::Item::Button("hi 4443", None, Action::Hi3),
|
||||
menu::Item::Folder(
|
||||
"nest 2 4".into(),
|
||||
"nest 3 4 >".into(),
|
||||
vec![
|
||||
menu::Item::Button("hi 443", None, Action::Hi2),
|
||||
menu::Item::Button("hi 4444", None, Action::Hi),
|
||||
|
|
|
|||
|
|
@ -51,25 +51,23 @@ pub(crate) struct MenuBarStateInner {
|
|||
pub(crate) bar_pressed: bool,
|
||||
pub(crate) view_cursor: Cursor,
|
||||
pub(crate) open: bool,
|
||||
pub(crate) active_root: Vec<Vec<usize>>,
|
||||
pub(crate) active_root: Vec<usize>,
|
||||
pub(crate) horizontal_direction: Direction,
|
||||
pub(crate) vertical_direction: Direction,
|
||||
/// List of all menu states
|
||||
pub(crate) menu_states: Vec<Vec<MenuState>>,
|
||||
pub(crate) menu_states: 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)
|
||||
.into_iter()
|
||||
.flat_map(|v| v.iter())
|
||||
.iter()
|
||||
.skip(index)
|
||||
.take_while(|ms| ms.index.is_some())
|
||||
.map(|ms| ms.index.expect("No indices were found in the menu state."))
|
||||
}
|
||||
|
||||
pub(super) fn reset(&mut self) {
|
||||
dbg!("reset");
|
||||
self.open = false;
|
||||
self.active_root = Vec::new();
|
||||
self.menu_states.clear();
|
||||
|
|
@ -205,13 +203,7 @@ where
|
|||
pub fn new(menu_roots: Vec<MenuTree<Message>>) -> Self {
|
||||
let mut menu_roots = menu_roots;
|
||||
menu_roots.iter_mut().for_each(MenuTree::set_index);
|
||||
// println!("======================================================");
|
||||
// for menu_root in &menu_roots {
|
||||
// dbg!(menu_root.index);
|
||||
// for inner_root in &menu_root.children {
|
||||
// dbg!(inner_root.index);
|
||||
// }
|
||||
// }
|
||||
|
||||
Self {
|
||||
width: Length::Shrink,
|
||||
height: Length::Shrink,
|
||||
|
|
@ -326,7 +318,6 @@ where
|
|||
}
|
||||
|
||||
#[cfg(all(feature = "wayland", feature = "winit"))]
|
||||
|
||||
pub fn with_positioner(
|
||||
mut self,
|
||||
positioner: iced_runtime::platform_specific::wayland::popup::SctkPositioner,
|
||||
|
|
@ -335,11 +326,13 @@ where
|
|||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn window_id(mut self, id: window::Id) -> Self {
|
||||
self.window_id = id;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn window_id_maybe(mut self, id: Option<window::Id>) -> Self {
|
||||
if let Some(id) = id {
|
||||
self.window_id = id;
|
||||
|
|
@ -347,6 +340,7 @@ where
|
|||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn on_surface_action(
|
||||
mut self,
|
||||
handler: impl Fn(crate::surface::Action) -> Message + Send + Sync + 'static,
|
||||
|
|
@ -355,6 +349,8 @@ where
|
|||
self
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "wayland", feature = "winit", feature = "surface-message"))]
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn create_popup(
|
||||
&mut self,
|
||||
layout: Layout<'_>,
|
||||
|
|
@ -363,11 +359,7 @@ where
|
|||
shell: &mut Shell<'_, Message>,
|
||||
viewport: &Rectangle,
|
||||
my_state: &mut MenuBarState,
|
||||
) -> event::Status {
|
||||
let mut status = event::Status::Ignored;
|
||||
|
||||
#[cfg(all(feature = "wayland", feature = "winit", feature = "surface-message"))]
|
||||
// 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::{
|
||||
|
|
@ -375,22 +367,20 @@ where
|
|||
};
|
||||
|
||||
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])
|
||||
});
|
||||
let old_active_root = my_state
|
||||
.inner
|
||||
.with_data(|state| state.active_root.get(0).copied());
|
||||
|
||||
// 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()));
|
||||
|
||||
if old_active_root == hovered_root {
|
||||
return status;
|
||||
if old_active_root
|
||||
.zip(hovered_root)
|
||||
.is_some_and(|r| r.0 == r.1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
let (id, root_list) = my_state.inner.with_data_mut(|state| {
|
||||
if let Some(id) = state.popup_id.get(&self.window_id).copied() {
|
||||
|
|
@ -441,7 +431,8 @@ where
|
|||
);
|
||||
let anchor_rect = my_state.inner.with_data_mut(|state| {
|
||||
state.popup_id.insert(self.window_id, id);
|
||||
state.menu_states[0]
|
||||
state
|
||||
.menu_states
|
||||
.iter()
|
||||
.find(|s| s.index.is_none())
|
||||
.map(|s| s.menu_bounds.parent_bounds)
|
||||
|
|
@ -491,7 +482,6 @@ where
|
|||
}),
|
||||
)));
|
||||
}
|
||||
status
|
||||
}
|
||||
}
|
||||
impl<Message> Widget<Message, crate::Theme, Renderer> for MenuBar<Message>
|
||||
|
|
@ -588,8 +578,6 @@ where
|
|||
let open = my_state.inner.with_data_mut(|state| {
|
||||
if reset {
|
||||
if let Some(popup_id) = state.popup_id.get(&self.window_id).copied() {
|
||||
dbg!("reset destroy");
|
||||
|
||||
if let Some(handler) = self.on_surface_action.as_ref() {
|
||||
shell.publish((handler)(crate::surface::Action::DestroyPopup(popup_id)));
|
||||
state.reset();
|
||||
|
|
@ -607,17 +595,22 @@ where
|
|||
state.view_cursor = view_cursor;
|
||||
state.open = true;
|
||||
create_popup = true;
|
||||
} else if let Some(id) = state.popup_id.remove(&self.window_id) {
|
||||
} else if let Some(_id) = state.popup_id.remove(&self.window_id) {
|
||||
state.menu_states.clear();
|
||||
state.active_root.clear();
|
||||
let surface_action = self.on_surface_action.as_ref().unwrap();
|
||||
state.open = false;
|
||||
#[cfg(all(
|
||||
feature = "wayland",
|
||||
feature = "winit",
|
||||
feature = "surface-message"
|
||||
))]
|
||||
shell.publish(surface_action(crate::surface::action::destroy_popup(id)));
|
||||
{
|
||||
let surface_action = self.on_surface_action.as_ref().unwrap();
|
||||
|
||||
shell.publish(surface_action(crate::surface::action::destroy_popup(
|
||||
_id,
|
||||
)));
|
||||
}
|
||||
state.view_cursor = view_cursor;
|
||||
}
|
||||
create_popup
|
||||
|
|
@ -626,38 +619,15 @@ where
|
|||
if !create_popup {
|
||||
return event::Status::Ignored;
|
||||
}
|
||||
|
||||
return root_status.merge(self.create_popup(
|
||||
layout,
|
||||
view_cursor,
|
||||
renderer,
|
||||
shell,
|
||||
viewport,
|
||||
my_state,
|
||||
));
|
||||
#[cfg(all(feature = "wayland", feature = "winit", feature = "surface-message"))]
|
||||
self.create_popup(layout, view_cursor, renderer, shell, viewport, my_state);
|
||||
}
|
||||
Mouse(mouse::Event::CursorMoved { .. } | mouse::Event::CursorEntered)
|
||||
if open && view_cursor.is_over(layout.bounds()) =>
|
||||
{
|
||||
return root_status.merge(self.create_popup(
|
||||
layout,
|
||||
view_cursor,
|
||||
renderer,
|
||||
shell,
|
||||
viewport,
|
||||
my_state,
|
||||
));
|
||||
#[cfg(all(feature = "wayland", feature = "winit", feature = "surface-message"))]
|
||||
self.create_popup(layout, view_cursor, renderer, shell, viewport, my_state);
|
||||
}
|
||||
// Window(Focused) => {
|
||||
// my_state.inner.with_data_mut(|state| {
|
||||
// if let Some(popup_id) = state.popup_id.get(&self.window_id).copied() {
|
||||
// if let Some(handler) = self.on_surface_action.as_ref() {
|
||||
// shell.publish((handler)(destroy_popup(popup_id)));
|
||||
// state.reset();
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
_ => (),
|
||||
}
|
||||
|
||||
|
|
@ -686,11 +656,7 @@ where
|
|||
// draw path highlight
|
||||
if self.path_highlight.is_some() {
|
||||
let styling = theme.appearance(&self.style);
|
||||
if let Some(active) = state
|
||||
.active_root
|
||||
.get(0)
|
||||
.and_then(|active_root| active_root.get(0))
|
||||
{
|
||||
if let Some(active) = state.active_root.get(0) {
|
||||
let active_bounds = layout
|
||||
.children()
|
||||
.nth(*active)
|
||||
|
|
@ -734,16 +700,13 @@ where
|
|||
_renderer: &Renderer,
|
||||
translation: Vector,
|
||||
) -> Option<overlay::Element<'b, Message, crate::Theme, Renderer>> {
|
||||
#[cfg(all(feature = "wayland", feature = "winit"))]
|
||||
#[cfg(all(feature = "wayland", feature = "winit", feature = "surface-message"))]
|
||||
return None;
|
||||
|
||||
let state = tree.state.downcast_ref::<MenuBarState>();
|
||||
if state
|
||||
.inner
|
||||
.with_data(|state| !state.open || state.active_root.is_empty())
|
||||
{
|
||||
if state.inner.with_data(|state| !state.open) {
|
||||
return None;
|
||||
};
|
||||
}
|
||||
|
||||
Some(
|
||||
Menu {
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ pub(super) struct MenuSlice {
|
|||
pub(super) upper_bound_rel: f32,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
/// Menu bounds in overlay space
|
||||
pub struct MenuBounds {
|
||||
child_positions: Vec<f32>,
|
||||
|
|
@ -322,9 +322,6 @@ impl MenuState {
|
|||
// self.menu_bounds.child_positions.len()
|
||||
// );
|
||||
|
||||
// for mt in &menu_tree.children[start_index..=end_index] {
|
||||
// dbg!(mt.index);
|
||||
// }
|
||||
|
||||
// viewport space children bounds
|
||||
let children_bounds = self.menu_bounds.children_bounds + overlay_offset;
|
||||
|
|
@ -336,7 +333,6 @@ impl MenuState {
|
|||
.map(|(i, ((cp, size), mt))| {
|
||||
let mut position = *cp;
|
||||
let mut size = *size;
|
||||
// dbg!(position, size);
|
||||
|
||||
if position < lower_bound_rel && (position + size.height) > lower_bound_rel {
|
||||
size.height = position + size.height - lower_bound_rel;
|
||||
|
|
@ -345,13 +341,9 @@ impl MenuState {
|
|||
{
|
||||
size.height = upper_bound_rel - position;
|
||||
}
|
||||
// dbg!(size);
|
||||
|
||||
let limits = Limits::new(size, size);
|
||||
// dbg!(i, mt.index, tree.len());
|
||||
// for child in &mt.children {
|
||||
// dbg!(child.index);
|
||||
// }
|
||||
|
||||
|
||||
mt.item
|
||||
.layout(&mut tree[mt.index], renderer, &limits)
|
||||
|
|
@ -359,11 +351,8 @@ impl MenuState {
|
|||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// dbg!(children_bounds.size());
|
||||
let node = Node::with_children(children_bounds.size(), child_nodes)
|
||||
.move_to(children_bounds.position());
|
||||
// dbg!(&node);
|
||||
node
|
||||
Node::with_children(children_bounds.size(), child_nodes)
|
||||
.move_to(children_bounds.position())
|
||||
}
|
||||
|
||||
fn layout_single<Message>(
|
||||
|
|
@ -479,29 +468,30 @@ impl<'b, Message: Clone + 'static> Menu<'b, Message> {
|
|||
|
||||
let empty = Vec::new();
|
||||
self.tree.inner.with_data_mut(|data| {
|
||||
if data.active_root.len() < self.depth + 1 || data.menu_states.len() < self.depth + 1 {
|
||||
return Node::new(Size::ZERO);
|
||||
}
|
||||
let overlay_offset = Point::ORIGIN - position;
|
||||
let tree_children = &mut data.tree.children;
|
||||
let children = data
|
||||
.active_root
|
||||
.get(self.depth)
|
||||
.cloned()
|
||||
let children = (if self.is_overlay {0} else {self.depth}..=self.depth)
|
||||
.map(|active_root| {
|
||||
if active_root.is_empty() || self.menu_roots.is_empty() {
|
||||
if self.menu_roots.is_empty() {
|
||||
return (&empty, vec![]);
|
||||
}
|
||||
let (active_tree, roots) = active_root
|
||||
let (active_tree, roots) = data.active_root[..=active_root]
|
||||
.iter()
|
||||
.skip(if self.is_overlay { 0 } else { 1 })
|
||||
.skip(1)
|
||||
.fold(
|
||||
(
|
||||
&mut tree_children[active_root[0]].children,
|
||||
&self.menu_roots[active_root[0]].children,
|
||||
&mut tree_children[data.active_root[0]].children,
|
||||
&self.menu_roots[data.active_root[0]].children,
|
||||
),
|
||||
|(tree, mt), next_active_root| (tree, &mt[*next_active_root].children),
|
||||
|(tree, mt), next_active_root| {
|
||||
(tree, &mt[*next_active_root].children)
|
||||
},
|
||||
);
|
||||
|
||||
if let Some(ms) = data.menu_states.get(self.depth) {
|
||||
ms.iter()
|
||||
data.menu_states[if self.is_overlay {0} else {self.depth}..=self.depth].iter()
|
||||
.enumerate()
|
||||
.filter(|ms| self.is_overlay || ms.0 < 1)
|
||||
.fold((roots, Vec::new()), |(menu_root, mut nodes), (_i, ms)| {
|
||||
|
|
@ -528,23 +518,19 @@ impl<'b, Message: Clone + 'static> Menu<'b, Message> {
|
|||
nodes,
|
||||
)
|
||||
})
|
||||
} else {
|
||||
(&empty, vec![])
|
||||
}
|
||||
})
|
||||
.map(|(_, l)| l)
|
||||
.unwrap_or_default();
|
||||
// dbg!(intrinsic_size);
|
||||
|
||||
}).map(|(_, l)| l).next().unwrap_or_default();
|
||||
|
||||
// overlay space viewport rectangle
|
||||
let node = Node::with_children(
|
||||
Node::with_children(
|
||||
limits.resolve(Length::Shrink, Length::Shrink, intrinsic_size),
|
||||
children,
|
||||
)
|
||||
.translate(Point::ORIGIN - position);
|
||||
node
|
||||
.translate(Point::ORIGIN - position)
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn on_event(
|
||||
&mut self,
|
||||
event: event::Event,
|
||||
|
|
@ -618,10 +604,9 @@ impl<'b, Message: Clone + 'static> Menu<'b, Message> {
|
|||
Mouse(CursorMoved { position }) | Touch(FingerMoved { position, .. }) => {
|
||||
let view_cursor = Cursor::Available(position);
|
||||
let overlay_cursor = view_cursor.position().unwrap_or_default() - overlay_offset;
|
||||
if !(self.is_overlay || view_cursor.is_over(viewport)) {
|
||||
if !self.is_overlay && !view_cursor.is_over(viewport) {
|
||||
return (None, menu_status);
|
||||
}
|
||||
// dbg!(view_cursor, viewport, self.window_id);
|
||||
|
||||
let (new_root, status) = process_overlay_events(
|
||||
self,
|
||||
|
|
@ -631,10 +616,8 @@ impl<'b, Message: Clone + 'static> Menu<'b, Message> {
|
|||
view_cursor,
|
||||
overlay_cursor,
|
||||
self.cross_offset as f32,
|
||||
self.is_overlay,
|
||||
shell,
|
||||
);
|
||||
dbg!(new_root.as_ref().map(|new_root| new_root.0));
|
||||
|
||||
return (new_root, status.merge(menu_status));
|
||||
}
|
||||
|
|
@ -651,7 +634,7 @@ impl<'b, Message: Clone + 'static> Menu<'b, Message> {
|
|||
.distance(view_cursor.position().unwrap_or_default())
|
||||
< 2.0
|
||||
{
|
||||
let is_inside = state.menu_states[self.depth]
|
||||
let is_inside = state.menu_states[..=self.depth]
|
||||
.iter()
|
||||
.any(|ms| ms.menu_bounds.check_bounds.contains(overlay_cursor));
|
||||
let mut needs_reset = false;
|
||||
|
|
@ -665,7 +648,6 @@ impl<'b, Message: Clone + 'static> Menu<'b, Message> {
|
|||
needs_reset |= self.close_condition.click_outside && !is_inside;
|
||||
|
||||
if needs_reset {
|
||||
dbg!("reset");
|
||||
if let Some(handler) = self.on_surface_action.as_ref() {
|
||||
let mut root = self.window_id;
|
||||
let mut depth = self.depth;
|
||||
|
|
@ -679,7 +661,6 @@ impl<'b, Message: Clone + 'static> Menu<'b, Message> {
|
|||
root = parent.0.clone();
|
||||
depth = depth.saturating_sub(1);
|
||||
}
|
||||
dbg!(root);
|
||||
shell
|
||||
.publish((handler)(crate::surface::Action::DestroyPopup(root)));
|
||||
}
|
||||
|
|
@ -704,7 +685,7 @@ impl<'b, Message: Clone + 'static> Menu<'b, Message> {
|
|||
(None, ret)
|
||||
}
|
||||
|
||||
#[allow(unused_results)]
|
||||
#[allow(unused_results, clippy::too_many_lines)]
|
||||
fn draw(
|
||||
&self,
|
||||
renderer: &mut crate::Renderer,
|
||||
|
|
@ -717,9 +698,7 @@ impl<'b, Message: Clone + 'static> Menu<'b, Message> {
|
|||
if !state.open || state.active_root.len() <= self.depth {
|
||||
return;
|
||||
}
|
||||
let Some(active_root) = state.active_root.get(self.depth) else {
|
||||
return;
|
||||
};
|
||||
let active_root = &state.active_root[..=self.depth];
|
||||
let viewport = layout.bounds();
|
||||
let viewport_size = viewport.size();
|
||||
let overlay_offset = Point::ORIGIN - viewport.position();
|
||||
|
|
@ -733,7 +712,7 @@ impl<'b, Message: Clone + 'static> Menu<'b, Message> {
|
|||
let styling = theme.appearance(&self.style);
|
||||
let (active_tree, roots) = active_root
|
||||
.iter()
|
||||
.skip(if self.is_overlay { 0 } else { 1 })
|
||||
.skip(1)
|
||||
.fold(
|
||||
(
|
||||
&state.tree.children[active_root[0]].children,
|
||||
|
|
@ -742,8 +721,7 @@ impl<'b, Message: Clone + 'static> Menu<'b, Message> {
|
|||
|(tree, mt), next_active_root| (tree, &mt[*next_active_root].children),
|
||||
);
|
||||
let indices = state.get_trimmed_indices(self.depth).collect::<Vec<_>>();
|
||||
|
||||
state.menu_states[self.depth]
|
||||
state.menu_states[if self.is_overlay {0} else {self.depth}..=self.depth]
|
||||
.iter()
|
||||
.zip(layout.children())
|
||||
.enumerate()
|
||||
|
|
@ -812,7 +790,6 @@ impl<'b, Message: Clone + 'static> Menu<'b, Message> {
|
|||
}
|
||||
}
|
||||
if start_index < menu_roots.len() {
|
||||
// dbg!(start_index, end_index, menu_roots.len());
|
||||
// draw item
|
||||
menu_roots[start_index..=end_index]
|
||||
.iter()
|
||||
|
|
@ -838,7 +815,7 @@ impl<'b, Message: Clone + 'static> Menu<'b, Message> {
|
|||
.map_or(menu_roots, |active| &menu_roots[active].children)
|
||||
},
|
||||
);
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
impl<Message: Clone + 'static> overlay::Overlay<Message, crate::Theme, crate::Renderer>
|
||||
|
|
@ -897,7 +874,6 @@ impl<'a, Message: std::clone::Clone + 'static> Widget<Message, crate::Theme, cra
|
|||
renderer: &crate::Renderer,
|
||||
limits: &iced_core::layout::Limits,
|
||||
) -> iced_core::layout::Node {
|
||||
// dbg!("layout", self.window_id, limits);
|
||||
Menu::layout(self, renderer, *limits)
|
||||
}
|
||||
|
||||
|
|
@ -928,7 +904,6 @@ impl<'a, Message: std::clone::Clone + 'static> Widget<Message, crate::Theme, cra
|
|||
) -> event::Status {
|
||||
let (new_root, status) = self.on_event(event, layout, cursor, renderer, clipboard, shell);
|
||||
|
||||
// dbg!(new_root.as_ref().map(|r| r.0));
|
||||
#[cfg(all(feature = "wayland", feature = "winit", feature = "surface-message"))]
|
||||
if let Some((new_root, new_ms)) = new_root {
|
||||
use iced_runtime::platform_specific::wayland::popup::{
|
||||
|
|
@ -948,11 +923,9 @@ impl<'a, Message: std::clone::Clone + 'static> Widget<Message, crate::Theme, cra
|
|||
.get(self.depth)
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
dbg!(self.window_id, popup_id, active_roots);
|
||||
// let root_bounds_list = active_roots
|
||||
// .into_iter()
|
||||
// .fold(layout, |l, active_root| {
|
||||
// dbg!(active_root, l.children().count());
|
||||
// l.children().nth(active_root).unwrap()
|
||||
// })
|
||||
// .children()
|
||||
|
|
@ -968,14 +941,6 @@ impl<'a, Message: std::clone::Clone + 'static> Widget<Message, crate::Theme, cra
|
|||
.collect();
|
||||
// drop(state);
|
||||
|
||||
// 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())),
|
||||
|
|
@ -997,24 +962,7 @@ impl<'a, Message: std::clone::Clone + 'static> Widget<Message, crate::Theme, cra
|
|||
on_surface_action: self.on_surface_action.clone(),
|
||||
};
|
||||
|
||||
// let mut state = self.tree.inner.lock().unwrap();
|
||||
// dbg!(state.menu_states.keys());
|
||||
// let Some(parent_root) = state.active_root.get(&self.window_id) else {
|
||||
// // TODO log warning
|
||||
// return status;
|
||||
// };
|
||||
let Some(parent_root) = state.active_root.get(self.depth).cloned() else {
|
||||
dbg!("NO ROOT?");
|
||||
return None;
|
||||
};
|
||||
|
||||
let mut roots = parent_root.clone();
|
||||
dbg!(&roots);
|
||||
|
||||
roots.push(new_root);
|
||||
dbg!(&roots);
|
||||
state.active_root.push(roots);
|
||||
dbg!(&state.active_root);
|
||||
state.active_root.push(new_root);
|
||||
|
||||
Some((popup_menu, popup_id))
|
||||
}) else {
|
||||
|
|
@ -1032,12 +980,7 @@ impl<'a, Message: std::clone::Clone + 'static> Widget<Message, crate::Theme, cra
|
|||
self.main_offset as f32,
|
||||
);
|
||||
let anchor_rect = self.tree.inner.with_data_mut(|state| {
|
||||
// let mut state = self.tree.inner.lock().unwrap();
|
||||
// state.menu_states.get_mut(self.depth).unwrap().push(new_ms);
|
||||
|
||||
state.menu_states[self.depth]
|
||||
.iter()
|
||||
.find(|s| s.index.is_none())
|
||||
state.menu_states.get(self.depth + 1)
|
||||
.map(|s| s.menu_bounds.parent_bounds)
|
||||
.map_or_else(
|
||||
|| {
|
||||
|
|
@ -1075,19 +1018,6 @@ impl<'a, Message: std::clone::Clone + 'static> Widget<Message, crate::Theme, cra
|
|||
..Default::default()
|
||||
};
|
||||
let parent = self.window_id;
|
||||
dbg!(
|
||||
self.depth + 1,
|
||||
&positioner,
|
||||
parent,
|
||||
popup_id,
|
||||
&menu_node,
|
||||
anchor_rect
|
||||
);
|
||||
let ar_len = self
|
||||
.tree
|
||||
.inner
|
||||
.with_data_mut(|state| state.active_root.len());
|
||||
// if self.depth < 1 {
|
||||
shell.publish((self.on_surface_action.as_ref().unwrap())(
|
||||
crate::surface::action::simple_popup(
|
||||
move || SctkPopupSettings {
|
||||
|
|
@ -1107,17 +1037,6 @@ impl<'a, Message: std::clone::Clone + 'static> Widget<Message, crate::Theme, cra
|
|||
}),
|
||||
),
|
||||
));
|
||||
// } else {
|
||||
// dbg!(SctkPopupSettings {
|
||||
// parent,
|
||||
// id: popup_id,
|
||||
// positioner: positioner.clone(),
|
||||
// parent_size: None,
|
||||
// grab: true,
|
||||
// close_with_children: false,
|
||||
// input_zone: None,
|
||||
// });
|
||||
// }
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
@ -1158,67 +1077,14 @@ pub(super) fn init_root_menu<Message: Clone>(
|
|||
if !(state
|
||||
.menu_states
|
||||
.get(menu.depth)
|
||||
.is_none_or(|s| s.is_empty())
|
||||
.is_none()
|
||||
&& (!menu.is_overlay || bar_bounds.contains(overlay_cursor)))
|
||||
|| menu.depth > 0
|
||||
|| !state.open
|
||||
{
|
||||
// dbg!("exiting from root menu init early...", menu.depth);
|
||||
return;
|
||||
}
|
||||
|
||||
dbg!(
|
||||
menu.depth,
|
||||
menu.window_id,
|
||||
&menu.root_bounds_list,
|
||||
state.menu_states.get(menu.depth).is_none()
|
||||
);
|
||||
dbg!(menu.menu_roots.len());
|
||||
dbg!(
|
||||
state
|
||||
.menu_states
|
||||
.get(menu.depth)
|
||||
.is_none_or(|s| s.is_empty())
|
||||
);
|
||||
dbg!(
|
||||
menu.menu_roots
|
||||
.as_slice()
|
||||
.iter()
|
||||
.map(|r| r.index)
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
dbg!(
|
||||
state
|
||||
.active_root
|
||||
.get(menu.depth)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.count()
|
||||
.saturating_sub(1)
|
||||
);
|
||||
// let root = state
|
||||
// .active_root
|
||||
// .get(menu.depth)
|
||||
// .iter()
|
||||
// .map(|l| l.into_iter())
|
||||
// .flatten()
|
||||
// .take(
|
||||
// state
|
||||
// .active_root
|
||||
// .get(menu.depth)
|
||||
// .into_iter()
|
||||
// .flatten()
|
||||
// .count()
|
||||
// .saturating_sub(1),
|
||||
// )
|
||||
// .fold(menu.menu_roots.as_slice(), |m, i| {
|
||||
// dbg!(m.len());
|
||||
// m[*i].children.as_slice()
|
||||
// });
|
||||
// dbg!(root.len());
|
||||
dbg!(menu.depth);
|
||||
|
||||
let mut set = false;
|
||||
for (i, (&root_bounds, mt)) in menu
|
||||
.root_bounds_list
|
||||
|
|
@ -1227,14 +1093,10 @@ pub(super) fn init_root_menu<Message: Clone>(
|
|||
.enumerate()
|
||||
{
|
||||
if mt.children.is_empty() {
|
||||
// dbg!("skipping menu with no children");
|
||||
continue;
|
||||
}
|
||||
dbg!(mt.children.len());
|
||||
dbg!(i, root_bounds.contains(overlay_cursor));
|
||||
|
||||
if root_bounds.contains(overlay_cursor) {
|
||||
dbg!(root_bounds);
|
||||
// dbg!(i, root_bounds, mt.width, mt.height);
|
||||
let view_center = viewport_size.width * 0.5;
|
||||
let rb_center = root_bounds.center_x();
|
||||
|
||||
|
|
@ -1268,22 +1130,14 @@ pub(super) fn init_root_menu<Message: Clone>(
|
|||
menu.is_overlay,
|
||||
);
|
||||
set = true;
|
||||
dbg!(i);
|
||||
|
||||
dbg!("inserting root menu state");
|
||||
dbg!(&menu_bounds.children_bounds);
|
||||
dbg!((&menu_bounds.child_positions));
|
||||
dbg!(&state.active_root);
|
||||
state.active_root.insert(menu.depth, vec![i]);
|
||||
// do we need to insert the rest now too?
|
||||
state.active_root.insert(menu.depth, i);
|
||||
let ms = MenuState {
|
||||
index: None,
|
||||
scroll_offset: 0.0,
|
||||
menu_bounds,
|
||||
};
|
||||
dbg!("pushing to menu states...");
|
||||
let v = super::menu_bar::get_mut_or_default(&mut state.menu_states, menu.depth);
|
||||
v.push(ms);
|
||||
state.menu_states.push(ms);
|
||||
|
||||
// Hack to ensure menu opens properly
|
||||
shell.invalidate_layout();
|
||||
|
|
@ -1292,12 +1146,12 @@ pub(super) fn init_root_menu<Message: Clone>(
|
|||
}
|
||||
}
|
||||
if !set {
|
||||
dbg!(overlay_cursor);
|
||||
panic!("huh");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "wayland", feature = "winit", feature = "surface-message"))]
|
||||
pub(super) fn init_root_popup_menu<Message>(
|
||||
menu: &mut Menu<'_, Message>,
|
||||
renderer: &crate::Renderer,
|
||||
|
|
@ -1310,61 +1164,29 @@ pub(super) fn init_root_popup_menu<Message>(
|
|||
) where
|
||||
Message: std::clone::Clone,
|
||||
{
|
||||
dbg!("init");
|
||||
menu.tree.inner.with_data_mut(|state| {
|
||||
if !(state
|
||||
.menu_states
|
||||
.get(menu.depth)
|
||||
.is_none_or(|s| s.is_empty())
|
||||
.is_none()
|
||||
&& (!menu.is_overlay || bar_bounds.contains(overlay_cursor)))
|
||||
{
|
||||
dbg!("exiting init early", menu.depth);
|
||||
return;
|
||||
}
|
||||
|
||||
println!(
|
||||
"init root menu {} {:?}",
|
||||
menu.window_id, menu.root_bounds_list
|
||||
);
|
||||
// dbg!(state
|
||||
// .menu_states
|
||||
// .get(&menu.window_id)
|
||||
// .is_none_or(|s| s.is_empty()));
|
||||
// dbg!(menu
|
||||
// .menu_roots
|
||||
// .as_slice()
|
||||
// .iter()
|
||||
// .map(|r| r.index)
|
||||
// .collect::<Vec<_>>());
|
||||
|
||||
// dbg!(state
|
||||
// .active_root
|
||||
// .get(&menu.window_id)
|
||||
// .into_iter()
|
||||
// .flatten()
|
||||
// .count());
|
||||
let active_roots = state
|
||||
.active_root
|
||||
.get(menu.depth)
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
dbg!(&active_roots);
|
||||
dbg!(menu.menu_roots.len(), menu.root_bounds_list.len());
|
||||
let active_roots = &state
|
||||
.active_root[..=menu.depth];
|
||||
|
||||
let mut set = false;
|
||||
let mt = active_roots
|
||||
.iter()
|
||||
.skip(if menu.is_overlay { 0 } else { 1 })
|
||||
let mt = active_roots.iter()
|
||||
.skip(1)
|
||||
.fold(&menu.menu_roots[active_roots[0]], |mt, next_active_root| {
|
||||
&mt.children[*next_active_root]
|
||||
});
|
||||
let i = active_roots.last().unwrap();
|
||||
let root_bounds = menu.root_bounds_list[*i];
|
||||
|
||||
if mt.children.is_empty() {
|
||||
panic!("skipping menu with no children");
|
||||
}
|
||||
dbg!(root_bounds, overlay_cursor);
|
||||
assert!(!mt.children.is_empty(), "skipping menu with no children");
|
||||
let aod = Aod {
|
||||
horizontal: true,
|
||||
vertical: true,
|
||||
|
|
@ -1389,8 +1211,7 @@ pub(super) fn init_root_popup_menu<Message>(
|
|||
&mut state.tree.children[0].children,
|
||||
menu.is_overlay,
|
||||
);
|
||||
dbg!(mt.children.len(), root_bounds, overlay_cursor, i,);
|
||||
dbg!(i, root_bounds, mt.width, mt.height);
|
||||
|
||||
let view_center = viewport_size.width * 0.5;
|
||||
let rb_center = root_bounds.center_x();
|
||||
|
||||
|
|
@ -1399,12 +1220,6 @@ pub(super) fn init_root_popup_menu<Message>(
|
|||
} else {
|
||||
Direction::Positive
|
||||
};
|
||||
|
||||
// dbg!(
|
||||
// state.tree.children.len(),
|
||||
// state.tree.children[0].children.len(),
|
||||
// );
|
||||
|
||||
set = true;
|
||||
|
||||
let ms = MenuState {
|
||||
|
|
@ -1412,23 +1227,18 @@ pub(super) fn init_root_popup_menu<Message>(
|
|||
scroll_offset: 0.0,
|
||||
menu_bounds,
|
||||
};
|
||||
let v = super::menu_bar::get_mut_or_default(&mut state.menu_states, menu.depth);
|
||||
v.push(ms);
|
||||
dbg!(v.len(), menu.depth);
|
||||
dbg!(i);
|
||||
state.menu_states.push(ms);
|
||||
|
||||
// Hack to ensure menu opens properly
|
||||
shell.invalidate_layout();
|
||||
|
||||
if !set {
|
||||
panic!("oops");
|
||||
}
|
||||
})
|
||||
// non tree buttons arent active?
|
||||
assert!(set, "oops");
|
||||
});
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn process_menu_events<'b, Message: std::clone::Clone>(
|
||||
menu: &'b mut Menu<Message>,
|
||||
fn process_menu_events<Message: std::clone::Clone>(
|
||||
menu: &mut Menu<Message>,
|
||||
event: event::Event,
|
||||
view_cursor: Cursor,
|
||||
renderer: &crate::Renderer,
|
||||
|
|
@ -1438,70 +1248,44 @@ fn process_menu_events<'b, Message: std::clone::Clone>(
|
|||
) -> event::Status {
|
||||
use event::Status;
|
||||
|
||||
let window_id = menu.window_id;
|
||||
let is_overlay = menu.is_overlay;
|
||||
let my_state = &mut menu.tree;
|
||||
let menu_roots = match &mut menu.menu_roots {
|
||||
Cow::Borrowed(_) => panic!(),
|
||||
Cow::Owned(o) => o.as_mut_slice(),
|
||||
};
|
||||
my_state.inner.with_data_mut(|state| {
|
||||
let Some(active_root) = state.active_root.get(menu.depth).cloned() else {
|
||||
if state.active_root.len() <= menu.depth {
|
||||
return event::Status::Ignored;
|
||||
}
|
||||
|
||||
let Some(hover) = state.menu_states.last_mut() else {
|
||||
return Status::Ignored;
|
||||
};
|
||||
|
||||
let indices = state.get_trimmed_indices(menu.depth);
|
||||
|
||||
let indices = indices.collect::<Vec<_>>();
|
||||
// if is_overlay {
|
||||
// indices.collect::<Vec<_>>()
|
||||
// } else {
|
||||
// indices.take(1).collect::<Vec<_>>()
|
||||
// };
|
||||
|
||||
if indices.is_empty() {
|
||||
let Some(hover_index) = hover.index else {
|
||||
return Status::Ignored;
|
||||
}
|
||||
};
|
||||
|
||||
// get active item
|
||||
// let mt = indices.iter().fold(root | mt, &i | &mut mt.children[i]);
|
||||
// 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| {
|
||||
// dbg!(mt.children.len(), next_active_root);
|
||||
// (tree, &mut mt.children[*next_active_root])
|
||||
// },
|
||||
// );
|
||||
let (tree, mt) = active_root
|
||||
let (tree, mt) = state.active_root
|
||||
.iter()
|
||||
.skip(if menu.is_overlay { 0 } else { 1 })
|
||||
.skip(1)
|
||||
.fold(
|
||||
// then use menu states for each open menu
|
||||
(
|
||||
&mut state.tree.children[active_root[0]].children,
|
||||
&mut menu_roots[active_root[0]],
|
||||
&mut state.tree.children[state.active_root[0]].children,
|
||||
&mut menu_roots[state.active_root[0]],
|
||||
),
|
||||
|(tree, mt), next_active_root| (tree, &mut mt.children[*next_active_root]),
|
||||
);
|
||||
// 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 mt = &mut mt.children[hover_index];
|
||||
let tree = &mut tree[mt.index];
|
||||
|
||||
// get layout
|
||||
let last_ms = &state.menu_states[menu.depth][indices.len() - 1];
|
||||
let child_node = last_ms.layout_single(
|
||||
let child_node = hover.layout_single(
|
||||
overlay_offset,
|
||||
last_ms.index.expect("missing index within menu state."),
|
||||
hover.index.expect("missing index within menu state."),
|
||||
renderer,
|
||||
mt,
|
||||
tree,
|
||||
|
|
@ -1531,8 +1315,7 @@ fn process_overlay_events<Message>(
|
|||
view_cursor: Cursor,
|
||||
overlay_cursor: Point,
|
||||
cross_offset: f32,
|
||||
is_overlay: bool,
|
||||
shell: &mut Shell<'_, Message>,
|
||||
_shell: &mut Shell<'_, Message>,
|
||||
) -> (Option<(usize, MenuState)>, event::Status)
|
||||
where
|
||||
Message: std::clone::Clone,
|
||||
|
|
@ -1550,12 +1333,7 @@ where
|
|||
let mut new_menu_root = None;
|
||||
|
||||
menu.tree.inner.with_data_mut(|state| {
|
||||
let Some(active_root) = state.active_root.get(menu.depth).clone() else {
|
||||
if is_overlay && !menu.bar_bounds.contains(overlay_cursor) {
|
||||
state.reset();
|
||||
}
|
||||
return (new_menu_root, Ignored);
|
||||
};
|
||||
let active_root = &state.active_root[..=menu.depth];
|
||||
|
||||
if state.pressed {
|
||||
return (new_menu_root, Ignored);
|
||||
|
|
@ -1566,28 +1344,24 @@ where
|
|||
state.view_cursor = view_cursor;
|
||||
|
||||
// * remove invalid menus
|
||||
dbg!(
|
||||
&state
|
||||
.menu_states
|
||||
.iter()
|
||||
.map(|s| s.iter().map(|s| s.index).collect::<Vec<_>>())
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
let mut prev_bounds = std::iter::once(menu.bar_bounds)
|
||||
.chain(
|
||||
(state.menu_states[..menu.depth])
|
||||
.iter()
|
||||
.map(|s| s[0].menu_bounds.children_bounds),
|
||||
if menu.is_overlay {
|
||||
state.menu_states[..state.menu_states.len().saturating_sub(1)].iter()
|
||||
} else {
|
||||
state.menu_states[..menu.depth].iter()
|
||||
}
|
||||
.map(|s| s.menu_bounds.children_bounds),
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
let menu_states = state.menu_states.get_mut(menu.depth).unwrap();
|
||||
|
||||
if menu.close_condition.leave {
|
||||
for i in (0..menu_states.len()).rev() {
|
||||
let mb = &menu_states[i].menu_bounds;
|
||||
|
||||
if menu.is_overlay && menu.close_condition.leave {
|
||||
for i in (0..state.menu_states.len()).rev() {
|
||||
let mb = &state.menu_states[i].menu_bounds;
|
||||
|
||||
if mb.parent_bounds.contains(overlay_cursor)
|
||||
|| is_overlay && mb.children_bounds.contains(overlay_cursor)
|
||||
|| menu.is_overlay && mb.children_bounds.contains(overlay_cursor)
|
||||
|| mb.offset_bounds.contains(overlay_cursor)
|
||||
|| (mb.check_bounds.contains(overlay_cursor)
|
||||
&& prev_bounds.iter().all(|pvb| !pvb.contains(overlay_cursor)))
|
||||
|
|
@ -1595,31 +1369,18 @@ where
|
|||
break;
|
||||
}
|
||||
prev_bounds.pop();
|
||||
menu_states.pop();
|
||||
}
|
||||
} else {
|
||||
for i in (0..menu_states.len()).rev() {
|
||||
let mb = &menu_states[i].menu_bounds;
|
||||
|
||||
if mb.parent_bounds.contains(overlay_cursor)
|
||||
|| mb.children_bounds.contains(overlay_cursor)
|
||||
|| prev_bounds.iter().all(|pvb| !pvb.contains(overlay_cursor))
|
||||
{
|
||||
break;
|
||||
}
|
||||
prev_bounds.pop();
|
||||
menu_states.pop();
|
||||
state.menu_states.pop();
|
||||
}
|
||||
}
|
||||
|
||||
// get indices
|
||||
let indices = menu_states.iter().map(|ms| ms.index).collect::<Vec<_>>();
|
||||
let should_add = is_overlay || menu_states.len() < 2;
|
||||
dbg!(&indices);
|
||||
|
||||
// dbg!(menu_states.iter().map(|m| m.index).collect::<Vec<_>>());
|
||||
// * update active item
|
||||
let Some(last_menu_state) = menu_states.get_mut(0) else {
|
||||
let menu_states_len = state.menu_states.len();
|
||||
let Some(last_menu_state) = state.menu_states.get_mut(if menu.is_overlay {
|
||||
menu_states_len - 1
|
||||
} else {
|
||||
menu.depth
|
||||
}) else {
|
||||
if menu.is_overlay {
|
||||
// no menus left
|
||||
// TODO do we want to avoid this for popups?
|
||||
|
|
@ -1633,7 +1394,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
dbg!("no last menu state", menu.depth, menu_states.len());
|
||||
return (new_menu_root, Captured);
|
||||
};
|
||||
|
||||
|
|
@ -1641,26 +1401,27 @@ where
|
|||
let last_parent_bounds = last_menu_bounds.parent_bounds;
|
||||
let last_children_bounds = last_menu_bounds.children_bounds;
|
||||
|
||||
if (is_overlay && !menu.menu_overlays_parent && last_parent_bounds.contains(overlay_cursor))
|
||||
if (menu.is_overlay && !menu.menu_overlays_parent && last_parent_bounds.contains(overlay_cursor))
|
||||
// cursor is in the parent part
|
||||
|| is_overlay && !last_children_bounds.contains(overlay_cursor)
|
||||
|| menu.is_overlay && !last_children_bounds.contains(overlay_cursor)
|
||||
// cursor is outside
|
||||
{
|
||||
last_menu_state.index = None;
|
||||
dbg!("cursor is outside...");
|
||||
return (new_menu_root, Captured);
|
||||
}
|
||||
// cursor is in the children part
|
||||
|
||||
// TODO set active root here even when not a tree.
|
||||
// ensure that the
|
||||
|
||||
// calc new index
|
||||
let height_diff = (overlay_cursor.y
|
||||
- (last_children_bounds.y + last_menu_state.scroll_offset))
|
||||
.clamp(0.0, last_children_bounds.height - 0.001);
|
||||
// dbg!(height_diff);
|
||||
|
||||
let (active_tree, roots) = active_root
|
||||
.iter()
|
||||
.skip(if menu.is_overlay { 0 } else { 1 })
|
||||
.skip(1)
|
||||
.fold(
|
||||
(
|
||||
&mut state.tree.children[active_root[0]].children,
|
||||
|
|
@ -1668,22 +1429,8 @@ where
|
|||
),
|
||||
|(tree, mt), next_active_root| (tree, &mt[*next_active_root].children),
|
||||
);
|
||||
if is_overlay {
|
||||
panic!();
|
||||
}
|
||||
let active_menu = if is_overlay {
|
||||
indices[0..indices.len().saturating_sub(1)].iter().fold(
|
||||
roots,
|
||||
|mt: &Vec<MenuTree<Message>>, i| {
|
||||
&mt[i.expect("missing active child index in menu")].children
|
||||
},
|
||||
)
|
||||
} else {
|
||||
// popup does one layer deep
|
||||
roots
|
||||
};
|
||||
// dbg!(active_menu.children.len());
|
||||
// dbg!(menu.window_id);
|
||||
|
||||
let active_menu = roots;
|
||||
let new_index = match menu.item_height {
|
||||
ItemHeight::Uniform(u) => (height_diff / f32::from(u)).floor() as usize,
|
||||
ItemHeight::Static(_) | ItemHeight::Dynamic(_) => {
|
||||
|
|
@ -1698,41 +1445,32 @@ where
|
|||
)
|
||||
}
|
||||
};
|
||||
let remove = last_menu_state
|
||||
.index
|
||||
.as_ref()
|
||||
.is_some_and(|i| *i != new_index && !active_menu[*i].children.is_empty());
|
||||
|
||||
|
||||
let remove = !menu.is_overlay
|
||||
&& last_menu_state
|
||||
.index
|
||||
.as_ref()
|
||||
.is_some_and(|i| *i != new_index && !active_menu[*i].children.is_empty());
|
||||
|
||||
#[cfg(all(feature = "wayland", feature = "winit", feature = "surface-message"))]
|
||||
if remove {
|
||||
if let Some(id) = state.popup_id.remove(&menu.window_id) {
|
||||
state.active_root.pop();
|
||||
shell.publish((menu.on_surface_action.as_ref().unwrap())({
|
||||
crate::surface::action::destroy_popup(id)
|
||||
}))
|
||||
};
|
||||
{
|
||||
if remove {
|
||||
if let Some(id) = state.popup_id.remove(&menu.window_id) {
|
||||
state.active_root.truncate(menu.depth + 1);
|
||||
_shell.publish((menu.on_surface_action.as_ref().unwrap())({
|
||||
crate::surface::action::destroy_popup(id)
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let item = &active_menu[new_index];
|
||||
// dbg!(new_index);
|
||||
// dbg!(item.index);
|
||||
// if the index changes, get a new root
|
||||
// if !last_menu_state.index.is_some_and(|old| old == new_index) && !item.children.is_empty() {
|
||||
// dbg!(&indices);
|
||||
// dbg!(new_index);
|
||||
// dbg!(item.children.len());
|
||||
// dbg!(menu.window_id);
|
||||
// new_menu_root = Some(new_index);
|
||||
// }
|
||||
|
||||
// set new index
|
||||
let old_index = last_menu_state.index.replace(new_index);
|
||||
// dbg!(should_add);
|
||||
dbg!(old_index, new_index);
|
||||
// get new active item
|
||||
// * add new menu if the new item is a menu
|
||||
if !item.children.is_empty() {
|
||||
// dbg!("its a menu");
|
||||
if !item.children.is_empty() && old_index.is_none_or(|i| i != new_index) {
|
||||
let item_position = Point::new(
|
||||
0.0,
|
||||
last_menu_bounds.child_positions[new_index] + last_menu_state.scroll_offset,
|
||||
|
|
@ -1770,19 +1508,14 @@ where
|
|||
menu.is_overlay,
|
||||
),
|
||||
};
|
||||
if !old_index.is_some_and(|old| old == new_index) {
|
||||
// dbg!("adding new menu");
|
||||
new_menu_root = Some((new_index, ms.clone()));
|
||||
}
|
||||
if should_add {
|
||||
let v = super::menu_bar::get_mut_or_default(&mut state.menu_states, menu.depth);
|
||||
v.push(ms);
|
||||
}
|
||||
|
||||
new_menu_root = Some((new_index, ms.clone()));
|
||||
state.menu_states.truncate(menu.depth + 1);
|
||||
state.menu_states.push(ms);
|
||||
} else if remove {
|
||||
state.menu_states.truncate(menu.depth + 1);
|
||||
}
|
||||
if remove {
|
||||
state.menu_states.pop();
|
||||
}
|
||||
|
||||
|
||||
(new_menu_root, Captured)
|
||||
})
|
||||
}
|
||||
|
|
@ -1801,7 +1534,6 @@ where
|
|||
use mouse::ScrollDelta;
|
||||
|
||||
menu.tree.inner.with_data_mut(|state| {
|
||||
dbg!(state.active_root.len());
|
||||
|
||||
let delta_y = match delta {
|
||||
ScrollDelta::Lines { y, .. } => y * 60.0,
|
||||
|
|
@ -1817,13 +1549,12 @@ where
|
|||
(viewport_size.height - (children_bounds.y + children_bounds.height)).min(0.0);
|
||||
(max_offset, min_offset)
|
||||
};
|
||||
let menu_states = state.menu_states.get_mut(0).unwrap();
|
||||
|
||||
// update
|
||||
if menu_states.is_empty() {
|
||||
if state.menu_states.is_empty() {
|
||||
return Ignored;
|
||||
} else if menu_states.len() == 1 {
|
||||
let last_ms = &mut menu_states[0];
|
||||
} else if state.menu_states.len() == 1 {
|
||||
let last_ms = &mut state.menu_states[0];
|
||||
|
||||
if last_ms.index.is_none() {
|
||||
return Captured;
|
||||
|
|
@ -1833,8 +1564,8 @@ where
|
|||
last_ms.scroll_offset = (last_ms.scroll_offset + delta_y).clamp(min_offset, max_offset);
|
||||
} else {
|
||||
// >= 2
|
||||
let max_index = menu_states.len() - 1;
|
||||
let last_two = &mut menu_states[max_index - 1..=max_index];
|
||||
let max_index = state.menu_states.len() - 1;
|
||||
let last_two = &mut state.menu_states[max_index - 1..=max_index];
|
||||
|
||||
if last_two[1].index.is_some() {
|
||||
// scroll the last one
|
||||
|
|
@ -1927,7 +1658,7 @@ fn get_children_layout<Message>(
|
|||
.collect(),
|
||||
};
|
||||
|
||||
let max_index = menu_tree.children.len() - 1;
|
||||
let max_index = menu_tree.children.len().saturating_sub(1);
|
||||
let child_positions: Vec<f32> = std::iter::once(0.0)
|
||||
.chain(child_sizes[0..max_index].iter().scan(0.0, |acc, x| {
|
||||
*acc += x.height;
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ pub fn menu_items<
|
|||
}
|
||||
|
||||
// dbg!("button with action...", action.message());
|
||||
let menu_button = menu_button(items).on_press(action.message()).description(l);
|
||||
let menu_button = menu_button(items).on_press(action.message());
|
||||
|
||||
trees.push(MenuTree::<Message>::from(Element::from(menu_button)));
|
||||
}
|
||||
|
|
@ -272,7 +272,7 @@ pub fn menu_items<
|
|||
items.insert(1, widget::Space::with_width(spacing.space_xxs).into());
|
||||
}
|
||||
|
||||
let menu_button = menu_button(items).description((l.clone()));
|
||||
let menu_button = menu_button(items);
|
||||
|
||||
trees.push(MenuTree::<Message>::from(Element::from(menu_button)));
|
||||
}
|
||||
|
|
@ -321,7 +321,6 @@ pub fn menu_items<
|
|||
.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() {
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ impl ResponsiveMenuBar {
|
|||
crate::widget::RcElementWrapper::new(Element::from(
|
||||
menu::root(mt.0),
|
||||
)),
|
||||
menu::items(key_binds, mt.1.into()),
|
||||
menu::items(key_binds, mt.1),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue