add parents

This commit is contained in:
Daniel Bulant 2023-10-27 17:57:38 +02:00
parent 119eb9cfb8
commit 55476f971f
3 changed files with 121 additions and 21 deletions

View file

@ -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<WeakNode>
}
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<crate::events::handler::InnerEventHandlerDataset> {
Some(self.events.handlers.clone())
}
fn set_parent(&mut self, parent: Option<WeakNode>) {
self.parent = parent;
}
fn parent(&self) -> Option<SharedNode> {
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(())
}
}
}

View file

@ -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<SharedNode>;
@ -56,8 +62,6 @@ type NodeChildren = Vec<SharedNode>;
#[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<WeakNode>) {
/// self.parent = parent;
/// }
fn set_parent(&mut self, parent: Option<WeakNode>);
/// Returns the parent node.
///
/// Example implementation:
/// ```rust
/// fn parent(&self) -> Option<SharedNode> {
/// match &self.parent {
/// Some(parent) => parent.upgrade(),
/// None => None
/// }
/// }
/// ```
fn parent(&self) -> Option<SharedNode>;
/// 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<RwLock<Node>> does **NOT** mean that it's safe to add the same node multiple times.
@ -115,9 +157,12 @@ pub trait Node: Debug {
/// Arc<RwLock<Node>> 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<RwLock<Node>> 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<RwLock<Node>> 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<InnerEventHandlerDataset> {
/// Some(self.events.handlers.clone())
/// }
/// ```
///
/// Example struct:
/// ```rust
/// struct MyNode {
/// events: EventHandlerDatabase
/// }
/// ```
fn event_handlers(&self) -> Option<InnerEventHandlerDataset> {
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();
}

View file

@ -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<WeakNode>
}
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<crate::events::handler::InnerEventHandlerDataset> {
Some(self.events.handlers.clone())
}
fn set_parent(&mut self, parent: Option<WeakNode>) {
self.parent = parent;
}
fn parent(&self) -> Option<SharedNode> {
match &self.parent {
Some(parent) => parent.upgrade(),
None => None
}
}
}