Skip to content

Commit

Permalink
mouse interations
Browse files Browse the repository at this point in the history
  • Loading branch information
latidoremi committed Feb 23, 2024
1 parent 17f33a7 commit 1f3f107
Show file tree
Hide file tree
Showing 8 changed files with 519 additions and 383 deletions.
585 changes: 301 additions & 284 deletions examples/menu/src/main.rs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/native/menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,6 @@ mod menu_bar_overlay;
mod menu_tree;

pub use crate::style::menu_bar::{Appearance, StyleSheet};
pub use common::DrawPath;
pub use menu_bar::MenuBar;
pub use menu_tree::{Item, Menu};
pub use common::DrawPath;
32 changes: 16 additions & 16 deletions src/native/menu/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,27 @@ pub struct CloseCondition {
*/

///
/// ## FakeHovering:
/// ## FakeHovering:
///
/// Places cursors at the path items, i.e. fake hovering,
/// useful when you want to customize the styling of each item in the path,
/// or you simple want the look of the items when they are hovered over.
///
/// The downside is when some widgets in the path don't response to hovering,
/// the path won't be fully drawn, and when you want uniform path styling
/// Places cursors at the path items,
/// useful when you want to customize the styling of each item in the path,
/// or you simple want the look of the items when they are hovered over.
///
/// The downside is when some widgets in the path don't response to hovering,
/// the path won't be fully drawn, and when you want uniform path styling
/// but some widgets response to hovering differently.
///
///
/// ## Backdrop:
///
/// Draws a rectangle behind each path item,
/// requires path items to have transparent backgrounds,
/// useful when you want uniform path styling.
///
/// The downside is,
/// depend on the style you're going for,
/// sometimes manually syncing the path styling to the path items is needed
/// Draws a rectangle behind each path item,
/// requires path items to have transparent backgrounds,
/// useful when you want uniform path styling.
///
/// The downside is,
/// depend on the style you're going for,
/// oftentimes manually syncing the path's styling to the path items' is necessary
///
pub enum DrawPath{
pub enum DrawPath {
/// FakeHovering
FakeHovering,
/// Backdrop
Expand Down
14 changes: 6 additions & 8 deletions src/native/menu/menu_bar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,27 +253,24 @@ where

let state = tree.state.downcast_ref::<MenuBarState>();
if state.open {
if let Some(active) = state.active_root{
let Some(active_bounds) = layout.children()
.nth(active)
.map(|l| l.bounds())
else{
if let Some(active) = state.active_root {
let Some(active_bounds) = layout.children().nth(active).map(|l| l.bounds()) else {
return;
};

match self.draw_path{
match self.draw_path {
DrawPath::Backdrop => {
renderer.fill_quad(
renderer::Quad {
bounds: active_bounds,
border: styling.path_border,
..Default::default()
},
styling.path
styling.path,
);
}
DrawPath::FakeHovering => {
if !cursor.is_over(active_bounds){
if !cursor.is_over(active_bounds) {
cursor = mouse::Cursor::Available(active_bounds.center())
}
}
Expand Down Expand Up @@ -313,6 +310,7 @@ where
check_bounds_width: self.check_bounds_width,
draw_path: &self.draw_path,
style: &self.style,
// is_over: false,
}
.overlay_element(),
)
Expand Down
131 changes: 101 additions & 30 deletions src/native/menu/menu_bar_overlay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ where
pub(super) check_bounds_width: f32,
pub(super) draw_path: &'b DrawPath,
pub(super) style: &'b Theme::Style,
// pub(super) is_over: bool,
}
impl<'a, 'b, Message, Theme, Renderer> MenuBarOverlay<'a, 'b, Message, Theme, Renderer>
where
Expand Down Expand Up @@ -394,6 +395,76 @@ where
}
}

fn mouse_interaction(
&self,
layout: Layout<'_>,
cursor: mouse::Cursor,
viewport: &Rectangle,
renderer: &Renderer,
) -> mouse::Interaction {
let bar = self.tree.state.downcast_ref::<MenuBarState>();
let Some(active) = bar.active_root else {
return mouse::Interaction::default();
};

// let viewport = layout.bounds();
let mut lc = layout.children();
let _bar_bounds = lc.next().unwrap().bounds();
let _roots_layout = lc.next().unwrap();

// let parent_bounds = roots_layout.children().nth(active).unwrap().bounds();
let menu_layouts_layout = lc.next().unwrap(); // Node{0, [menu_node...]}
let mut menu_layouts = menu_layouts_layout.children(); // [menu_node...]

let active_root = &self.roots[active];
let active_tree = &self.tree.children[active];

fn rec<'a, 'b, Message, Theme: StyleSheet, Renderer: renderer::Renderer>(
tree: &Tree,
item: &Item<'a, Message, Theme, Renderer>,
layout_iter: &mut impl Iterator<Item = Layout<'b>>,
cursor: mouse::Cursor,
renderer: &Renderer,
viewport: &Rectangle,
) -> mouse::Interaction {
let menu = item.menu.as_ref().expect("No menu defined in this item");
let menu_tree = &tree.children[1];

let Some(menu_layout) = layout_iter.next() else {
return mouse::Interaction::default();
}; // menu_node: Node{inf, [ slice_node, prescroll, offset_bounds, check_bounds ]}

let menu_state = menu_tree.state.downcast_ref::<MenuState>();

let i = menu.mouse_interaction(menu_tree, menu_layout, cursor, viewport, renderer);

if let Some(active) = menu_state.active {
let next_tree = &menu_tree.children[active];
let next_item = &menu.items[active];
rec(
next_tree,
next_item,
layout_iter,
cursor,
renderer,
viewport,
)
.max(i)
} else {
i
}
}

rec(
active_tree,
active_root,
&mut menu_layouts,
cursor,
renderer,
viewport,
)
}

fn draw(
&self,
renderer: &mut Renderer,
Expand Down Expand Up @@ -440,38 +511,22 @@ where

let menu_state = menu_tree.state.downcast_ref::<MenuState>();

let mut draw_menu = || {
menu.draw(
draw_path,
menu_tree,
renderer,
theme,
style,
theme_style,
menu_layout,
cursor,
viewport,
);
};
menu.draw(
draw_path,
menu_tree,
renderer,
theme,
style,
theme_style,
menu_layout,
cursor,
viewport,
);

if let Some(active) = menu_state.active {
let next_tree = &menu_tree.children[active];
let next_item = &menu.items[active];

// let mut mc = menu_layout.children();
// let slice_layout = mc.next().unwrap(); // slice_node
// let active_bounds = {
// let Some(layout) = slice_layout
// .children()
// .nth(active - menu_state.slice.start_index)
// else {
// return;
// };
// layout.bounds()
// };

draw_menu();

renderer.with_layer(*viewport, |r| {
rec(
draw_path,
Expand All @@ -486,8 +541,6 @@ where
viewport,
);
});
} else {
draw_menu();
}
}

Expand All @@ -505,7 +558,25 @@ where
);
}

fn is_over(&self, _layout: Layout<'_>, _renderer: &Renderer, _cursor_position: Point) -> bool {
fn is_over(&self, layout: Layout<'_>, _renderer: &Renderer, cursor_position: Point) -> bool {
let mut lc = layout.children();
let _bar_bounds = lc.next().unwrap().bounds();
let _roots_layout = lc.next().unwrap();
let Some(menu_layouts) = lc.next().map(|l| l.children()) else {
return false;
}; // [menu_node...]

for menu_layout in menu_layouts {
// menu_node: Node{inf, [ slice_node, prescroll, offset_bounds, check_bounds ]}
let mut mc = menu_layout.children();
let _slice_layout = mc.next().unwrap();
let prescroll = mc.next().unwrap().bounds();

if prescroll.contains(cursor_position) {
return true;
}
}

false
}
}
64 changes: 53 additions & 11 deletions src/native/menu/menu_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ where
child_direction,
)
}

/// tree: Tree{ menu_state, \[item_tree...] }
///
/// layout: Node{inf, \[ slice_node, prescroll, offset_bounds, check_bounds ]}
Expand Down Expand Up @@ -360,6 +361,34 @@ where
.merge(status)
}

