update TUI renderer to new approach

This commit is contained in:
Evan Almloff committed 2023-01-28 14:51:05 -06:00
1 parent ce59ccfd44
commit 9efff74c0c
14 files changed
+339 -270

No files matched your search

+41 -38
View File
@@ -1,15 +1,17 @@
use crate::{node::PreventDefault, TuiDom};
use crate::node::PreventDefault;
use dioxus_native_core::{
tree::TreeView,
node_ref::{AttributeMaskBuilder, NodeMaskBuilder},
real_dom::{NodeImmutable, NodeMutable},
utils::{ElementProduced, PersistantElementIter},
NodeId, Pass, SendAnyMap,
Dependancy, NodeId, Pass, RealDom, SendAnyMap,
};
use dioxus_native_core_macro::sorted_str_slice;
use std::{cmp::Ordering, num::NonZeroU16};
use dioxus_native_core::node_ref::{AttributeMask, NodeMask, NodeView};
use dioxus_native_core::node_ref::NodeView;
pub struct Focused(pub bool);
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub(crate) enum FocusLevel {
@@ -62,8 +64,9 @@ pub(crate) struct Focus {
}
impl Pass for Focus {
const NODE_MASK: NodeMask =
NodeMask::new_with_attrs(AttributeMask::Static(FOCUS_ATTRIBUTES)).with_listeners();
const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new()
.with_attrs(AttributeMaskBuilder::Some(FOCUS_ATTRIBUTES))
.with_listeners();
type ParentDependencies = ();
type ChildDependencies = ();
@@ -72,18 +75,10 @@ impl Pass for Focus {
fn pass<'a>(
&mut self,
node_view: NodeView,
_: <Self::NodeDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>,
_: Option<
<Self::ParentDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>,
>,
_: Option<
impl Iterator<
Item = <Self::ChildDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<
'a,
>,
>,
>,
_: &SendAnyMap,
node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
context: &SendAnyMap,
) -> bool {
let new = Focus {
level: if let Some(a) = node_view
@@ -128,8 +123,8 @@ impl Pass for Focus {
}
}
const FOCUS_EVENTS: &[&str] = &sorted_str_slice!(["keydown", "keypress", "keyup"]);
const FOCUS_ATTRIBUTES: &[&str] = &sorted_str_slice!(["tabindex"]);
const FOCUS_EVENTS: &[&str] = &["keydown", "keypress", "keyup"];
const FOCUS_ATTRIBUTES: &[&str] = &["tabindex"];
#[derive(Default)]
pub(crate) struct FocusState {
@@ -141,9 +136,11 @@ pub(crate) struct FocusState {
impl FocusState {
/// Returns true if the focus has changed.
pub fn progress(&mut self, rdom: &mut TuiDom, forward: bool) -> bool {
pub fn progress(&mut self, rdom: &mut RealDom, forward: bool) -> bool {
if let Some(last) = self.last_focused_id {
if rdom[last].state.prevent_default == PreventDefault::KeyDown {
if rdom.get(last).unwrap().get::<PreventDefault>().copied()
== Some(PreventDefault::KeyDown)
{
return false;
}
}
@@ -165,7 +162,7 @@ impl FocusState {
if forward {
// find the closest focusable element after the current level
rdom.traverse_depth_first(|n| {
let node_level = n.state.focus.level;
let node_level = n.get::<Focus>().unwrap().level;
if node_level != *focus_level
&& node_level.focusable()
&& node_level > *focus_level
@@ -182,7 +179,7 @@ impl FocusState {
} else {
// find the closest focusable element before the current level
rdom.traverse_depth_first(|n| {
let node_level = n.state.focus.level;
let node_level = n.get::<Focus>().unwrap().level;
if node_level != *focus_level
&& node_level.focusable()
&& node_level < *focus_level
@@ -219,7 +216,7 @@ impl FocusState {
loop_marker_id = Some(new_id);
}
let current_level = rdom[new_id].state.focus.level;
let current_level = rdom.get(new_id).unwrap().get::<Focus>().unwrap().level;
let after_previous_focused = if forward {
current_level >= *focus_level
} else {
@@ -233,12 +230,16 @@ impl FocusState {
}
if let Some(id) = next_focus {
if !rdom[id].state.focus.level.focusable() {
let mut node = rdom.get_mut_raw(id).unwrap();
if !node.get::<Focus>().unwrap().level.focusable() {
panic!()
}
rdom[id].state.focused = true;
let focused = node.get_mut::<Focused>().unwrap();
focused.0 = true;
if let Some(old) = self.last_focused_id.replace(id) {
rdom[old].state.focused = false;
let mut old = rdom.get_mut_raw(old).unwrap();
let focused = old.get_mut::<Focused>().unwrap();
focused.0 = false;
}
// reset the position to the currently focused element
while self.focus_iter.next(rdom).id() != id {}
@@ -249,8 +250,8 @@ impl FocusState {
false
}
pub(crate) fn prune(&mut self, mutations: &dioxus_core::Mutations, rdom: &TuiDom) {
fn remove_children(to_prune: &mut [&mut Option<NodeId>], rdom: &TuiDom, removed: NodeId) {
pub(crate) fn prune(&mut self, mutations: &dioxus_core::Mutations, rdom: &RealDom) {
fn remove_children(to_prune: &mut [&mut Option<NodeId>], rdom: &RealDom, removed: NodeId) {
for opt in to_prune.iter_mut() {
if let Some(id) = opt {
if *id == removed {
@@ -258,8 +259,9 @@ impl FocusState {
}
}
}
if let Some(children) = &rdom.children_ids(removed) {
for child in *children {
let node = rdom.get(removed).unwrap();
if let Some(children) = node.child_ids() {
for child in children {
remove_children(to_prune, rdom, *child);
}
}
@@ -284,13 +286,14 @@ impl FocusState {
}
}
pub(crate) fn set_focus(&mut self, rdom: &mut TuiDom, id: NodeId) {
pub(crate) fn set_focus(&mut self, rdom: &mut RealDom, id: NodeId) {
if let Some(old) = self.last_focused_id.replace(id) {
rdom[old].state.focused = false;
let mut node = rdom.get_mut_raw(old).unwrap();
node.get_mut::<Focused>().unwrap().0 = false;
}
let state = &mut rdom[id].state;
state.focused = true;
self.focus_level = state.focus.level;
let mut node = &mut rdom.get_mut_raw(id).unwrap();
node.get_mut::<Focused>().unwrap().0 = true;
self.focus_level = node.get::<Focus>().unwrap().level;
// reset the position to the currently focused element
while self.focus_iter.next(rdom).id() != id {}
self.dirty = true;
+31 -23
View File
@@ -2,8 +2,8 @@ use crossterm::event::{
Event as TermEvent, KeyCode as TermKeyCode, KeyModifiers, MouseButton, MouseEventKind,
};
use dioxus_core::*;
use dioxus_native_core::tree::TreeView;
use dioxus_native_core::NodeId;
use dioxus_native_core::real_dom::NodeImmutable;
use dioxus_native_core::{NodeId, NodeRef, RealDom};
use rustc_hash::{FxHashMap, FxHashSet};
use dioxus_html::geometry::euclid::{Point2D, Rect, Size2D};
@@ -23,8 +23,9 @@ use std::{
use taffy::geometry::{Point, Size};
use taffy::{prelude::Layout, Taffy};
use crate::focus::{Focus, Focused};
use crate::layout::TaffyLayout;
use crate::{layout_to_screen_space, FocusState};
use crate::{TuiDom, TuiNode};
pub(crate) struct Event {
pub id: ElementId,
@@ -173,7 +174,7 @@ impl InnerInputState {
evts: &mut Vec<EventCore>,
resolved_events: &mut Vec<Event>,
layout: &Taffy,
dom: &mut TuiDom,
dom: &mut RealDom,
) {
let previous_mouse = self.mouse.clone();
@@ -201,7 +202,7 @@ impl InnerInputState {
// elements with listeners will always have a element id
if let Some(id) = self.focus_state.last_focused_id {
let element = dom.get(id).unwrap();
if let Some(id) = element.node_data.element_id {
if let Some(id) = element.node_data().element_id {
resolved_events.push(Event {
name: "focus",
id,
@@ -218,7 +219,7 @@ impl InnerInputState {
}
if let Some(id) = old_focus {
let element = dom.get(id).unwrap();
if let Some(id) = element.node_data.element_id {
if let Some(id) = element.node_data().element_id {
resolved_events.push(Event {
name: "focusout",
id,
@@ -239,7 +240,7 @@ impl InnerInputState {
previous_mouse: Option<MouseData>,
resolved_events: &mut Vec<Event>,
layout: &Taffy,
dom: &mut TuiDom,
dom: &mut RealDom,
) {
fn layout_contains_point(layout: &Layout, point: ScreenPoint) -> bool {
let Point { x, y } = layout.location;
@@ -262,17 +263,17 @@ impl InnerInputState {
data: Rc<dyn Any>,
will_bubble: &mut FxHashSet<NodeId>,
resolved_events: &mut Vec<Event>,
node: &TuiNode,
dom: &TuiDom,
node: NodeRef,
dom: &RealDom,
) {
// only trigger event if the event was not triggered already by a child
let id = node.node_data.node_id;
let id = node.node_data().node_id;
if will_bubble.insert(id) {
let mut parent = dom.parent(id);
let mut parent = Some(node);
while let Some(current_parent) = parent {
let parent_id = current_parent.node_data.node_id;
let parent_id = current_parent.node_data().node_id;
will_bubble.insert(parent_id);
parent = dom.parent(parent_id);
parent = current_parent.parent_id().and_then(|id| dom.get(id));
}
if let Some(id) = node.mounted_id() {
resolved_events.push(Event {
@@ -564,11 +565,13 @@ impl InnerInputState {
if was_released {
let mut focus_id = None;
dom.traverse_depth_first(|node| {
let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap();
let node_layout = layout
.layout(node.get::<TaffyLayout>().unwrap().node.unwrap())
.unwrap();
let currently_contains = layout_contains_point(node_layout, new_pos);
if currently_contains && node.state.focus.level.focusable() {
focus_id = Some(node.node_data.node_id);
if currently_contains && node.get::<Focus>().unwrap().level.focusable() {
focus_id = Some(node.node_data().node_id);
}
});
if let Some(id) = focus_id {
@@ -583,13 +586,18 @@ impl InnerInputState {
// }
}
fn get_abs_layout(node: &TuiNode, dom: &TuiDom, taffy: &Taffy) -> Layout {
let mut node_layout = *taffy.layout(node.state.layout.node.unwrap()).unwrap();
fn get_abs_layout(node: NodeRef, dom: &RealDom, taffy: &Taffy) -> Layout {
let mut node_layout = *taffy
.layout(node.get::<TaffyLayout>().unwrap().node.unwrap())
.unwrap();
let mut current = node;
while let Some(parent) = dom.parent(current.node_data.node_id) {
while let Some(parent) = current.parent_id() {
let parent = dom.get(parent).unwrap();
current = parent;
let parent_layout = taffy.layout(parent.state.layout.node.unwrap()).unwrap();
let parent_layout = taffy
.layout(parent.get::<TaffyLayout>().unwrap().node.unwrap())
.unwrap();
node_layout.location.x += parent_layout.location.x;
node_layout.location.y += parent_layout.location.y;
}
@@ -632,11 +640,11 @@ impl RinkInputHandler {
)
}
pub(crate) fn prune(&self, mutations: &dioxus_core::Mutations, rdom: &TuiDom) {
pub(crate) fn prune(&self, mutations: &dioxus_core::Mutations, rdom: &RealDom) {
self.state.borrow_mut().focus_state.prune(mutations, rdom);
}
pub(crate) fn get_events(&self, layout: &Taffy, dom: &mut TuiDom) -> Vec<Event> {
pub(crate) fn get_events(&self, layout: &Taffy, dom: &mut RealDom) -> Vec<Event> {
let mut resolved_events = Vec::new();
(*self.state).borrow_mut().update(
@@ -680,7 +688,7 @@ impl RinkInputHandler {
for (event, datas) in hm {
for node in dom.get_listening_sorted(event) {
for data in &datas {
if node.state.focused {
if node.get::<Focused>().unwrap().0 {
if let Some(id) = node.mounted_id() {
resolved_events.push(Event {
name: event,
+11 -19
View File
@@ -4,9 +4,8 @@ use dioxus_native_core::layout_attributes::{
apply_layout_attributes_cfg, BorderWidths, LayoutConfigeration,
};
use dioxus_native_core::node::OwnedAttributeView;
use dioxus_native_core::node_ref::{AttributeMask, NodeMask, NodeView};
use dioxus_native_core::{Pass, SendAnyMap};
use dioxus_native_core_macro::sorted_str_slice;
use dioxus_native_core::node_ref::{AttributeMaskBuilder, NodeMaskBuilder, NodeView};
use dioxus_native_core::{Dependancy, Pass, SendAnyMap};
use taffy::prelude::*;
use crate::{screen_to_layout_space, unit_to_layout_space};
@@ -48,23 +47,16 @@ impl Pass for TaffyLayout {
type ParentDependencies = ();
type NodeDependencies = ();
const NODE_MASK: NodeMask =
NodeMask::new_with_attrs(AttributeMask::Static(SORTED_LAYOUT_ATTRS)).with_text();
const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new()
.with_attrs(AttributeMaskBuilder::Some(SORTED_LAYOUT_ATTRS))
.with_text();
fn pass<'a>(
&mut self,
node_view: NodeView,
_: <Self::NodeDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>,
_: Option<
<Self::ParentDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>,
>,
children: Option<
impl Iterator<
Item = <Self::ChildDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<
'a,
>,
>,
>,
node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
ctx: &SendAnyMap,
) -> bool {
let mut changed = false;
@@ -203,7 +195,7 @@ impl Pass for TaffyLayout {
}
// these are the attributes in layout_attiributes in native-core
const SORTED_LAYOUT_ATTRS: &[&str] = &sorted_str_slice!([
const SORTED_LAYOUT_ATTRS: &[&str] = &[
"align-content",
"align-items",
"align-self",
@@ -355,5 +347,5 @@ const SORTED_LAYOUT_ATTRS: &[&str] = &sorted_str_slice!([
"word-break",
"word-spacing",
"word-wrap",
"z-index"
]);
"z-index",
];
+17 -6
View File
@@ -6,6 +6,7 @@ use crossterm::{
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use dioxus_core::*;
use dioxus_native_core::{node_ref::NodeMaskBuilder, real_dom::NodeImmutable, Pass};
use dioxus_native_core::{real_dom::RealDom, FxDashSet, NodeId, NodeMask, SendAnyMap};
use focus::FocusState;
use futures::{
@@ -13,6 +14,7 @@ use futures::{
pin_mut, StreamExt,
};
use futures_channel::mpsc::unbounded;
use layout::TaffyLayout;
use query::Query;
use std::rc::Rc;
use std::{
@@ -101,7 +103,9 @@ pub fn launch_cfg_with_props<Props: 'static>(app: Component<Props>, props: Props
}
let cx = dom.base_scope();
let rdom = Rc::new(RefCell::new(RealDom::new()));
let rdom = Rc::new(RefCell::new(RealDom::new(Box::new([
TaffyLayout::to_type_erased(),
]))));
let taffy = Arc::new(Mutex::new(Taffy::new()));
cx.provide_context(state);
cx.provide_context(TuiContext { tx: event_tx_clone });
@@ -136,7 +140,7 @@ fn render_vdom(
mut event_reciever: UnboundedReceiver<InputEvent>,
handler: RinkInputHandler,
cfg: Config,
rdom: Rc<RefCell<TuiDom>>,
rdom: Rc<RefCell<RealDom>>,
taffy: Arc<Mutex<Taffy>>,
mut register_event: impl FnMut(crossterm::event::Event),
) -> Result<()> {
@@ -177,10 +181,16 @@ fn render_vdom(
if !to_rerender.is_empty() || updated {
updated = false;
fn resize(dims: Rect, taffy: &mut Taffy, rdom: &TuiDom) {
fn resize(dims: Rect, taffy: &mut Taffy, rdom: &RealDom) {
let width = screen_to_layout_space(dims.width);
let height = screen_to_layout_space(dims.height);
let root_node = rdom[NodeId(0)].state.layout.node.unwrap();
let root_node = rdom
.get(NodeId(0))
.unwrap()
.get::<TaffyLayout>()
.unwrap()
.node
.unwrap();
// the root node fills the entire area
@@ -204,7 +214,7 @@ fn render_vdom(
let mut taffy = taffy.lock().expect("taffy lock poisoned");
// size is guaranteed to not change when rendering
resize(frame.size(), &mut taffy, &rdom);
let root = &rdom[NodeId(0)];
let root = rdom.get(NodeId(0)).unwrap();
render::render_vnode(frame, &taffy, &rdom, root, cfg, Point::ZERO);
})?;
execute!(terminal.backend_mut(), RestorePosition, Show).unwrap();
@@ -277,8 +287,9 @@ fn render_vdom(
any_map.insert(taffy.clone());
let (new_to_rerender, dirty) = rdom.update_state(any_map);
to_rerender = new_to_rerender;
let text_mask = NodeMaskBuilder::new().with_text().build();
for (id, mask) in dirty {
if mask.overlaps(&NodeMask::new().with_text()) {
if mask.overlaps(&text_mask) {
to_rerender.insert(id);
}
}
+14 -22
View File
@@ -1,23 +1,18 @@
use crate::focus::Focus;
use crate::layout::TaffyLayout;
use crate::style_attributes::StyleModifier;
use dioxus_native_core::{real_dom::RealDom, Dependancy, Pass, SendAnyMap};
use dioxus_native_core_macro::{sorted_str_slice, AnyMapLike, State};
use dioxus_native_core::{node_ref::NodeView, Dependancy, Pass, SendAnyMap};
pub(crate) type TuiDom = RealDom<NodeState>;
pub(crate) type TuiNode = dioxus_native_core::node::Node<NodeState>;
#[derive(Debug, Clone, State, AnyMapLike, Default)]
#[derive(Debug, Clone, Default)]
pub(crate) struct NodeState {
pub layout: TaffyLayout,
pub style: StyleModifier,
pub prevent_default: PreventDefault,
pub focus: Focus,
#[skip]
pub focused: bool,
}
#[derive(PartialEq, Debug, Clone)]
#[derive(PartialEq, Debug, Clone, Copy)]
pub(crate) enum PreventDefault {
Focus,
KeyPress,
@@ -47,23 +42,20 @@ impl Pass for PreventDefault {
type ChildDependencies = ();
type NodeDependencies = ();
const NODE_MASK: dioxus_native_core::node_ref::NodeMask =
dioxus_native_core::node_ref::NodeMask::new_with_attrs(
dioxus_native_core::node_ref::AttributeMask::Static(&sorted_str_slice!([
"dioxus-prevent-default"
])),
)
.with_listeners();
const NODE_MASK: dioxus_native_core::node_ref::NodeMaskBuilder =
dioxus_native_core::node_ref::NodeMaskBuilder::new()
.with_attrs(dioxus_native_core::node_ref::AttributeMaskBuilder::Some(&[
"dioxus-prevent-default",
]))
.with_listeners();
fn pass<'a>(
&mut self,
node_view: dioxus_native_core::node_ref::NodeView,
_: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
_: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
_: Option<
impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
>,
_: &SendAnyMap,
node_view: NodeView,
node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
context: &SendAnyMap,
) -> bool {
let new = match node_view.attributes().and_then(|mut attrs| {
attrs
+14 -5
View File
@@ -5,13 +5,14 @@ use std::{
};
use dioxus_core::ElementId;
use dioxus_native_core::{real_dom::NodeImmutable, RealDom};
use taffy::{
geometry::Point,
prelude::{Layout, Size},
Taffy,
};
use crate::{layout_to_screen_space, TuiDom};
use crate::{layout::TaffyLayout, layout_to_screen_space};
/// Allows querying the layout of nodes after rendering. It will only provide a correct value after a node is rendered.
/// Provided as a root context for all tui applictions.
@@ -46,7 +47,7 @@ use crate::{layout_to_screen_space, TuiDom};
/// ```
#[derive(Clone)]
pub struct Query {
pub(crate) rdom: Rc<RefCell<TuiDom>>,
pub(crate) rdom: Rc<RefCell<RealDom>>,
pub(crate) stretch: Arc<Mutex<Taffy>>,
}
@@ -61,13 +62,13 @@ impl Query {
}
pub struct ElementRef<'a> {
inner: Ref<'a, TuiDom>,
inner: Ref<'a, RealDom>,
stretch: MutexGuard<'a, Taffy>,
id: ElementId,
}
impl<'a> ElementRef<'a> {
fn new(inner: Ref<'a, TuiDom>, stretch: MutexGuard<'a, Taffy>, id: ElementId) -> Self {
fn new(inner: Ref<'a, RealDom>, stretch: MutexGuard<'a, Taffy>, id: ElementId) -> Self {
Self { inner, stretch, id }
}
@@ -85,7 +86,15 @@ impl<'a> ElementRef<'a> {
pub fn layout(&self) -> Option<Layout> {
let layout = self
.stretch
.layout(self.inner[self.id].state.layout.node.ok()?)
.layout(
self.inner
.get(self.id)
.unwrap()
.get::<TaffyLayout>()
.unwrap()
.node
.ok()?,
)
.ok();
layout.map(|layout| Layout {
order: layout.order,
+30 -20
View File
@@ -1,18 +1,24 @@
use dioxus_native_core::tree::TreeView;
use dioxus_native_core::{real_dom::NodeImmutable, NodeRef, RealDom};
use std::io::Stdout;
use taffy::{
geometry::Point,
prelude::{Dimension, Layout, Size},
Taffy,
};
use tui::{backend::CrosstermBackend, layout::Rect, style::Color};
use tui::{
backend::CrosstermBackend,
layout::Rect,
style::{Color, Style},
};
use crate::{
focus::Focused,
layout::TaffyLayout,
layout_to_screen_space,
style::{RinkColor, RinkStyle},
style_attributes::{BorderEdge, BorderStyle},
style_attributes::{BorderEdge, BorderStyle, StyleModifier},
widget::{RinkBuffer, RinkCell, RinkWidget, WidgetWithContext},
Config, TuiDom, TuiNode,
Config,
};
const RADIUS_MULTIPLIER: [f32; 2] = [1.0, 0.5];
@@ -20,20 +26,22 @@ const RADIUS_MULTIPLIER: [f32; 2] = [1.0, 0.5];
pub(crate) fn render_vnode(
frame: &mut tui::Frame<CrosstermBackend<Stdout>>,
layout: &Taffy,
rdom: &TuiDom,
node: &TuiNode,
rdom: &RealDom,
node: NodeRef,
cfg: Config,
parent_location: Point<f32>,
) {
use dioxus_native_core::node::NodeType;
if let NodeType::Placeholder = &node.node_data.node_type {
if let NodeType::Placeholder = &node.node_type() {
return;
}
let Layout {
mut location, size, ..
} = layout.layout(node.state.layout.node.unwrap()).unwrap();
} = layout
.layout(node.get::<TaffyLayout>().unwrap().node.unwrap())
.unwrap();
location.x += parent_location.x;
location.y += parent_location.y;
@@ -44,7 +52,7 @@ pub(crate) fn render_vnode(
let width = layout_to_screen_space(fx + width).round() as u16 - x;
let height = layout_to_screen_space(fy + height).round() as u16 - y;
match &node.node_data.node_type {
match node.node_type() {
NodeType::Text(text) => {
#[derive(Default)]
struct Label<'a> {
@@ -65,7 +73,7 @@ pub(crate) fn render_vnode(
let label = Label {
text,
style: node.state.style.core,
style: node.get::<StyleModifier>().unwrap().core,
};
let area = Rect::new(x, y, width, height);
@@ -82,15 +90,15 @@ pub(crate) fn render_vnode(
frame.render_widget(WidgetWithContext::new(node, cfg), area);
}
for c in rdom.children_ids(node.node_data.node_id).unwrap() {
render_vnode(frame, layout, rdom, &rdom[*c], cfg, location);
for c in node.children().unwrap() {
render_vnode(frame, layout, rdom, c, cfg, location);
}
}
NodeType::Placeholder => unreachable!(),
}
}
impl RinkWidget for &TuiNode {
impl RinkWidget for NodeRef<'_> {
fn render(self, area: Rect, mut buf: RinkBuffer<'_>) {
use tui::symbols::line::*;
@@ -275,10 +283,10 @@ impl RinkWidget for &TuiNode {
for x in area.left()..area.right() {
for y in area.top()..area.bottom() {
let mut new_cell = RinkCell::default();
if let Some(c) = self.state.style.core.bg {
if let Some(c) = self.get::<StyleModifier>().unwrap().core.bg {
new_cell.bg = c;
}
if self.state.focused {
if self.get::<Focused>().unwrap().0 {
new_cell.bg.alpha = 100;
new_cell.bg.color = new_cell.bg.blend(Color::White);
}
@@ -286,7 +294,9 @@ impl RinkWidget for &TuiNode {
}
}
let borders = &self.state.style.modifier.borders;
let style = self.get::<StyleModifier>().unwrap();
let borders = &style.modifier.borders;
let last_edge = &borders.left;
let current_edge = &borders.top;
@@ -303,7 +313,7 @@ impl RinkWidget for &TuiNode {
(last_r * RADIUS_MULTIPLIER[0]) as u16,
(last_r * RADIUS_MULTIPLIER[1]) as u16,
];
let color = current_edge.color.or(self.state.style.core.fg);
let color = current_edge.color.or(style.core.fg);
let mut new_cell = RinkCell::default();
if let Some(c) = color {
new_cell.fg = c;
@@ -338,7 +348,7 @@ impl RinkWidget for &TuiNode {
(last_r * RADIUS_MULTIPLIER[0]) as u16,
(last_r * RADIUS_MULTIPLIER[1]) as u16,
];
let color = current_edge.color.or(self.state.style.core.fg);
let color = current_edge.color.or(style.core.fg);
let mut new_cell = RinkCell::default();
if let Some(c) = color {
new_cell.fg = c;
@@ -373,7 +383,7 @@ impl RinkWidget for &TuiNode {
(last_r * RADIUS_MULTIPLIER[0]) as u16,
(last_r * RADIUS_MULTIPLIER[1]) as u16,
];
let color = current_edge.color.or(self.state.style.core.fg);
let color = current_edge.color.or(style.core.fg);
let mut new_cell = RinkCell::default();
if let Some(c) = color {
new_cell.fg = c;
@@ -408,7 +418,7 @@ impl RinkWidget for &TuiNode {
(last_r * RADIUS_MULTIPLIER[0]) as u16,
(last_r * RADIUS_MULTIPLIER[1]) as u16,
];
let color = current_edge.color.or(self.state.style.core.fg);
let color = current_edge.color.or(style.core.fg);
let mut new_cell = RinkCell::default();
if let Some(c) = color {
new_cell.fg = c;
+12 -20
View File
@@ -32,10 +32,9 @@
use dioxus_native_core::{
layout_attributes::parse_value,
node::OwnedAttributeView,
node_ref::{AttributeMask, NodeMask, NodeView},
Pass, SendAnyMap,
node_ref::{AttributeMaskBuilder, NodeMaskBuilder, NodeView},
Dependancy, Pass, SendAnyMap,
};
use dioxus_native_core_macro::sorted_str_slice;
use taffy::prelude::*;
use crate::style::{RinkColor, RinkStyle};
@@ -52,24 +51,17 @@ impl Pass for StyleModifier {
type NodeDependencies = ();
// todo: seperate each attribute into it's own class
const NODE_MASK: NodeMask =
NodeMask::new_with_attrs(AttributeMask::Static(SORTED_STYLE_ATTRS)).with_element();
const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new()
.with_attrs(AttributeMaskBuilder::Some(SORTED_STYLE_ATTRS))
.with_element();
fn pass<'a>(
&mut self,
node_view: NodeView,
_: <Self::NodeDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>,
parent: Option<
<Self::ParentDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<'a>,
>,
_: Option<
impl Iterator<
Item = <Self::ChildDependencies as dioxus_native_core::Dependancy>::ElementBorrowed<
'a,
>,
>,
>,
_: &SendAnyMap,
node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
context: &SendAnyMap,
) -> bool {
let mut new = StyleModifier::default();
if parent.is_some() {
@@ -615,7 +607,7 @@ fn apply_transition(_name: &str, _value: &str, _style: &mut StyleModifier) {
todo!()
}
const SORTED_STYLE_ATTRS: &[&str] = &sorted_str_slice!([
const SORTED_STYLE_ATTRS: &[&str] = &[
"animation",
"animation-delay",
"animation-direction",
@@ -816,5 +808,5 @@ const SORTED_STYLE_ATTRS: &[&str] = &sorted_str_slice!([
"text-justify",
"text-overflow",
"text-shadow",
"text-transform"
]);
"text-transform",
];