diff --git a/ui/src/nodes/layout.rs b/ui/src/nodes/layout.rs index cd18d8a..a144540 100644 --- a/ui/src/nodes/layout.rs +++ b/ui/src/nodes/layout.rs @@ -1,5 +1,5 @@ use std::fmt::{Debug, Formatter}; -use crate::{nodes::{Node, NodeChildren, Style}, events::handler::EventHandlerDatabase}; +use crate::{nodes::{Node, NodeChildren, Style}, events::handler::EventHandlerDatabase, WeakNode, SharedNode}; use taffy::style::Dimension; /// A simple layout node which contains children. @@ -7,7 +7,8 @@ use taffy::style::Dimension; pub struct Layout { pub style: Style, pub children: NodeChildren, - pub events: EventHandlerDatabase + pub events: EventHandlerDatabase, + pub parent: Option } impl Layout { @@ -15,7 +16,8 @@ impl Layout { Layout { style: Style::default(), children, - events: EventHandlerDatabase::default() + events: EventHandlerDatabase::default(), + parent: None } } } @@ -42,13 +44,35 @@ impl Node for Layout { } fn add_child_at(&mut self, child: crate::SharedNode, index: usize) -> Result<(), super::ChildAddError> { - if let Some(_) = self.has_child(&child) { - return Err(super::ChildAddError::ChildAlreadyExists); + let mut index = index; + if let Some(i) = self.has_child(&child) { + self.children.remove(i); + if i < index { + index -= 1; + } } - self.children.insert(index, child); Ok(()) + self.children.insert(index, child); + Ok(()) } fn event_handlers(&self) -> Option { Some(self.events.handlers.clone()) } + fn set_parent(&mut self, parent: Option) { + self.parent = parent; + } + fn parent(&self) -> Option { + match &self.parent { + Some(parent) => parent.upgrade(), + None => None + } + } + fn remove_child(&mut self, child: &SharedNode) -> Result<(), super::ChildAddError> { + if let Some(i) = self.has_child(child) { + self.children.remove(i); + Ok(()) + } else { + Ok(()) + } + } } \ No newline at end of file diff --git a/ui/src/nodes/mod.rs b/ui/src/nodes/mod.rs index 9dd94a3..9858638 100644 --- a/ui/src/nodes/mod.rs +++ b/ui/src/nodes/mod.rs @@ -8,7 +8,7 @@ use taffy::layout::Layout; use taffy::Taffy; use crate::events::Location; use crate::events::handler::{EventHandlerDatabase, InnerEventHandlerDataset}; -use crate::{NodeLayoutMap, NodePtr, CurrentRenderer, SharedNode}; +use crate::{NodeLayoutMap, NodePtr, CurrentRenderer, SharedNode, WeakNode}; pub use taffy::style::Style as TaffyStyle; @@ -45,10 +45,16 @@ pub enum Overflow { // Scroll, // Auto } +#[derive(Copy, Clone, Default, Debug)] +pub enum Cursor { + #[default] + Default +} #[derive(Clone, Default, Debug)] pub struct Style { pub layout: TaffyStyle, - pub overflow: Overflow + pub overflow: Overflow, + pub cursor: Cursor } type NodeChildren = Vec; @@ -56,8 +62,6 @@ type NodeChildren = Vec; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ChildAddError { ChildrenNotSupported, - /// The child already exists in the node - ChildAlreadyExists, /// The index is out of bounds (cannot be thrown from add_child as long as the [`Node`] implementation is correct) OutOfBounds, /// Generic error text (subject to change for better error handling) @@ -79,7 +83,12 @@ pub enum ChildAddError { /// If you support children in a read only matter, you can return a [`NodeChildren`] from [`Node::children`]. /// /// If you also need to be able to update children, implement [`Node::add_child_at`] in addition to [`Node::children`]. -/// Other child adding methods are implemented using [`Node::add_child_at`] and/or [`Node::children`]. +/// Other child adding methods are implemented using [`Node::add_child_at`] and/or [`Node::children`] automatically. +/// Implement [`Node::remove_child`] to support removing children. +/// +/// # Events +/// +/// If you need to handle events, implement [`Node::event_handlers`]. pub trait Node: Debug { /// Return style. /// @@ -95,6 +104,39 @@ pub trait Node: Debug { /// fn children(&self) -> Option<&NodeChildren> { Some(&self.children) } /// ``` fn children(&self) -> Option<&NodeChildren>; + + /// Render the node, called before rendering it's children + /// Canvas considers 0, 0 to be top left corner (for location after layouting happens) + fn render_pre_children(&self, _context: &mut RenderContext, _layout: Layout) {} + /// Render the node, called after rendering it's children + /// Canvas considers 0, 0 to be top left corner (for location after layouting happens) + fn render_post_children(&self, _context: &mut RenderContext, _layout: Layout) {} + + /// Sets the parent node. + /// May be called multiple times with the same value. + /// + /// Implementors: SAVE A WEAK REFERENCE! + /// Without a weak reference, the tree will have a loop and will never be dropped. + /// + /// Example implementation: + /// ```rust + /// fn set_parent(&mut self, parent: Option) { + /// self.parent = parent; + /// } + fn set_parent(&mut self, parent: Option); + /// Returns the parent node. + /// + /// Example implementation: + /// ```rust + /// fn parent(&self) -> Option { + /// match &self.parent { + /// Some(parent) => parent.upgrade(), + /// None => None + /// } + /// } + /// ``` + fn parent(&self) -> Option; + /// Add a child to the node. If the node does not support children, returns error ChildrenNotSupported. /// Adding the same child multiple times or to multiple parents is not supported and will result in undefined behavior. /// Arc> does **NOT** mean that it's safe to add the same node multiple times. @@ -115,9 +157,12 @@ pub trait Node: Debug { /// Arc> does **NOT** mean that it's safe to add the same node multiple times. /// /// Implementors can check [`Node::has_child`] to check if the child already exists. Default implementation thros [`ChildAddError::ChildrenNotSupported`]. + /// Adding a child that already exists should move that child to the new position. fn add_child_at(&mut self, _child: SharedNode, _index: usize) -> Result<(), ChildAddError> { Err(ChildAddError::ChildrenNotSupported) } /// Adds a child after the given child. If the node does not support children, returns error ChildrenNotSupported. + /// Adding the same child multiple times or to multiple parents is not supported and will result in undefined behavior. + /// Arc> does **NOT** mean that it's safe to add the same node multiple times. fn add_child_after(&mut self, child: SharedNode, after: &SharedNode) -> Result<(), ChildAddError> { if let Some(_) = self.children() { if let Some(index) = self.has_child(after) { @@ -130,21 +175,40 @@ pub trait Node: Debug { } } - /// Render the node, called before rendering it's children - /// Canvas considers 0, 0 to be top left corner (for location after layouting happens) - fn render_pre_children(&self, _context: &mut RenderContext, _layout: Layout) {} - /// Render the node, called after rendering it's children - /// Canvas considers 0, 0 to be top left corner (for location after layouting happens) - fn render_post_children(&self, _context: &mut RenderContext, _layout: Layout) {} + /// Adds a child before the given child. If the node does not support children, returns error ChildrenNotSupported. + /// Adding the same child multiple times or to multiple parents is not supported and will result in undefined behavior. + /// Arc> does **NOT** mean that it's safe to add the same node multiple times. + fn add_child_before(&mut self, child: SharedNode, before: &SharedNode) -> Result<(), ChildAddError> { + if let Some(_) = self.children() { + if let Some(index) = self.has_child(before) { + self.add_child_at(child, index) + } else { + Err(ChildAddError::GenericError("Child not found".to_owned())) + } + } else { + Err(ChildAddError::ChildrenNotSupported) + } + } + + /// Removes a child from the node. If the node does not support children, returns error ChildrenNotSupported. + /// Removing non-existent child is a no-op. + fn remove_child(&mut self, _child: &SharedNode) -> Result<(), ChildAddError> { Err(ChildAddError::ChildrenNotSupported) } /// Returns the event handlers of the node. If the node has no event handlers, return None. /// Use [`EventHandlerDatabase`] to manage this, and return it's handlers property. - /// Example code: + /// Example implementation: /// ```rust /// fn event_handlers(&self) -> Option { /// Some(self.events.handlers.clone()) /// } /// ``` + /// + /// Example struct: + /// ```rust + /// struct MyNode { + /// events: EventHandlerDatabase + /// } + /// ``` fn event_handlers(&self) -> Option { None } @@ -244,6 +308,7 @@ pub(crate) fn layout_recursively(node: &SharedNode, context: &mut RenderContext) let mut t_children = Vec::with_capacity(children.len()); for child in children { t_children.push(layout_recursively(child, context).to_owned()); + child.write().unwrap().set_parent(Some(Arc::downgrade(node))); } context.taffy.set_children(taffy_node, t_children.as_slice()).unwrap(); } diff --git a/ui/src/nodes/primitives.rs b/ui/src/nodes/primitives.rs index c4af92e..386338d 100644 --- a/ui/src/nodes/primitives.rs +++ b/ui/src/nodes/primitives.rs @@ -1,13 +1,14 @@ use femtovg::{Color, Paint, Path}; use taffy::layout::Layout; -use crate::{nodes::{Node, NodeChildren, RenderContext, Style}, events::handler::EventHandlerDatabase}; +use crate::{nodes::{Node, NodeChildren, RenderContext, Style}, events::handler::EventHandlerDatabase, WeakNode, SharedNode}; #[derive(Default, Debug)] pub struct Rectangle { pub style: Style, pub fill: Paint, pub radius: f32, - pub events: EventHandlerDatabase + pub events: EventHandlerDatabase, + pub parent: Option } impl Rectangle { @@ -16,7 +17,8 @@ impl Rectangle { style: Style::default(), fill: Paint::color(Color::rgb(0, 0, 0)), radius: 0., - events: EventHandlerDatabase::default() + events: EventHandlerDatabase::default(), + parent: None } } } @@ -45,4 +47,13 @@ impl Node for Rectangle { fn event_handlers(&self) -> Option { Some(self.events.handlers.clone()) } + fn set_parent(&mut self, parent: Option) { + self.parent = parent; + } + fn parent(&self) -> Option { + match &self.parent { + Some(parent) => parent.upgrade(), + None => None + } + } } \ No newline at end of file