refactor: remove menu tree changes
This commit is contained in:
parent
93e3d4fd42
commit
5a5670eda5
9 changed files with 221 additions and 197 deletions
|
|
@ -390,7 +390,7 @@ impl Core {
|
||||||
pub fn responsive_menu_bar<'a, Message: Clone + From<SurfaceMessage> + 'static>(
|
pub fn responsive_menu_bar<'a, Message: Clone + From<SurfaceMessage> + 'static>(
|
||||||
&self,
|
&self,
|
||||||
id: crate::widget::Id,
|
id: crate::widget::Id,
|
||||||
roots: Vec<Tree<'a, Message, Renderer>>,
|
roots: Vec<Tree<'a, Message>>,
|
||||||
) -> crate::Element<'a, Message> {
|
) -> crate::Element<'a, Message> {
|
||||||
let menu_bar_size = self.menu_bars.get(&id);
|
let menu_bar_size = self.menu_bars.get(&id);
|
||||||
if !menu_bar_size.is_some_and(|(limits, size)| {
|
if !menu_bar_size.is_some_and(|(limits, size)| {
|
||||||
|
|
@ -405,10 +405,12 @@ impl Core {
|
||||||
} else {
|
} else {
|
||||||
crate::Element::from(
|
crate::Element::from(
|
||||||
responsive_container::responsive_container(
|
responsive_container::responsive_container(
|
||||||
menu::bar(vec![menu::Tree::<'a, _, _>::with_children(
|
menu::bar(vec![menu::Tree::<_>::with_children(
|
||||||
button::icon(icon::from_name("open-menu-symbolic"))
|
Element::from(
|
||||||
.padding([4, 12])
|
button::icon(icon::from_name("open-menu-symbolic"))
|
||||||
.class(crate::theme::Button::MenuRoot),
|
.padding([4, 12])
|
||||||
|
.class(crate::theme::Button::MenuRoot),
|
||||||
|
),
|
||||||
roots,
|
roots,
|
||||||
)]),
|
)]),
|
||||||
id,
|
id,
|
||||||
|
|
|
||||||
|
|
@ -6,30 +6,24 @@
|
||||||
use crate::widget::menu::{
|
use crate::widget::menu::{
|
||||||
self, CloseCondition, ItemHeight, ItemWidth, MenuBarState, PathHighlight,
|
self, CloseCondition, ItemHeight, ItemWidth, MenuBarState, PathHighlight,
|
||||||
};
|
};
|
||||||
use crate::widget::ArcElementWrapper;
|
|
||||||
use derive_setters::Setters;
|
use derive_setters::Setters;
|
||||||
use iced::touch::Finger;
|
use iced::touch::Finger;
|
||||||
use iced::{Event, Vector};
|
use iced::{Event, Vector};
|
||||||
use iced_core::widget::{tree, Tree, Widget};
|
use iced_core::widget::{tree, Tree, Widget};
|
||||||
use iced_core::{event, mouse, touch, Length, Point, Size};
|
use iced_core::{event, mouse, touch, Length, Point, Size};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
|
|
||||||
use super::dropdown;
|
|
||||||
|
|
||||||
/// A context menu is a menu in a graphical user interface that appears upon user interaction, such as a right-click mouse operation.
|
/// A context menu is a menu in a graphical user interface that appears upon user interaction, such as a right-click mouse operation.
|
||||||
pub fn context_menu<Message: Clone + 'static>(
|
pub fn context_menu<'a, Message: 'a>(
|
||||||
content: impl Into<crate::Element<'static, Message>> + 'static,
|
content: impl Into<crate::Element<'a, Message>> + 'a,
|
||||||
// on_context: Message,
|
// on_context: Message,
|
||||||
context_menu: Option<Vec<menu::Tree<Message>>>,
|
context_menu: Option<Vec<menu::Tree<'a, Message>>>,
|
||||||
) -> ContextMenu<'static, Message> {
|
) -> ContextMenu<'a, Message> {
|
||||||
let mut this = ContextMenu {
|
let mut this = ContextMenu {
|
||||||
content: content.into(),
|
content: content.into(),
|
||||||
context_menu: context_menu.map(|menus| {
|
context_menu: context_menu.map(|menus| {
|
||||||
vec![menu::Tree::with_children(
|
vec![menu::Tree::with_children(
|
||||||
ArcElementWrapper(Arc::new(Mutex::new(crate::Element::from(
|
crate::widget::row::<'static, Message>(),
|
||||||
crate::widget::row::<'static, Message>(),
|
|
||||||
)))),
|
|
||||||
menus,
|
menus,
|
||||||
)]
|
)]
|
||||||
}),
|
}),
|
||||||
|
|
@ -49,10 +43,10 @@ pub struct ContextMenu<'a, Message> {
|
||||||
#[setters(skip)]
|
#[setters(skip)]
|
||||||
content: crate::Element<'a, Message>,
|
content: crate::Element<'a, Message>,
|
||||||
#[setters(skip)]
|
#[setters(skip)]
|
||||||
context_menu: Option<Vec<menu::Tree<Message>>>,
|
context_menu: Option<Vec<menu::Tree<'a, Message>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Message: Clone + 'static> Widget<Message, crate::Theme, crate::Renderer>
|
impl<'a, Message: Clone> Widget<Message, crate::Theme, crate::Renderer>
|
||||||
for ContextMenu<'a, Message>
|
for ContextMenu<'a, Message>
|
||||||
{
|
{
|
||||||
fn tag(&self) -> tree::Tag {
|
fn tag(&self) -> tree::Tag {
|
||||||
|
|
@ -64,7 +58,6 @@ impl<'a, Message: Clone + 'static> Widget<Message, crate::Theme, crate::Renderer
|
||||||
tree::State::new(LocalState {
|
tree::State::new(LocalState {
|
||||||
context_cursor: Point::default(),
|
context_cursor: Point::default(),
|
||||||
fingers_pressed: Default::default(),
|
fingers_pressed: Default::default(),
|
||||||
menu_state: Default::default(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,12 +75,9 @@ impl<'a, Message: Clone + 'static> Widget<Message, crate::Theme, crate::Renderer
|
||||||
.map(|root| {
|
.map(|root| {
|
||||||
let mut tree = Tree::empty();
|
let mut tree = Tree::empty();
|
||||||
let flat = root
|
let flat = root
|
||||||
.flatten()
|
.flattern()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|mt| {
|
.map(|mt| Tree::new(mt.item.as_widget()))
|
||||||
let guard = mt.item.0.lock().unwrap();
|
|
||||||
Tree::new(guard.as_widget())
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
tree.children = flat;
|
tree.children = flat;
|
||||||
tree
|
tree
|
||||||
|
|
@ -224,7 +214,7 @@ impl<'a, Message: Clone + 'static> Widget<Message, crate::Theme, crate::Renderer
|
||||||
translation: Vector,
|
translation: Vector,
|
||||||
) -> Option<iced_core::overlay::Element<'b, Message, crate::Theme, crate::Renderer>> {
|
) -> Option<iced_core::overlay::Element<'b, Message, crate::Theme, crate::Renderer>> {
|
||||||
let state = tree.state.downcast_ref::<LocalState>();
|
let state = tree.state.downcast_ref::<LocalState>();
|
||||||
let menu_state = state.menu_state.clone();
|
|
||||||
let Some(context_menu) = self.context_menu.as_mut() else {
|
let Some(context_menu) = self.context_menu.as_mut() else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
@ -239,8 +229,8 @@ impl<'a, Message: Clone + 'static> Widget<Message, crate::Theme, crate::Renderer
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
crate::widget::menu::Menu {
|
crate::widget::menu::Menu {
|
||||||
tree: menu_state,
|
tree: &mut tree.children[1],
|
||||||
menu_roots: std::borrow::Cow::Borrowed(context_menu),
|
menu_roots: context_menu,
|
||||||
bounds_expand: 16,
|
bounds_expand: 16,
|
||||||
menu_overlays_parent: true,
|
menu_overlays_parent: true,
|
||||||
close_condition: CloseCondition {
|
close_condition: CloseCondition {
|
||||||
|
|
@ -255,7 +245,7 @@ impl<'a, Message: Clone + 'static> Widget<Message, crate::Theme, crate::Renderer
|
||||||
cross_offset: 0,
|
cross_offset: 0,
|
||||||
root_bounds_list: vec![bounds],
|
root_bounds_list: vec![bounds],
|
||||||
path_highlight: Some(PathHighlight::MenuActive),
|
path_highlight: Some(PathHighlight::MenuActive),
|
||||||
style: std::borrow::Cow::Owned(crate::theme::menu_bar::MenuBarStyle::Default),
|
style: &crate::theme::menu_bar::MenuBarStyle::Default,
|
||||||
position: Point::new(translation.x, translation.y),
|
position: Point::new(translation.x, translation.y),
|
||||||
}
|
}
|
||||||
.overlay(),
|
.overlay(),
|
||||||
|
|
@ -275,10 +265,8 @@ impl<'a, Message: Clone + 'static> Widget<Message, crate::Theme, crate::Renderer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Message: Clone + 'static> From<ContextMenu<'static, Message>>
|
impl<'a, Message: Clone + 'a> From<ContextMenu<'a, Message>> for crate::Element<'a, Message> {
|
||||||
for crate::Element<'static, Message>
|
fn from(widget: ContextMenu<'a, Message>) -> Self {
|
||||||
{
|
|
||||||
fn from(widget: ContextMenu<'static, Message>) -> Self {
|
|
||||||
Self::new(widget)
|
Self::new(widget)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -297,5 +285,4 @@ fn touch_lifted(event: &Event) -> bool {
|
||||||
pub struct LocalState {
|
pub struct LocalState {
|
||||||
context_cursor: Point,
|
context_cursor: Point,
|
||||||
fingers_pressed: HashSet<Finger>,
|
fingers_pressed: HashSet<Finger>,
|
||||||
menu_state: dropdown::menu::State,
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,7 @@ pub struct State {
|
||||||
pub(crate) tree: Arc<Mutex<Tree>>,
|
pub(crate) tree: Arc<Mutex<Tree>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO use the Rc wrapper instead
|
||||||
// XXX The tree is only used on one thread, but this is needed to make a message
|
// XXX The tree is only used on one thread, but this is needed to make a message
|
||||||
unsafe impl Send for State {}
|
unsafe impl Send for State {}
|
||||||
unsafe impl Sync for State {}
|
unsafe impl Sync for State {}
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ where
|
||||||
.map(|root| {
|
.map(|root| {
|
||||||
let mut tree = Tree::empty();
|
let mut tree = Tree::empty();
|
||||||
let flat = root
|
let flat = root
|
||||||
.flatten()
|
.flattern()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|mt| Tree::new(mt.item.as_widget()))
|
.map(|mt| Tree::new(mt.item.as_widget()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
@ -110,7 +110,7 @@ pub(crate) fn menu_roots_diff<'a, Message, Renderer>(
|
||||||
.zip(menu_roots.iter())
|
.zip(menu_roots.iter())
|
||||||
.for_each(|(t, root)| {
|
.for_each(|(t, root)| {
|
||||||
let mut flat = root
|
let mut flat = root
|
||||||
.flatten()
|
.flattern()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|mt| {
|
.map(|mt| {
|
||||||
let widget = mt.item.as_widget();
|
let widget = mt.item.as_widget();
|
||||||
|
|
@ -129,7 +129,7 @@ pub(crate) fn menu_roots_diff<'a, Message, Renderer>(
|
||||||
let extended = menu_roots[tree.children.len()..].iter().map(|root| {
|
let extended = menu_roots[tree.children.len()..].iter().map(|root| {
|
||||||
let mut tree = Tree::empty();
|
let mut tree = Tree::empty();
|
||||||
let flat = root
|
let flat = root
|
||||||
.flatten()
|
.flattern()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|mt| Tree::new(mt.item.as_widget()))
|
.map(|mt| Tree::new(mt.item.as_widget()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,8 @@
|
||||||
// From iced_aw, license MIT
|
// From iced_aw, license MIT
|
||||||
|
|
||||||
//! Menu tree overlay
|
//! Menu tree overlay
|
||||||
use std::{
|
|
||||||
borrow::Cow,
|
|
||||||
sync::{Arc, Mutex},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{menu_bar::MenuBarState, menu_tree::MenuTree};
|
use super::{menu_bar::MenuBarState, menu_tree::MenuTree};
|
||||||
use crate::{style::menu_bar::StyleSheet, widget::dropdown};
|
use crate::style::menu_bar::StyleSheet;
|
||||||
|
|
||||||
use iced_core::{Border, Shadow};
|
use iced_core::{Border, Shadow};
|
||||||
use iced_widget::core::{
|
use iced_widget::core::{
|
||||||
|
|
@ -245,7 +240,7 @@ struct MenuBounds {
|
||||||
impl MenuBounds {
|
impl MenuBounds {
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn new<Message, Renderer>(
|
fn new<Message, Renderer>(
|
||||||
menu_tree: &MenuTree<Message>,
|
menu_tree: &MenuTree<'_, Message, Renderer>,
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
item_width: ItemWidth,
|
item_width: ItemWidth,
|
||||||
item_height: ItemHeight,
|
item_height: ItemHeight,
|
||||||
|
|
@ -305,7 +300,7 @@ impl MenuState {
|
||||||
overlay_offset: Vector,
|
overlay_offset: Vector,
|
||||||
slice: MenuSlice,
|
slice: MenuSlice,
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
menu_tree: &MenuTree<Message>,
|
menu_tree: &MenuTree<'_, Message, Renderer>,
|
||||||
tree: &mut [Tree],
|
tree: &mut [Tree],
|
||||||
) -> Node
|
) -> Node
|
||||||
where
|
where
|
||||||
|
|
@ -359,7 +354,7 @@ impl MenuState {
|
||||||
overlay_offset: Vector,
|
overlay_offset: Vector,
|
||||||
index: usize,
|
index: usize,
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
menu_tree: &MenuTree<Message>,
|
menu_tree: &MenuTree<'_, Message, Renderer>,
|
||||||
tree: &mut Tree,
|
tree: &mut Tree,
|
||||||
) -> Node
|
) -> Node
|
||||||
where
|
where
|
||||||
|
|
@ -432,9 +427,12 @@ impl MenuState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct Menu<'b, Message: std::clone::Clone> {
|
pub(crate) struct Menu<'a, 'b, Message, Renderer>
|
||||||
pub(crate) tree: dropdown::menu::State,
|
where
|
||||||
pub(crate) menu_roots: Cow<'b, Vec<MenuTree<Message>>>,
|
Renderer: renderer::Renderer,
|
||||||
|
{
|
||||||
|
pub(crate) tree: &'b mut Tree,
|
||||||
|
pub(crate) menu_roots: &'b mut Vec<MenuTree<'a, Message, Renderer>>,
|
||||||
pub(crate) bounds_expand: u16,
|
pub(crate) bounds_expand: u16,
|
||||||
/// Allows menu overlay items to overlap the parent
|
/// Allows menu overlay items to overlap the parent
|
||||||
pub(crate) menu_overlays_parent: bool,
|
pub(crate) menu_overlays_parent: bool,
|
||||||
|
|
@ -446,10 +444,10 @@ pub(crate) struct Menu<'b, Message: std::clone::Clone> {
|
||||||
pub(crate) cross_offset: i32,
|
pub(crate) cross_offset: i32,
|
||||||
pub(crate) root_bounds_list: Vec<Rectangle>,
|
pub(crate) root_bounds_list: Vec<Rectangle>,
|
||||||
pub(crate) path_highlight: Option<PathHighlight>,
|
pub(crate) path_highlight: Option<PathHighlight>,
|
||||||
pub(crate) style: Cow<'b, <crate::Theme as StyleSheet>::Style>,
|
pub(crate) style: &'b <crate::Theme as StyleSheet>::Style,
|
||||||
pub(crate) position: Point,
|
pub(crate) position: Point,
|
||||||
}
|
}
|
||||||
impl<'b, Message: Clone + 'static, Renderer> Menu<'b, Message>
|
impl<'a, 'b, Message, Renderer> Menu<'a, 'b, Message, Renderer>
|
||||||
where
|
where
|
||||||
Renderer: renderer::Renderer,
|
Renderer: renderer::Renderer,
|
||||||
{
|
{
|
||||||
|
|
@ -753,7 +751,7 @@ fn pad_rectangle(rect: Rectangle, padding: Padding) -> Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn init_root_menu<Message, Renderer>(
|
pub(super) fn init_root_menu<Message, Renderer>(
|
||||||
menu: &mut Menu<'_, Message>,
|
menu: &mut Menu<'_, '_, Message, Renderer>,
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
shell: &mut Shell<'_, Message>,
|
shell: &mut Shell<'_, Message>,
|
||||||
overlay_cursor: Point,
|
overlay_cursor: Point,
|
||||||
|
|
@ -831,7 +829,7 @@ pub(super) fn init_root_menu<Message, Renderer>(
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn process_menu_events<'b, Message, Renderer>(
|
fn process_menu_events<'b, Message, Renderer>(
|
||||||
tree: &'b mut Tree,
|
tree: &'b mut Tree,
|
||||||
menu_roots: &'b mut [MenuTree<Message>],
|
menu_roots: &'b mut [MenuTree<'_, Message, Renderer>],
|
||||||
event: event::Event,
|
event: event::Event,
|
||||||
view_cursor: Cursor,
|
view_cursor: Cursor,
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
|
|
@ -889,7 +887,7 @@ where
|
||||||
|
|
||||||
#[allow(unused_results)]
|
#[allow(unused_results)]
|
||||||
fn process_overlay_events<Message, Renderer>(
|
fn process_overlay_events<Message, Renderer>(
|
||||||
menu: &mut Menu<'_, Message>,
|
menu: &mut Menu<'_, '_, Message, Renderer>,
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
viewport_size: Size,
|
viewport_size: Size,
|
||||||
overlay_offset: Vector,
|
overlay_offset: Vector,
|
||||||
|
|
@ -899,7 +897,6 @@ fn process_overlay_events<Message, Renderer>(
|
||||||
) -> event::Status
|
) -> event::Status
|
||||||
where
|
where
|
||||||
Renderer: renderer::Renderer,
|
Renderer: renderer::Renderer,
|
||||||
Message: std::clone::Clone,
|
|
||||||
{
|
{
|
||||||
use event::Status::{Captured, Ignored};
|
use event::Status::{Captured, Ignored};
|
||||||
/*
|
/*
|
||||||
|
|
@ -1080,13 +1077,16 @@ where
|
||||||
Captured
|
Captured
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_scroll_events<Message: Clone>(
|
fn process_scroll_events<Message, Renderer>(
|
||||||
menu: &mut Menu<'_, Message>,
|
menu: &mut Menu<'_, '_, Message, Renderer>,
|
||||||
delta: mouse::ScrollDelta,
|
delta: mouse::ScrollDelta,
|
||||||
overlay_cursor: Point,
|
overlay_cursor: Point,
|
||||||
viewport_size: Size,
|
viewport_size: Size,
|
||||||
overlay_offset: Vector,
|
overlay_offset: Vector,
|
||||||
) -> event::Status {
|
) -> event::Status
|
||||||
|
where
|
||||||
|
Renderer: renderer::Renderer,
|
||||||
|
{
|
||||||
use event::Status::{Captured, Ignored};
|
use event::Status::{Captured, Ignored};
|
||||||
use mouse::ScrollDelta;
|
use mouse::ScrollDelta;
|
||||||
|
|
||||||
|
|
@ -1155,13 +1155,16 @@ fn process_scroll_events<Message: Clone>(
|
||||||
|
|
||||||
#[allow(clippy::pedantic)]
|
#[allow(clippy::pedantic)]
|
||||||
/// Returns (children_size, child_positions, child_sizes)
|
/// Returns (children_size, child_positions, child_sizes)
|
||||||
fn get_children_layout<Message>(
|
fn get_children_layout<Message, Renderer>(
|
||||||
menu_tree: &MenuTree<Message>,
|
menu_tree: &MenuTree<'_, Message, Renderer>,
|
||||||
renderer: &crate::Renderer,
|
renderer: &Renderer,
|
||||||
item_width: ItemWidth,
|
item_width: ItemWidth,
|
||||||
item_height: ItemHeight,
|
item_height: ItemHeight,
|
||||||
tree: &mut [Tree],
|
tree: &mut [Tree],
|
||||||
) -> (Size, Vec<f32>, Vec<Size>) {
|
) -> (Size, Vec<f32>, Vec<Size>)
|
||||||
|
where
|
||||||
|
Renderer: renderer::Renderer,
|
||||||
|
{
|
||||||
let width = match item_width {
|
let width = match item_width {
|
||||||
ItemWidth::Uniform(u) => f32::from(u),
|
ItemWidth::Uniform(u) => f32::from(u),
|
||||||
ItemWidth::Static(s) => f32::from(menu_tree.width.unwrap_or(s)),
|
ItemWidth::Static(s) => f32::from(menu_tree.width.unwrap_or(s)),
|
||||||
|
|
@ -1181,8 +1184,7 @@ fn get_children_layout<Message>(
|
||||||
.children
|
.children
|
||||||
.iter()
|
.iter()
|
||||||
.map(|mt| {
|
.map(|mt| {
|
||||||
let guard = mt.item.0.lock().unwrap();
|
let w = mt.item.as_widget();
|
||||||
let w = guard.as_widget();
|
|
||||||
match w.size().height {
|
match w.size().height {
|
||||||
Length::Fixed(f) => Size::new(width, f),
|
Length::Fixed(f) => Size::new(width, f),
|
||||||
Length::Shrink => {
|
Length::Shrink => {
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,13 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
|
|
||||||
use iced_widget::core::{renderer, Element};
|
use iced_widget::core::{renderer, Element};
|
||||||
|
|
||||||
use crate::iced_core::{Alignment, Length};
|
use crate::iced_core::{Alignment, Length};
|
||||||
|
use crate::widget::icon;
|
||||||
use crate::widget::menu::action::MenuAction;
|
use crate::widget::menu::action::MenuAction;
|
||||||
use crate::widget::menu::key_bind::KeyBind;
|
use crate::widget::menu::key_bind::KeyBind;
|
||||||
use crate::widget::{icon, ArcElementWrapper};
|
|
||||||
use crate::{theme, widget};
|
use crate::{theme, widget};
|
||||||
|
|
||||||
/// Nested menu is essentially a tree of items, a menu is a collection of items
|
/// Nested menu is essentially a tree of items, a menu is a collection of items
|
||||||
|
|
@ -24,27 +23,27 @@ use crate::{theme, widget};
|
||||||
/// but there's no need to explicitly distinguish them here, if a menu tree
|
/// but there's no need to explicitly distinguish them here, if a menu tree
|
||||||
/// has children, it's a menu, otherwise it's an item
|
/// has children, it's a menu, otherwise it's an item
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
#[derive(Clone)]
|
pub struct MenuTree<'a, Message, Renderer = crate::Renderer> {
|
||||||
|
|
||||||
pub struct MenuTree<Message> {
|
|
||||||
/// The menu tree will be flatten into a vector to build a linear widget tree,
|
/// The menu tree will be flatten into a vector to build a linear widget tree,
|
||||||
/// the `index` field is the index of the item in that vector
|
/// the `index` field is the index of the item in that vector
|
||||||
pub(crate) index: usize,
|
pub(crate) index: usize,
|
||||||
|
|
||||||
// TODO needs to be wrapped in Arc<Mutex kinda like in cosmic-files. Check the widget there for details
|
|
||||||
/// The item of the menu tree
|
/// The item of the menu tree
|
||||||
pub(crate) item: ArcElementWrapper<Message>,
|
pub(crate) item: Element<'a, Message, crate::Theme, Renderer>,
|
||||||
/// The children of the menu tree
|
/// The children of the menu tree
|
||||||
pub(crate) children: Vec<MenuTree<Message>>,
|
pub(crate) children: Vec<MenuTree<'a, Message, Renderer>>,
|
||||||
/// The width of the menu tree
|
/// The width of the menu tree
|
||||||
pub(crate) width: Option<u16>,
|
pub(crate) width: Option<u16>,
|
||||||
/// The height of the menu tree
|
/// The height of the menu tree
|
||||||
pub(crate) height: Option<u16>,
|
pub(crate) height: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Message: Clone + 'static> MenuTree<Message> {
|
impl<'a, Message, Renderer> MenuTree<'a, Message, Renderer>
|
||||||
|
where
|
||||||
|
Renderer: renderer::Renderer,
|
||||||
|
{
|
||||||
/// Create a new menu tree from a widget
|
/// Create a new menu tree from a widget
|
||||||
pub fn new(item: impl Into<ArcElementWrapper<Message>>) -> Self {
|
pub fn new(item: impl Into<Element<'a, Message, crate::Theme, Renderer>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
index: 0,
|
index: 0,
|
||||||
item: item.into(),
|
item: item.into(),
|
||||||
|
|
@ -56,8 +55,8 @@ impl<Message: Clone + 'static> MenuTree<Message> {
|
||||||
|
|
||||||
/// Create a menu tree from a widget and a vector of sub trees
|
/// Create a menu tree from a widget and a vector of sub trees
|
||||||
pub fn with_children(
|
pub fn with_children(
|
||||||
item: impl Into<ArcElementWrapper<Message>>,
|
item: impl Into<Element<'a, Message, crate::Theme, Renderer>>,
|
||||||
children: Vec<impl Into<MenuTree<Message>>>,
|
children: Vec<impl Into<MenuTree<'a, Message, Renderer>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
index: 0,
|
index: 0,
|
||||||
|
|
@ -93,7 +92,7 @@ impl<Message: Clone + 'static> MenuTree<Message> {
|
||||||
/// Set the index of each item
|
/// Set the index of each item
|
||||||
pub(crate) fn set_index(&mut self) {
|
pub(crate) fn set_index(&mut self) {
|
||||||
/// inner counting function.
|
/// inner counting function.
|
||||||
fn rec<Message: Clone + 'static>(mt: &mut MenuTree<Message>, count: &mut usize) {
|
fn rec<Message, Renderer>(mt: &mut MenuTree<'_, Message, Renderer>, count: &mut usize) {
|
||||||
// keep items under the same menu line up
|
// keep items under the same menu line up
|
||||||
mt.children.iter_mut().for_each(|c| {
|
mt.children.iter_mut().for_each(|c| {
|
||||||
c.index = *count;
|
c.index = *count;
|
||||||
|
|
@ -110,32 +109,36 @@ impl<Message: Clone + 'static> MenuTree<Message> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flatten the menu tree
|
/// Flatten the menu tree
|
||||||
pub(crate) fn flatten(&self) -> Vec<Self> {
|
pub(crate) fn flattern(&'a self) -> Vec<&Self> {
|
||||||
/// Inner flattening function
|
/// Inner flattening function
|
||||||
fn rec<Message: Clone + 'static>(
|
fn rec<'a, Message, Renderer>(
|
||||||
mt: &MenuTree<Message>,
|
mt: &'a MenuTree<'a, Message, Renderer>,
|
||||||
flat: &mut Vec<MenuTree<Message>>,
|
flat: &mut Vec<&MenuTree<'a, Message, Renderer>>,
|
||||||
) {
|
) {
|
||||||
mt.children.clone().into_iter().for_each(|c| {
|
mt.children.iter().for_each(|c| {
|
||||||
flat.push(c);
|
flat.push(c);
|
||||||
});
|
});
|
||||||
|
|
||||||
mt.children.iter().for_each(|c| {
|
mt.children.iter().for_each(|c| {
|
||||||
rec(&c, flat);
|
rec(c, flat);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut flat = Vec::new();
|
let mut flat = Vec::new();
|
||||||
flat.push(self.clone());
|
flat.push(self);
|
||||||
rec(self, &mut flat);
|
rec(self, &mut flat);
|
||||||
|
|
||||||
flat
|
flat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Message: Clone + 'static> From<crate::Element<'static, Message>> for MenuTree<Message> {
|
impl<'a, Message, Renderer> From<Element<'a, Message, crate::Theme, Renderer>>
|
||||||
fn from(value: crate::Element<'static, Message>) -> Self {
|
for MenuTree<'a, Message, Renderer>
|
||||||
Self::new(ArcElementWrapper(Arc::new(Mutex::new(value))))
|
where
|
||||||
|
Renderer: renderer::Renderer,
|
||||||
|
{
|
||||||
|
fn from(value: Element<'a, Message, crate::Theme, Renderer>) -> Self {
|
||||||
|
Self::new(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -154,7 +157,6 @@ pub fn menu_button<'a, Message: 'a>(
|
||||||
.class(theme::Button::MenuItem)
|
.class(theme::Button::MenuItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
/// Represents a menu item that performs an action when selected or a separator between menu items.
|
/// Represents a menu item that performs an action when selected or a separator between menu items.
|
||||||
///
|
///
|
||||||
/// - `Action` - Represents a menu item that performs an action when selected.
|
/// - `Action` - Represents a menu item that performs an action when selected.
|
||||||
|
|
@ -211,13 +213,18 @@ where
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// - A vector of `MenuTree`.
|
/// - A vector of `MenuTree`.
|
||||||
pub fn menu_items<
|
pub fn menu_items<
|
||||||
|
'a,
|
||||||
A: MenuAction<Message = Message>,
|
A: MenuAction<Message = Message>,
|
||||||
L: Into<Cow<'static, str>> + 'static,
|
L: Into<Cow<'static, str>> + 'static,
|
||||||
Message: 'static + std::clone::Clone,
|
Message: 'a,
|
||||||
|
Renderer: renderer::Renderer + 'a,
|
||||||
>(
|
>(
|
||||||
key_binds: &HashMap<KeyBind, A>,
|
key_binds: &HashMap<KeyBind, A>,
|
||||||
children: Vec<MenuItem<A, L>>,
|
children: Vec<MenuItem<A, L>>,
|
||||||
) -> Vec<MenuTree<Message>> {
|
) -> Vec<MenuTree<'a, Message, Renderer>>
|
||||||
|
where
|
||||||
|
Element<'a, Message, crate::Theme, Renderer>: From<widget::button::Button<'a, Message>>,
|
||||||
|
{
|
||||||
fn find_key<A: MenuAction>(action: &A, key_binds: &HashMap<KeyBind, A>) -> String {
|
fn find_key<A: MenuAction>(action: &A, key_binds: &HashMap<KeyBind, A>) -> String {
|
||||||
for (key_bind, key_action) in key_binds {
|
for (key_bind, key_action) in key_binds {
|
||||||
if action == key_action {
|
if action == key_action {
|
||||||
|
|
@ -252,7 +259,7 @@ pub fn menu_items<
|
||||||
|
|
||||||
let menu_button = menu_button(items).on_press(action.message());
|
let menu_button = menu_button(items).on_press(action.message());
|
||||||
|
|
||||||
trees.push(MenuTree::<Message>::from(Element::from(menu_button)));
|
trees.push(MenuTree::<Message, Renderer>::new(menu_button));
|
||||||
}
|
}
|
||||||
MenuItem::ButtonDisabled(label, icon, action) => {
|
MenuItem::ButtonDisabled(label, icon, action) => {
|
||||||
let key = find_key(&action, key_binds);
|
let key = find_key(&action, key_binds);
|
||||||
|
|
@ -270,7 +277,7 @@ pub fn menu_items<
|
||||||
|
|
||||||
let menu_button = menu_button(items);
|
let menu_button = menu_button(items);
|
||||||
|
|
||||||
trees.push(MenuTree::<Message>::from(Element::from(menu_button)));
|
trees.push(MenuTree::<Message, Renderer>::new(menu_button));
|
||||||
}
|
}
|
||||||
MenuItem::CheckBox(label, icon, value, action) => {
|
MenuItem::CheckBox(label, icon, value, action) => {
|
||||||
let key = find_key(&action, key_binds);
|
let key = find_key(&action, key_binds);
|
||||||
|
|
@ -300,40 +307,36 @@ pub fn menu_items<
|
||||||
items.insert(2, widget::icon::icon(icon).size(14).into());
|
items.insert(2, widget::icon::icon(icon).size(14).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
trees.push(MenuTree::from(Element::from(
|
trees.push(MenuTree::new(menu_button(items).on_press(action.message())));
|
||||||
menu_button(items).on_press(action.message()),
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
MenuItem::Folder(label, children) => {
|
MenuItem::Folder(label, children) => {
|
||||||
trees.push(MenuTree::<Message>::with_children(
|
trees.push(MenuTree::<Message, Renderer>::with_children(
|
||||||
ArcElementWrapper(Arc::new(Mutex::new(crate::Element::from(
|
menu_button(vec![
|
||||||
menu_button::<'static, _>(vec![
|
widget::text(label).into(),
|
||||||
widget::text(label).into(),
|
widget::horizontal_space().into(),
|
||||||
widget::horizontal_space().into(),
|
widget::icon::from_name("pan-end-symbolic")
|
||||||
widget::icon::from_name("pan-end-symbolic")
|
.size(16)
|
||||||
.size(16)
|
.icon()
|
||||||
.icon()
|
.into(),
|
||||||
.into(),
|
])
|
||||||
])
|
.class(
|
||||||
.class(
|
// Menu folders have no on_press so they take on the disabled style by default
|
||||||
// Menu folders have no on_press so they take on the disabled style by default
|
if children.is_empty() {
|
||||||
if children.is_empty() {
|
// This will make the folder use the disabled style if it has no children
|
||||||
// This will make the folder use the disabled style if it has no children
|
theme::Button::MenuItem
|
||||||
theme::Button::MenuItem
|
} else {
|
||||||
} else {
|
// This will make the folder use the enabled style if it has children
|
||||||
// This will make the folder use the enabled style if it has children
|
theme::Button::MenuFolder
|
||||||
theme::Button::MenuFolder
|
},
|
||||||
},
|
),
|
||||||
),
|
|
||||||
)))),
|
|
||||||
menu_items(key_binds, children),
|
menu_items(key_binds, children),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
MenuItem::Divider => {
|
MenuItem::Divider => {
|
||||||
if i != size - 1 {
|
if i != size - 1 {
|
||||||
trees.push(MenuTree::<Message>::from(Element::from(
|
trees.push(MenuTree::<Message, Renderer>::new(
|
||||||
widget::divider::horizontal::light(),
|
widget::divider::horizontal::light(),
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ impl<'a, Message: Clone + 'static> NavBar<'a, Message> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn context_menu(mut self, context_menu: Option<Vec<menu::Tree<Message>>>) -> Self {
|
pub fn context_menu(mut self, context_menu: Option<Vec<menu::Tree<'a, Message>>>) -> Self {
|
||||||
self.segmented_button = self.segmented_button.context_menu(context_menu);
|
self.segmented_button = self.segmented_button.context_menu(context_menu);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use crate::widget::menu::{
|
||||||
self, menu_roots_children, menu_roots_diff, CloseCondition, ItemHeight, ItemWidth,
|
self, menu_roots_children, menu_roots_diff, CloseCondition, ItemHeight, ItemWidth,
|
||||||
MenuBarState, PathHighlight,
|
MenuBarState, PathHighlight,
|
||||||
};
|
};
|
||||||
use crate::widget::{dropdown, icon, Icon};
|
use crate::widget::{icon, Icon};
|
||||||
use crate::{Element, Renderer};
|
use crate::{Element, Renderer};
|
||||||
use derive_setters::Setters;
|
use derive_setters::Setters;
|
||||||
use iced::clipboard::dnd::{self, DndAction, DndDestinationRectangle, DndEvent, OfferEvent};
|
use iced::clipboard::dnd::{self, DndAction, DndDestinationRectangle, DndEvent, OfferEvent};
|
||||||
|
|
@ -127,7 +127,7 @@ where
|
||||||
pub(super) style: Style,
|
pub(super) style: Style,
|
||||||
/// The context menu to display when a context is activated
|
/// The context menu to display when a context is activated
|
||||||
#[setters(skip)]
|
#[setters(skip)]
|
||||||
pub(super) context_menu: Option<Vec<menu::Tree<Message>>>,
|
pub(super) context_menu: Option<Vec<menu::Tree<'a, Message, crate::Renderer>>>,
|
||||||
/// Emits the ID of the item that was activated.
|
/// Emits the ID of the item that was activated.
|
||||||
#[setters(skip)]
|
#[setters(skip)]
|
||||||
pub(super) on_activate: Option<Box<dyn Fn(Entity) -> Message + 'static>>,
|
pub(super) on_activate: Option<Box<dyn Fn(Entity) -> Message + 'static>>,
|
||||||
|
|
@ -197,13 +197,13 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn context_menu(mut self, context_menu: Option<Vec<menu::Tree<Message>>>) -> Self
|
pub fn context_menu(mut self, context_menu: Option<Vec<menu::Tree<'a, Message>>>) -> Self
|
||||||
where
|
where
|
||||||
Message: Clone + 'static,
|
Message: 'static,
|
||||||
{
|
{
|
||||||
self.context_menu = context_menu.map(|menus| {
|
self.context_menu = context_menu.map(|menus| {
|
||||||
vec![menu::Tree::with_children(
|
vec![menu::Tree::with_children(
|
||||||
crate::Element::from(crate::widget::row::<'static, Message>()),
|
crate::widget::row::<'static, Message>(),
|
||||||
menus,
|
menus,
|
||||||
)]
|
)]
|
||||||
});
|
});
|
||||||
|
|
@ -593,7 +593,6 @@ where
|
||||||
dnd_state: Default::default(),
|
dnd_state: Default::default(),
|
||||||
fingers_pressed: Default::default(),
|
fingers_pressed: Default::default(),
|
||||||
pressed_item: None,
|
pressed_item: None,
|
||||||
menu_state: Default::default(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1553,7 +1552,7 @@ where
|
||||||
translation: Vector,
|
translation: Vector,
|
||||||
) -> Option<iced_core::overlay::Element<'b, Message, crate::Theme, Renderer>> {
|
) -> Option<iced_core::overlay::Element<'b, Message, crate::Theme, Renderer>> {
|
||||||
let state = tree.state.downcast_ref::<LocalState>();
|
let state = tree.state.downcast_ref::<LocalState>();
|
||||||
let menu_state = state.menu_state.clone();
|
|
||||||
let Some(entity) = state.show_context else {
|
let Some(entity) = state.show_context else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
@ -1581,8 +1580,8 @@ where
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
crate::widget::menu::Menu {
|
crate::widget::menu::Menu {
|
||||||
tree: menu_state,
|
tree: &mut tree.children[0],
|
||||||
menu_roots: Cow::Borrowed(context_menu),
|
menu_roots: context_menu,
|
||||||
bounds_expand: 16,
|
bounds_expand: 16,
|
||||||
menu_overlays_parent: true,
|
menu_overlays_parent: true,
|
||||||
close_condition: CloseCondition {
|
close_condition: CloseCondition {
|
||||||
|
|
@ -1597,7 +1596,7 @@ where
|
||||||
cross_offset: 0,
|
cross_offset: 0,
|
||||||
root_bounds_list: vec![bounds],
|
root_bounds_list: vec![bounds],
|
||||||
path_highlight: Some(PathHighlight::MenuActive),
|
path_highlight: Some(PathHighlight::MenuActive),
|
||||||
style: Cow::Owned(crate::theme::menu_bar::MenuBarStyle::Default),
|
style: &crate::theme::menu_bar::MenuBarStyle::Default,
|
||||||
position: Point::new(translation.x, translation.y),
|
position: Point::new(translation.x, translation.y),
|
||||||
}
|
}
|
||||||
.overlay(),
|
.overlay(),
|
||||||
|
|
@ -1684,8 +1683,6 @@ pub struct LocalState {
|
||||||
fingers_pressed: HashSet<Finger>,
|
fingers_pressed: HashSet<Finger>,
|
||||||
/// The currently pressed item
|
/// The currently pressed item
|
||||||
pressed_item: Option<Item>,
|
pressed_item: Option<Item>,
|
||||||
/// Menu state
|
|
||||||
pub(crate) menu_state: dropdown::menu::State,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq)]
|
#[derive(Debug, Default, PartialEq)]
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,55 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
|
rc::Rc,
|
||||||
|
thread::{self, ThreadId},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::Element;
|
use crate::Element;
|
||||||
use iced::{event, Length, Rectangle, Size};
|
use iced::{event, Length, Rectangle, Size};
|
||||||
use iced_core::{id::Id, widget, widget::tree, Widget};
|
use iced_core::{id::Id, widget, widget::tree, Widget};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ArcElementWrapper<M>(pub Arc<Mutex<Element<'static, M>>>);
|
pub struct RcElementWrapper<M> {
|
||||||
|
pub(crate) element: Rc<RefCell<Element<'static, M>>>,
|
||||||
|
pub(crate) thread_id: ThreadId,
|
||||||
|
}
|
||||||
|
|
||||||
impl<M> Widget<M, crate::Theme, crate::Renderer> for ArcElementWrapper<M> {
|
impl<M> RcElementWrapper<M> {
|
||||||
|
pub fn new(element: Element<'static, M>) -> Self {
|
||||||
|
Self {
|
||||||
|
element: Rc::new(RefCell::new(element)),
|
||||||
|
thread_id: thread::current().id(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_element<T>(&self, f: impl FnOnce(&Element<'static, M>) -> T) -> T {
|
||||||
|
assert_eq!(self.thread_id, thread::current().id());
|
||||||
|
let my_ref: &Element<'static, M> = &RefCell::borrow(self.element.as_ref());
|
||||||
|
f(my_ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_element_mut<T>(&self, f: impl FnOnce(&mut Element<'static, M>) -> T) -> T {
|
||||||
|
assert_eq!(self.thread_id, thread::current().id());
|
||||||
|
let my_refmut: &mut Element<'static, M> = &mut RefCell::borrow_mut(self.element.as_ref());
|
||||||
|
f(my_refmut)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) unsafe fn as_ptr(&self) -> *mut Element<'static, M> {
|
||||||
|
assert_eq!(self.thread_id, thread::current().id());
|
||||||
|
RefCell::as_ptr(self.element.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<M: 'static> Send for RcElementWrapper<M> {}
|
||||||
|
unsafe impl<M: 'static> Sync for RcElementWrapper<M> {}
|
||||||
|
|
||||||
|
impl<M> Widget<M, crate::Theme, crate::Renderer> for RcElementWrapper<M> {
|
||||||
fn size(&self) -> Size<Length> {
|
fn size(&self) -> Size<Length> {
|
||||||
self.0.lock().unwrap().as_widget().size()
|
self.with_element(|e| e.as_widget().size())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size_hint(&self) -> Size<Length> {
|
fn size_hint(&self) -> Size<Length> {
|
||||||
self.0.lock().unwrap().as_widget().size_hint()
|
self.element.borrow_mut().as_widget().size_hint()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout(
|
fn layout(
|
||||||
|
|
@ -22,11 +58,7 @@ impl<M> Widget<M, crate::Theme, crate::Renderer> for ArcElementWrapper<M> {
|
||||||
renderer: &crate::Renderer,
|
renderer: &crate::Renderer,
|
||||||
limits: &crate::iced_core::layout::Limits,
|
limits: &crate::iced_core::layout::Limits,
|
||||||
) -> crate::iced_core::layout::Node {
|
) -> crate::iced_core::layout::Node {
|
||||||
self.0
|
self.with_element_mut(|e| e.as_widget_mut().layout(tree, renderer, limits))
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.as_widget_mut()
|
|
||||||
.layout(tree, renderer, limits)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(
|
fn draw(
|
||||||
|
|
@ -39,27 +71,26 @@ impl<M> Widget<M, crate::Theme, crate::Renderer> for ArcElementWrapper<M> {
|
||||||
cursor: crate::iced_core::mouse::Cursor,
|
cursor: crate::iced_core::mouse::Cursor,
|
||||||
viewport: &Rectangle,
|
viewport: &Rectangle,
|
||||||
) {
|
) {
|
||||||
self.0
|
self.with_element(move |e| {
|
||||||
.lock()
|
e.as_widget()
|
||||||
.unwrap()
|
.draw(tree, renderer, theme, style, layout, cursor, viewport)
|
||||||
.as_widget()
|
})
|
||||||
.draw(tree, renderer, theme, style, layout, cursor, viewport)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tag(&self) -> tree::Tag {
|
fn tag(&self) -> tree::Tag {
|
||||||
self.0.lock().unwrap().as_widget().tag()
|
self.with_element(|e| e.as_widget().tag())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn state(&self) -> tree::State {
|
fn state(&self) -> tree::State {
|
||||||
self.0.lock().unwrap().as_widget().state()
|
self.with_element(|e| e.as_widget().state())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn children(&self) -> Vec<tree::Tree> {
|
fn children(&self) -> Vec<tree::Tree> {
|
||||||
self.0.lock().unwrap().as_widget().children()
|
self.with_element(|e| e.as_widget().children())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn diff(&mut self, tree: &mut tree::Tree) {
|
fn diff(&mut self, tree: &mut tree::Tree) {
|
||||||
self.0.lock().unwrap().as_widget_mut().diff(tree)
|
self.with_element_mut(|e| e.as_widget_mut().diff(tree))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn operate(
|
fn operate(
|
||||||
|
|
@ -69,87 +100,88 @@ impl<M> Widget<M, crate::Theme, crate::Renderer> for ArcElementWrapper<M> {
|
||||||
renderer: &crate::Renderer,
|
renderer: &crate::Renderer,
|
||||||
operation: &mut dyn widget::Operation,
|
operation: &mut dyn widget::Operation,
|
||||||
) {
|
) {
|
||||||
self.0
|
self.with_element(|e| {
|
||||||
.lock()
|
e.as_widget().operate(state, layout, renderer, operation);
|
||||||
.unwrap()
|
})
|
||||||
.as_widget()
|
|
||||||
.operate(state, layout, renderer, operation)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(
|
fn on_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut tree::Tree,
|
state: &mut tree::Tree,
|
||||||
_event: crate::iced::Event,
|
event: crate::iced::Event,
|
||||||
_layout: crate::iced_core::Layout<'_>,
|
layout: crate::iced_core::Layout<'_>,
|
||||||
_cursor: crate::iced_core::mouse::Cursor,
|
cursor: crate::iced_core::mouse::Cursor,
|
||||||
_renderer: &crate::Renderer,
|
renderer: &crate::Renderer,
|
||||||
_clipboard: &mut dyn crate::iced_core::Clipboard,
|
clipboard: &mut dyn crate::iced_core::Clipboard,
|
||||||
_shell: &mut crate::iced_core::Shell<'_, M>,
|
shell: &mut crate::iced_core::Shell<'_, M>,
|
||||||
_viewport: &Rectangle,
|
viewport: &Rectangle,
|
||||||
) -> event::Status {
|
) -> event::Status {
|
||||||
self.0.lock().unwrap().as_widget_mut().on_event(
|
self.with_element_mut(|e| {
|
||||||
_state, _event, _layout, _cursor, _renderer, _clipboard, _shell, _viewport,
|
e.as_widget_mut().on_event(
|
||||||
)
|
state, event, layout, cursor, renderer, clipboard, shell, viewport,
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mouse_interaction(
|
fn mouse_interaction(
|
||||||
&self,
|
&self,
|
||||||
_state: &tree::Tree,
|
state: &tree::Tree,
|
||||||
_layout: crate::iced_core::Layout<'_>,
|
layout: crate::iced_core::Layout<'_>,
|
||||||
_cursor: crate::iced_core::mouse::Cursor,
|
cursor: crate::iced_core::mouse::Cursor,
|
||||||
_viewport: &Rectangle,
|
viewport: &Rectangle,
|
||||||
_renderer: &crate::Renderer,
|
renderer: &crate::Renderer,
|
||||||
) -> crate::iced_core::mouse::Interaction {
|
) -> crate::iced_core::mouse::Interaction {
|
||||||
self.0
|
self.with_element(|e| {
|
||||||
.lock()
|
e.as_widget()
|
||||||
.unwrap()
|
.mouse_interaction(state, layout, cursor, viewport, renderer)
|
||||||
.as_widget()
|
})
|
||||||
.mouse_interaction(_state, _layout, _cursor, _viewport, _renderer)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn overlay<'a>(
|
fn overlay<'a>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
_state: &'a mut tree::Tree,
|
state: &'a mut tree::Tree,
|
||||||
_layout: crate::iced_core::Layout<'_>,
|
layout: crate::iced_core::Layout<'_>,
|
||||||
_renderer: &crate::Renderer,
|
renderer: &crate::Renderer,
|
||||||
_translation: crate::iced_core::Vector,
|
translation: crate::iced_core::Vector,
|
||||||
) -> Option<crate::iced_core::overlay::Element<'a, M, crate::Theme, crate::Renderer>> {
|
) -> Option<crate::iced_core::overlay::Element<'a, M, crate::Theme, crate::Renderer>> {
|
||||||
// TODO
|
assert_eq!(self.thread_id, thread::current().id());
|
||||||
None
|
Rc::get_mut(&mut self.element).and_then(|e| {
|
||||||
|
e.get_mut()
|
||||||
|
.as_widget_mut()
|
||||||
|
.overlay(state, layout, renderer, translation)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn id(&self) -> Option<Id> {
|
fn id(&self) -> Option<Id> {
|
||||||
self.0.lock().unwrap().as_widget().id()
|
self.with_element_mut(|e| e.as_widget_mut().id())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_id(&mut self, _id: Id) {
|
fn set_id(&mut self, id: Id) {
|
||||||
self.0.lock().unwrap().as_widget_mut().set_id(_id)
|
self.with_element_mut(|e| e.as_widget_mut().set_id(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drag_destinations(
|
fn drag_destinations(
|
||||||
&self,
|
&self,
|
||||||
_state: &tree::Tree,
|
state: &tree::Tree,
|
||||||
_layout: crate::iced_core::Layout<'_>,
|
layout: crate::iced_core::Layout<'_>,
|
||||||
renderer: &crate::Renderer,
|
renderer: &crate::Renderer,
|
||||||
_dnd_rectangles: &mut crate::iced_core::clipboard::DndDestinationRectangles,
|
dnd_rectangles: &mut crate::iced_core::clipboard::DndDestinationRectangles,
|
||||||
) {
|
) {
|
||||||
self.0.lock().unwrap().as_widget().drag_destinations(
|
self.with_element_mut(|e| {
|
||||||
_state,
|
e.as_widget_mut()
|
||||||
_layout,
|
.drag_destinations(state, layout, renderer, dnd_rectangles)
|
||||||
renderer,
|
})
|
||||||
_dnd_rectangles,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Message: 'static> From<ArcElementWrapper<Message>> for Element<'static, Message> {
|
impl<Message: 'static> From<RcElementWrapper<Message>> for Element<'static, Message> {
|
||||||
fn from(wrapper: ArcElementWrapper<Message>) -> Self {
|
fn from(wrapper: RcElementWrapper<Message>) -> Self {
|
||||||
Element::new(wrapper)
|
Element::new(wrapper)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Message: 'static> From<Element<'static, Message>> for ArcElementWrapper<Message> {
|
impl<Message: 'static> From<Element<'static, Message>> for RcElementWrapper<Message> {
|
||||||
fn from(e: Element<'static, Message>) -> Self {
|
fn from(e: Element<'static, Message>) -> Self {
|
||||||
ArcElementWrapper(Arc::new(Mutex::new(e)))
|
RcElementWrapper::new(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue