#![allow(clippy::unwrap_used)]
#![allow(clippy::doc_markdown)]
#![allow(clippy::wildcard_imports)]
#![allow(clippy::enum_glob_use)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::items_after_statements)]
#![allow(clippy::similar_names)]
use iced_core::{
Clipboard, Event, Layout, Point, Rectangle, Shell, Size, Vector,
layout::{Limits, Node},
mouse, overlay, renderer,
time::Instant,
widget::{Operation, Tree},
window,
};
use super::{common::*, menu_bar::*, menu_tree::*};
use crate::style::{Status, menu_bar::*};
#[cfg(feature = "debug_log")]
use log::{debug, trace, warn};
pub(super) struct MenuBarOverlay<'a, 'b, Message, Theme, Renderer>
where
Theme: Catalog,
Renderer: renderer::Renderer,
{
pub(super) menu_bar: &'b mut MenuBar<'a, Message, Theme, Renderer>,
pub(super) layout: Layout<'b>,
pub(super) translation: Vector,
pub(super) tree: &'b mut Tree,
}
impl<'b, Message, Theme, Renderer> MenuBarOverlay<'_, 'b, Message, Theme, Renderer>
where
Theme: Catalog,
Renderer: renderer::Renderer,
{
pub(super) fn overlay_element(self) -> overlay::Element<'b, Message, Theme, Renderer> {
overlay::Element::new(Box::new(self))
}
}
impl<Message, Theme, Renderer> overlay::Overlay<Message, Theme, Renderer>
for MenuBarOverlay<'_, '_, Message, Theme, Renderer>
where
Theme: Catalog,
Renderer: renderer::Renderer,
{
fn layout(&mut self, renderer: &Renderer, bounds: Size) -> Node {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::layout", "");
let translation = self.translation;
let bar_bounds = self.layout.bounds();
let slice_layout = self.layout.children().next().unwrap();
let root_bounds = slice_layout
.children()
.map(|l| l.bounds())
.collect::<Vec<_>>();
let bar = self.tree.state.downcast_ref::<MenuBarState>();
let MenuBarState {
global_state,
menu_state: bar_menu_state,
} = bar;
let slice = bar_menu_state.slice;
let bar_node = Node::with_children(bar_bounds.size(), [].into())
.move_to(bar_bounds.position() + translation);
let roots_node = Node::with_children(
Size::ZERO,
root_bounds
.iter()
.map(|r| Node::new(r.size()).move_to(r.position()))
.collect(),
)
.translate(translation);
if !global_state.open {
return Node::with_children(bounds, [bar_node, roots_node].into());
}
let Some(active) = bar_menu_state.active else {
return Node::with_children(bounds, [bar_node, roots_node].into());
};
let active_root = &mut self.menu_bar.roots[active];
let active_tree = &mut self.tree.children[active]; let parent_bounds = root_bounds[active - slice.start_index] + translation;
fn rec<Message, Theme: Catalog, Renderer: renderer::Renderer>(
renderer: &Renderer,
item: &mut Item<'_, Message, Theme, Renderer>,
tree: &mut Tree,
menu_nodes: &mut Vec<Node>,
parent_bounds: Rectangle,
parent_direction: (Direction, Direction),
viewport: &Rectangle,
) {
if let Some(menu) = item.menu.as_mut() {
let menu_tree = &mut tree.children[1];
let (menu_node, direction) = menu.layout(
menu_tree,
renderer,
&Limits::NONE,
parent_bounds,
parent_direction,
viewport,
);
menu_nodes.push(menu_node);
let menu_state = menu_tree.state.downcast_ref::<MenuState>();
if let Some(active) = menu_state.active {
let next_item = &mut menu.items[active];
let next_tree = &mut menu_tree.children[active];
let next_parent_bounds = {
let slice_node = &menu_nodes.last().unwrap().children()[0];
let active_in_slice = active - menu_state.slice.start_index;
let node = &slice_node.children()[active_in_slice];
node.bounds() + (slice_node.bounds().position() - Point::ORIGIN)
};
rec(
renderer,
next_item,
next_tree,
menu_nodes,
next_parent_bounds,
direction,
viewport,
);
}
}
}
let mut menu_nodes = vec![];
let parent_direction = {
let hcenter = bounds.width / 2.0;
let vcenter = bounds.height / 2.0;
let phcenter = parent_bounds.x + parent_bounds.width / 2.0;
let pvcenter = parent_bounds.y + parent_bounds.height / 2.0;
(
if phcenter < hcenter {
Direction::Positive
} else {
Direction::Negative
},
if pvcenter < vcenter {
Direction::Positive
} else {
Direction::Negative
},
)
};
rec(
renderer,
active_root,
active_tree,
&mut menu_nodes,
parent_bounds,
parent_direction,
&Rectangle::new(Point::ORIGIN, bounds),
);
Node::with_children(
bounds,
[
bar_node,
roots_node,
Node::with_children(Size::ZERO, menu_nodes),
]
.into(),
)
}
#[allow(unused_results)]
fn update(
&mut self,
event: &Event,
layout: Layout<'_>,
cursor: mouse::Cursor,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>,
) {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::update", "");
let bar = self.tree.state.downcast_mut::<MenuBarState>();
let MenuBarState {
global_state,
menu_state: bar_menu_state,
} = bar;
let slice = bar_menu_state.slice;
if !global_state.open {
return;
}
let Some(active) = bar_menu_state.active else {
return;
};
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 - slice.start_index)
.unwrap()
.bounds();
let menu_layouts_layout = lc.next().unwrap(); let mut menu_layouts = menu_layouts_layout.children();
let active_root = &mut self.menu_bar.roots[active];
let active_tree = &mut self.tree.children[active];
let mut prev_bounds_list = vec![bar_bounds];
match event {
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => {
global_state.pressed = true;
}
Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) => {
global_state.pressed = false;
shell.request_redraw();
}
Event::Window(window::Event::Resized { .. }) => {
bar.close(self.tree.children.as_mut_slice(), shell);
return;
}
_ => {}
}
#[rustfmt::skip]
fn rec<'a, 'b, Message, Theme: Catalog, Renderer: renderer::Renderer>(
global_state: &mut GlobalState,
global_parameters: &GlobalParameters<'a, Theme>,
tree: &mut Tree,
item: &mut Item<'a, Message, Theme, Renderer>,
event: &Event,
layout_iter: &mut impl Iterator<Item = Layout<'b>>,
cursor: mouse::Cursor,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>,
parent_bounds: Rectangle,
viewport: &Rectangle,
prev_bounds_list: &mut Vec<Rectangle>,
prev_active: &mut Index,
) -> RecEvent {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::update", "rec");
let Some(menu) = item.menu.as_mut() else {
return RecEvent::Close;
};
let menu_tree = &mut tree.children[1];
let Some(menu_layout) = layout_iter.next() else {
return RecEvent::Close;
};
let mut mc = menu_layout.children();
let slice_layout = mc.next().unwrap(); let items_bounds = mc.next().unwrap().bounds();
let background_bounds = pad_rectangle(items_bounds, menu.padding);
prev_bounds_list.push(background_bounds);
let menu_state = menu_tree.state.downcast_mut::<MenuState>();
let rec_event = if let Some(active) = menu_state.active {
let next_tree = &mut menu_tree.children[active];
let next_item = &mut menu.items[active];
let active_in_slice = active - menu_state.slice.start_index;
let next_parent_bounds = slice_layout
.children()
.nth(active_in_slice)
.expect(
"Index (in slice space) is not within the slice layout. \
This should not happen, please report this issue"
)
.bounds();
rec(
global_state,
global_parameters,
next_tree,
next_item,
event,
layout_iter,
cursor,
renderer,
clipboard,
shell,
next_parent_bounds,
viewport,
prev_bounds_list,
&mut menu_state.active,
)
} else if cursor == mouse::Cursor::Unavailable{
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::update", "rec | cursor is unavailable");
RecEvent::Event
} else {
RecEvent::Close
};
prev_bounds_list.pop();
#[cfg(feature = "debug_log")]
{
debug!(target:"menu::MenuBarOverlay::update", "");
debug!(target:"menu::MenuBarOverlay::update", "menu_state.active: {:?}", menu_state.active);
debug!(target:"menu::MenuBarOverlay::update", "menu_state.slice: {:?}", menu_state.slice);
debug!(target:"menu::MenuBarOverlay::update", "rec_event: {rec_event:?}");
debug!(target:"menu::MenuBarOverlay::update", "event: {event:?}");
debug!(target:"menu::MenuBarOverlay::update", "cursor: {cursor:?}");
debug!(target:"menu::MenuBarOverlay::update", "cursor is over background bounds: {:?}", cursor.is_over(background_bounds));
debug!(target:"menu::MenuBarOverlay::update", "shell.is_event_captured(): {:?}", shell.is_event_captured());
}
menu.update(
global_state,
global_parameters,
rec_event,
menu_tree,
event,
menu_layout,
cursor,
renderer,
clipboard,
shell,
viewport,
parent_bounds,
prev_bounds_list,
prev_active,
)
}
let re = rec(
global_state,
&self.menu_bar.global_parameters,
active_tree,
active_root,
event,
&mut menu_layouts,
cursor,
renderer,
clipboard,
shell,
parent_bounds,
&viewport,
&mut prev_bounds_list,
&mut bar_menu_state.active,
);
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::update", "re: {re:?}");
if matches!(
event,
Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left))
) && matches!(global_state.task(), Some(MenuBarTask::CloseOnClick))
{
bar.close(self.tree.children.as_mut_slice(), shell);
return;
}
match re {
RecEvent::Event => {
let redraw_event = Event::Window(window::Event::RedrawRequested(Instant::now()));
let mut fake_messages = vec![];
let mut fake_shell = Shell::new(&mut fake_messages);
let Self {
menu_bar,
layout,
tree,
..
} = self;
let draw_path = menu_bar.global_parameters.draw_path;
let cursor = match draw_path {
DrawPath::FakeHovering => {
let center = parent_bounds.center();
mouse::Cursor::Available(center - self.translation)
}
DrawPath::Backdrop => mouse::Cursor::Unavailable,
};
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::update", "calling update_items() on MenuBar");
let slice_layout = layout.children().next().unwrap();
itl_iter_slice!(
slice,
menu_bar.roots;iter_mut,
tree.children;iter_mut,
slice_layout.children()
)
.for_each(|((item, tree), layout)| {
item.update(
tree,
&redraw_event,
layout,
cursor,
renderer,
clipboard,
&mut fake_shell,
&viewport,
);
});
}
RecEvent::Close => {
if !cursor.is_over(bar_bounds) {
bar.close(self.tree.children.as_mut_slice(), shell);
}
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::update", "RecEvent::Close | MenuBar should process the event");
assert!(
!shell.is_event_captured(),
"MenuBarOverlay::update() | RecEvent::Close | Returning"
);
}
RecEvent::None => {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::update", "RecEvent::None | MenuBar should process the event");
assert!(
!shell.is_event_captured(),
"MenuBarOverlay::update() | RecEvent::None | Returning"
);
}
}
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::update", "returning | shell.is_layout_invalid(): {:?}", shell.is_layout_invalid());
}
fn mouse_interaction(
&self,
layout: Layout<'_>,
cursor: mouse::Cursor,
renderer: &Renderer,
) -> mouse::Interaction {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::mouse_interaction", "");
let bar = self.tree.state.downcast_ref::<MenuBarState>();
let MenuBarState {
global_state,
menu_state: bar_menu_state,
} = bar;
if !global_state.open {
return mouse::Interaction::default();
}
let Some(active) = bar_menu_state.active else {
return mouse::Interaction::default();
};
let mut lc = layout.children();
let _bar_bounds = lc.next().unwrap().bounds();
let _roots_layout = lc.next().unwrap();
let menu_layouts_layout = lc.next().unwrap(); let mut menu_layouts = menu_layouts_layout.children();
let active_root = &self.menu_bar.roots[active];
let active_tree = &self.tree.children[active];
fn rec<'a, 'b, Message, Theme: Catalog, Renderer: renderer::Renderer>(
tree: &Tree,
item: &Item<'a, Message, Theme, Renderer>,
layout_iter: &mut impl Iterator<Item = Layout<'b>>,
cursor: mouse::Cursor,
renderer: &Renderer,
) -> mouse::Interaction {
let Some(menu) = item.menu.as_ref() else {
return mouse::Interaction::default();
};
let menu_tree = &tree.children[1];
let Some(menu_layout) = layout_iter.next() else {
#[cfg(feature = "debug_log")]
warn!(target:"menu::MenuBarOverlay::mouse_interaction", "menu exists, but menu_layout is None");
return mouse::Interaction::default();
};
let menu_state = menu_tree.state.downcast_ref::<MenuState>();
let i = menu.mouse_interaction(menu_tree, menu_layout, cursor, renderer);
menu_state.active.map_or(i, |active| {
let next_tree = &menu_tree.children[active];
let next_item = &menu.items[active];
rec(next_tree, next_item, layout_iter, cursor, renderer).max(i)
})
}
rec(
active_tree,
active_root,
&mut menu_layouts,
cursor,
renderer,
)
}
fn operate(
&mut self,
layout: Layout<'_>,
renderer: &Renderer,
operation: &mut dyn Operation<()>,
) {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::operate", "");
let bar = self.tree.state.downcast_ref::<MenuBarState>();
let MenuBarState {
global_state,
menu_state: bar_menu_state,
} = bar;
if !global_state.open {
return;
}
let Some(active) = bar_menu_state.active else {
return;
};
let mut lc = layout.children();
let _bar_bounds = lc.next().unwrap().bounds();
let _roots_layout = lc.next().unwrap();
let menu_layouts_layout = lc.next().unwrap(); let mut menu_layouts = menu_layouts_layout.children();
let active_root = &mut self.menu_bar.roots[active];
let active_tree = &mut self.tree.children[active];
fn rec<'a, 'b, Message, Theme: Catalog, Renderer: renderer::Renderer>(
tree: &mut Tree,
item: &mut Item<'a, Message, Theme, Renderer>,
layout_iter: &mut impl Iterator<Item = Layout<'b>>,
renderer: &Renderer,
operation: &mut dyn Operation<()>,
) {
let Some(menu) = item.menu.as_mut() else {
return;
};
let menu_tree = &mut tree.children[1];
let Some(menu_layout) = layout_iter.next() else {
#[cfg(feature = "debug_log")]
warn!(target:"menu::MenuBarOverlay::operate", "menu exists, but menu_layout is None");
return;
};
menu.operate(menu_tree, menu_layout, renderer, operation);
operation.container(None, menu_layout.bounds());
operation.traverse(&mut |operation| {
menu.items
.iter_mut() .zip(menu_tree.children.iter_mut()) .for_each(|(child, state)| {
rec(state, child, layout_iter, renderer, operation);
});
});
}
rec(
active_tree,
active_root,
&mut menu_layouts,
renderer,
operation,
);
}
fn overlay<'c>(
&'c mut self,
layout: Layout<'c>,
renderer: &Renderer,
) -> Option<overlay::Element<'c, Message, Theme, Renderer>> {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::overlay", "");
let Tree {
state,
children: item_trees,
..
} = self.tree;
let bar = state.downcast_ref::<MenuBarState>();
let MenuBarState {
global_state,
menu_state: bar_menu_state,
} = bar;
let slice = bar_menu_state.slice;
if !global_state.open {
return None;
}
let active = bar_menu_state.active?;
let mut lc = layout.children();
let viewport = layout.bounds();
let _bar_bounds = lc.next()?.bounds();
let _roots_layout = lc.next()?;
let menu_layouts_layout = lc.next()?; let mut menu_layouts = menu_layouts_layout.children();
fn rec<'a, 'b, Message, Theme: Catalog, Renderer: renderer::Renderer>(
items: &'b mut [Item<'a, Message, Theme, Renderer>],
menu_tree: &'b mut Tree, menu_layouts: &mut impl Iterator<Item = Layout<'b>>, overlays: &mut Vec<overlay::Element<'b, Message, Theme, Renderer>>,
renderer: &Renderer,
viewport: &Rectangle,
) {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::overlay", "rec");
let menu_state = menu_tree.state.downcast_mut::<MenuState>();
let menu_layout = menu_layouts.next().unwrap(); let mut mlc = menu_layout.children();
let slice_layout = mlc.next().unwrap(); #[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::overlay", "rec | slice_layout.children : {}", slice_layout.children().count());
let slice = menu_state.slice;
if let Some(active) = menu_state.active {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::overlay", "rec | active");
let mut next = None;
for (i, ((item, item_tree), item_layout)) in itl_iter_slice_enum!(
slice,
items;iter_mut,
menu_tree.children;iter_mut,
slice_layout.children()
) {
#[cfg(feature = "debug_log")]
trace!(target:"menu::MenuBarOverlay::overlay", "rec | i: {i}");
let Item {
item: item_widget,
menu: item_menu,
..
} = item;
let item_widget_tree = if i == active {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::overlay", "rec | i == active {active}");
let [item_widget_tree, item_menu_tree] = item_tree.children.as_mut_slice()
else {
#[cfg(feature = "debug_log")]
warn!(target:"menu::MenuBarOverlay::overlay", "rec | menu_state.active is Some, but there's no state tree for it");
continue;
};
next = Some((item_menu.as_mut().unwrap(), item_menu_tree));
item_widget_tree
} else {
&mut item_tree.children.as_mut_slice()[0]
};
if let Some(overlay) = item_widget.as_widget_mut().overlay(
item_widget_tree,
item_layout,
renderer,
viewport,
Vector::ZERO,
) {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::overlay", "rec | active | i: {i} | Some overlay");
overlays.push(overlay);
}
}
if let Some((next_menu, next_menu_tree)) = next {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::overlay", "rec | next");
rec(
&mut next_menu.items,
next_menu_tree,
menu_layouts,
overlays,
renderer,
viewport,
);
}
} else {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::overlay", "rec | no active");
#[cfg(feature = "debug_log")]
let mut count = slice.start_index;
for ((item, item_tree), item_layout) in itl_iter_slice!(
slice,
items;iter_mut,
menu_tree.children;iter_mut,
slice_layout.children()
) {
#[cfg(feature = "debug_log")]
trace!(target:"menu::MenuBarOverlay::overlay", "rec | i: {count}");
let Item {
item: item_widget, ..
} = item;
if let Some(overlay) = item_widget.as_widget_mut().overlay(
&mut item_tree.children[0],
item_layout,
renderer,
viewport,
Vector::ZERO,
) {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::overlay", "rec | no active | i: {count} | Some overlay");
overlays.push(overlay);
}
#[cfg(feature = "debug_log")]
{
count += 1;
}
}
}
}
let mut overlays = vec![];
let mut next = None;
let slice_layout = self.layout.children().next()?;
for (i, ((item, item_tree), item_layout)) in itl_iter_slice_enum!(
slice,
self.menu_bar.roots;iter_mut,
item_trees;iter_mut,
slice_layout.children()
) {
#[cfg(feature = "debug_log")]
trace!(target:"menu::MenuBarOverlay::overlay", "root | i: {i}");
let Item {
item: item_widget,
menu: item_menu,
..
} = item;
let [item_widget_tree, item_menu_tree] = item_tree.children.as_mut_slice() else {
continue;
};
if i == active
&& let Some(menu) = item_menu.as_mut()
{
next = Some((menu, item_menu_tree));
}
if let Some(overlay) = item_widget.as_widget_mut().overlay(
item_widget_tree,
item_layout,
renderer,
&viewport,
self.translation,
) {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::overlay", "root | i: {i} | Some overlay");
overlays.push(overlay);
}
}
if let Some((next_menu, next_menu_tree)) = next {
rec(
&mut next_menu.items,
next_menu_tree,
&mut menu_layouts,
&mut overlays,
renderer,
&viewport,
);
}
if overlays.is_empty() {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::overlay", "return | None");
None
} else {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::overlay", "return | Some");
Some(overlay::Group::with_children(overlays).overlay())
}
}
fn draw(
&self,
renderer: &mut Renderer,
theme: &Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor: mouse::Cursor,
) {
#[cfg(feature = "debug_log")]
debug!(target:"menu::MenuBarOverlay::draw", "");
let bar = self.tree.state.downcast_ref::<MenuBarState>();
let MenuBarState {
global_state,
menu_state: bar_menu_state,
} = bar;
if !global_state.open {
return;
}
let Some(active) = bar_menu_state.active else {
return;
};
let viewport = layout.bounds();
let mut lc = layout.children();
let _bar_bounds = lc.next().unwrap().bounds();
let _roots_layout = lc.next().unwrap();
let menu_layouts_layout = lc.next().unwrap(); let mut menu_layouts = menu_layouts_layout.children();
let active_root = &self.menu_bar.roots[active];
let active_tree = &self.tree.children[active];
fn rec<'a, 'b, Message, Theme: Catalog, Renderer: renderer::Renderer>(
global_parameters: &GlobalParameters<'a, Theme>,
tree: &Tree,
item: &Item<'a, Message, Theme, Renderer>,
layout_iter: &mut impl Iterator<Item = Layout<'b>>,
cursor: mouse::Cursor,
renderer: &mut Renderer,
theme: &Theme,
style: &renderer::Style,
theme_style: &Style,
viewport: &Rectangle,
) {
let Some(menu) = item.menu.as_ref() else {
return;
};
let menu_tree = &tree.children[1];
let Some(menu_layout) = layout_iter.next() else {
#[cfg(feature = "debug_log")]
warn!(target:"menu::MenuBarOverlay::draw", "menu exists, but menu_layout is None");
return;
};
let menu_state = menu_tree.state.downcast_ref::<MenuState>();
menu.draw(
&global_parameters.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];
renderer.with_layer(*viewport, |r| {
rec(
global_parameters,
next_tree,
next_item,
layout_iter,
cursor,
r,
theme,
style,
theme_style,
viewport,
);
});
}
}
let theme_style = theme.style(&self.menu_bar.global_parameters.class, Status::Active);
rec(
&self.menu_bar.global_parameters,
active_tree,
active_root,
&mut menu_layouts,
cursor,
renderer,
theme,
style,
&theme_style,
&viewport,
);
}
}