/// tree: Tree{ menu_state, \[item_tree...] }
///
/// layout: Node{inf, \[ slice_node, prescroll, offset_bounds, check_bounds ]}
pub(super) fn mouse_interaction(
&self,
tree: &Tree,
layout: Layout<'_>,
cursor: mouse::Cursor,
viewport: &Rectangle,
renderer: &Renderer,
) -> mouse::Interaction {
let mut lc = layout.children();
let slice_layout = lc.next().unwrap();

let menu_state = tree.state.downcast_ref::<MenuState>();
let slice = &menu_state.slice;

self.items[slice.start_index..=slice.end_index]
.iter()
.zip(tree.children[slice.start_index..=slice.end_index].iter()) // [item_tree...]
.zip(slice_layout.children()) // [item_layout...]
.map(|((item, tree), layout)| {
item.mouse_interaction(tree, layout, cursor, viewport, renderer)
})
.max()
.unwrap_or_default()
}

/// tree: Tree{menu_state, \[item_tree...]}
///
/// layout: Node{inf, \[ items_node, slice_node, prescroll, offset_bounds, check_bounds ]}
Expand Down Expand Up @@ -400,7 +429,8 @@ where

// draw path
if let Some(active) = menu_state.active {
let Some(active_bounds) = slice_layout.children()
let Some(active_bounds) = slice_layout
.children()
.nth(active - menu_state.slice.start_index)
.map(|l| l.bounds())
else {
Expand All @@ -425,8 +455,7 @@ where
}
}
}



// draw start
let Some(start) = self.items.get(slice.start_index) else {
return;
Expand Down Expand Up @@ -455,17 +484,11 @@ where
});

// draw the rest
let Some(items) = self
.items
.get(slice.start_index + 1..=slice.end_index)
else {
let Some(items) = self.items.get(slice.start_index + 1..=slice.end_index) else {
return;
};

let Some(trees) = tree
.children
.get(slice.start_index + 1..=slice.end_index)
else {
let Some(trees) = tree.children.get(slice.start_index + 1..=slice.end_index) else {
return;
};

Expand Down Expand Up @@ -700,6 +723,25 @@ where
)
}

/// tree: Tree{stateless, \[widget_tree, menu_tree]}
///
pub(super) fn mouse_interaction(
&self,
tree: &Tree,
layout: Layout<'_>,
cursor: mouse::Cursor,
viewport: &Rectangle,
renderer: &Renderer,
) -> mouse::Interaction {
self.item.as_widget().mouse_interaction(
&tree.children[0],
layout,
cursor,
viewport,
renderer,
)
}

/// tree: Tree{stateless, \[widget_tree, menu_tree]}
///
pub(super) fn draw(
Expand Down
Loading

0 comments on commit 1f3f107

Please sign in to comment.