Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Multiple dependencies for states in the RealDom (native core) #412

Merged
merged 23 commits into from
Jul 7, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
273 changes: 0 additions & 273 deletions docs/guide/src/advanced-guides/custom-renderer.md

This file was deleted.

6 changes: 3 additions & 3 deletions docs/reference/src/guide/custom_renderer.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,11 +244,11 @@ You've probably noticed that many elements in the `rsx!` macros support on-hover

# Native Core

Renderers take a lot of work. If you are creating a renderer in rust, native core provides some utilites to implement a renderer. It provides an abstraction over DomEdits and handles layout for you.
If you are creating a renderer in rust, native core provides some utilites to implement a renderer. It provides an abstraction over DomEdits and handles layout for you.

## RealDom

The `RealDom` is a higher level abstraction over updating the Dom. It updates with `DomEdits` and provides a way to lazily update the state of nodes based on what attributes change.
The `RealDom` is a higher level abstraction over updating the Dom. It updates with `DomEdits` and provides a way to incrementally update the state of nodes based on what attributes change.

### Example

Expand Down Expand Up @@ -304,7 +304,7 @@ flowchart TB
end
```

To help in building a Dom, native core provides four traits: State, ChildDepState, ParentDepState, and NodeDepState and a RealDom struct.
To help in building a Dom, native core provides four traits: State, ChildDepState, ParentDepState, and NodeDepState and a RealDom struct. The ChildDepState, ParentDepState, and NodeDepState provide a way to discribe how some information in a node relates to that of its relatives. By providing how to build a single node from its relations, native-core will derive a way to update the state of all nodes for you with ```#[derive(State)]```. Once you have a state you can provide it as a generic to RealDom. RealDom provides all of the methods to interact and update your new dom.

```rust
use dioxus_native_core::node_ref::*;
Expand Down
47 changes: 47 additions & 0 deletions packages/native-core/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::{cmp::Ordering, fmt::Debug};

use anymap::AnyMap;
use dioxus_core::ElementId;
use dioxus_html::{GlobalAttributes, SvgAttributes};
use fxhash::FxHashSet;

use crate::element_borrowable::ElementBorrowable;
Expand Down Expand Up @@ -79,6 +80,51 @@ pub trait ParentDepState {
/// This state that is upadated lazily. For example any propertys that do not effect other parts of the dom like bg-color.
/// Called when the current node's node properties are modified or a parrent's [PushedDownState] is modified.
/// Called at most once per update.
/// NodeDepState is the only state that can accept multable dependancies, but only from the current node.
ealmloff marked this conversation as resolved.
Show resolved Hide resolved
/// ```rust
/// impl NodeDepState for Layout {
/// type Ctx = LayoutCache;
/// type DepState = (TextWrap, ChildLayout);
/// const NODE_MASK: NodeMask =
/// NodeMask::new_with_attrs(AttributeMask::Static(&sorted_str_slice!([
/// "width", "height"
/// ])))
/// .with_text();
/// fn reduce<'a>(
/// &mut self,
/// node: NodeView,
/// siblings: (&TextWrap, &ChildLayout),
/// ctx: &Self::Ctx,
/// ) -> bool {
/// let old = self.clone();
/// let (text_wrap, child_layout) = siblings;
/// if TextWrap::Wrap == text_wrap {
/// if let Some(text) = node.text() {
/// let lines = text_wrap.get_lines(text);
/// self.width = lines.max_by(|l| l.len());
/// self.height = lines.len();
/// return old != self;
/// }
/// }
/// let mut width = child_layout.width;
/// let mut height = child_layout.width;
/// for attr in node.attributes() {
/// match attr.name {
/// "width" => {
/// width = attr.value.as_text().unwrap().parse().unwrap();
/// }
/// "height" => {
/// height = attr.value.as_text().unwrap().parse().unwrap();
/// }
/// _ => unreachable!(),
/// }
/// }
/// self.width = width;
/// self.height = height;
/// old != self
/// }
/// }
/// ```
pub trait NodeDepState {
type Ctx;
/// This must be either a [ChildDepState], [ParentDepState] or [NodeDepState]
Expand All @@ -92,6 +138,7 @@ pub trait NodeDepState {
) -> bool;
}

/// Do not implement this trait. It is only meant to be derived and used through [RealDom].
ealmloff marked this conversation as resolved.
Show resolved Hide resolved
pub trait State: Default + Clone {
fn update<'a, T: Traversable<Node = Self, Id = ElementId>>(
dirty: &Vec<(ElementId, NodeMask)>,
Expand Down