diff --git a/packages/native-core/src/utils.rs b/packages/native-core/src/utils.rs index 7a55ad6db..3ffe45916 100644 --- a/packages/native-core/src/utils.rs +++ b/packages/native-core/src/utils.rs @@ -125,7 +125,7 @@ impl PersistantElementIter { /// get the next element pub fn next(&mut self, rdom: &RealDom) -> ElementProduced { - let r = if self.stack.is_empty() { + if self.stack.is_empty() { let id = NodeId(0); let new = (id, NodePosition::AtNode); self.stack.push(new); @@ -156,9 +156,7 @@ impl PersistantElementIter { ElementProduced::Progressed(self.pop()) } } - }; - println!("next: {:?}", r); - r + } } /// get the previous element diff --git a/packages/tui/src/hooks.rs b/packages/tui/src/hooks.rs index 197c7ea79..b57b71e13 100644 --- a/packages/tui/src/hooks.rs +++ b/packages/tui/src/hooks.rs @@ -23,7 +23,7 @@ use std::{ use taffy::geometry::{Point, Size}; use taffy::{prelude::Layout, Taffy}; -use crate::FocusState; +use crate::{layout_to_screen_space, FocusState}; use crate::{TuiDom, TuiNode}; pub(crate) struct Event { @@ -243,7 +243,15 @@ impl InnerInputState { ) { fn layout_contains_point(layout: &Layout, point: ScreenPoint) -> bool { let Point { x, y } = layout.location; + let (x, y) = ( + layout_to_screen_space(x).round(), + layout_to_screen_space(y).round(), + ); let Size { width, height } = layout.size; + let (width, height) = ( + layout_to_screen_space(width).round(), + layout_to_screen_space(height).round(), + ); let layout_rect = Rect::new(Point2D::new(x, y), Size2D::new(width, height)); layout_rect.contains(point.cast()) diff --git a/packages/tui/src/layout.rs b/packages/tui/src/layout.rs index 1e14f159c..d863f13d8 100644 --- a/packages/tui/src/layout.rs +++ b/packages/tui/src/layout.rs @@ -7,6 +7,8 @@ use dioxus_native_core::state::ChildDepState; use dioxus_native_core_macro::sorted_str_slice; use taffy::prelude::*; +use crate::screen_to_layout_space; + #[derive(Debug, Clone, Copy, PartialEq)] pub(crate) enum PossiblyUninitalized { Uninitalized, @@ -66,10 +68,10 @@ impl ChildDepState for TaffyLayout { style = Style { size: Size { // characters are 1 point tall - height: Dimension::Points(1.0), + height: Dimension::Points(screen_to_layout_space(1)), // text is as long as it is declared - width: Dimension::Points(char_len as f32), + width: Dimension::Points(screen_to_layout_space(char_len as u16)), }, ..Default::default() }; diff --git a/packages/tui/src/lib.rs b/packages/tui/src/lib.rs index cb000f00e..058dfc7d5 100644 --- a/packages/tui/src/lib.rs +++ b/packages/tui/src/lib.rs @@ -35,6 +35,15 @@ pub use config::*; pub use hooks::*; pub(crate) use node::*; +// the layout space has a multiplier of 10 to minimize rounding errors +pub(crate)fn screen_to_layout_space(screen: u16) -> f32{ + screen as f32 * 10.0 +} + +pub(crate)fn layout_to_screen_space(layout: f32) -> f32{ + layout / 10.0 +} + #[derive(Clone)] pub struct TuiContext { tx: UnboundedSender, @@ -149,22 +158,22 @@ fn render_vdom( if !to_rerender.is_empty() || updated { updated = false; fn resize(dims: Rect, taffy: &mut Taffy, rdom: &TuiDom) { - let width = dims.width; - let height = dims.height; + 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(); // the root node fills the entire area let mut style=*taffy.style(root_node).unwrap(); style.size=Size { - width: Dimension::Points(width as f32), - height: Dimension::Points(height as f32), + width: Dimension::Points(width ), + height: Dimension::Points(height ), }; taffy.set_style(root_node, style).unwrap(); let size =Size { - width: AvailableSpace::Definite(width as f32), - height: AvailableSpace::Definite(height as f32), + width: AvailableSpace::Definite(width), + height: AvailableSpace::Definite(height), }; taffy .compute_layout( @@ -195,8 +204,8 @@ fn render_vdom( Rect { x: 0, y: 0, - width: 100, - height: 100, + width: 1000, + height: 1000, }, &mut taffy.lock().expect("taffy lock poisoned"), &rdom, diff --git a/packages/tui/src/query.rs b/packages/tui/src/query.rs index 15b7fd7f2..3fbcc15fa 100644 --- a/packages/tui/src/query.rs +++ b/packages/tui/src/query.rs @@ -11,7 +11,7 @@ use taffy::{ Taffy, }; -use crate::TuiDom; +use crate::{layout_to_screen_space, TuiDom}; /// 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. @@ -72,19 +72,28 @@ impl<'a> ElementRef<'a> { } pub fn size(&self) -> Option> { - self.layout().map(|l| l.size.map(|v| v as u32)) + self.layout().map(|l| l.size.map(|v| v.round() as u32)) } pub fn pos(&self) -> Option> { self.layout().map(|l| Point { - x: l.location.x as u32, - y: l.location.y as u32, + x: l.location.x.round() as u32, + y: l.location.y.round() as u32, }) } - pub fn layout(&self) -> Option<&Layout> { - self.stretch + pub fn layout(&self) -> Option { + let layout = self + .stretch .layout(self.inner[self.id].state.layout.node.ok()?) - .ok() + .ok(); + layout.map(|layout| Layout { + order: layout.order, + size: layout.size.map(|v| layout_to_screen_space(v)), + location: Point { + x: layout_to_screen_space(layout.location.x), + y: layout_to_screen_space(layout.location.y), + }, + }) } } diff --git a/packages/tui/src/render.rs b/packages/tui/src/render.rs index d779418fa..ef18f2989 100644 --- a/packages/tui/src/render.rs +++ b/packages/tui/src/render.rs @@ -8,6 +8,7 @@ use taffy::{ use tui::{backend::CrosstermBackend, layout::Rect, style::Color}; use crate::{ + layout_to_screen_space, style::{RinkColor, RinkStyle}, style_attributes::{BorderEdge, BorderStyle}, widget::{RinkBuffer, RinkCell, RinkWidget, WidgetWithContext}, @@ -36,15 +37,12 @@ pub(crate) fn render_vnode( location.x += parent_location.x; location.y += parent_location.y; - let Point { mut x, mut y } = location; - x = x.floor(); - y = y.floor(); - let Size { - mut width, - mut height, - } = size; - width = width.ceil(); - height = height.ceil(); + let Point { x: fx, y: fy } = location; + let x = layout_to_screen_space(fx).round() as u16; + let y = layout_to_screen_space(fy).round() as u16; + let Size { width, height } = *size; + 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 { NodeType::Text { text } => { @@ -69,7 +67,7 @@ pub(crate) fn render_vnode( text, style: node.state.style.core, }; - let area = Rect::new(x as u16, y as u16, width as u16, height as u16); + let area = Rect::new(x, y, width, height); // the renderer will panic if a node is rendered out of range even if the size is zero if area.width > 0 && area.height > 0 { @@ -77,7 +75,7 @@ pub(crate) fn render_vnode( } } NodeType::Element { .. } => { - let area = Rect::new(x as u16, y as u16, width as u16, height as u16); + let area = Rect::new(x, y, width, height); // the renderer will panic if a node is rendered out of range even if the size is zero if area.width > 0 && area.height > 0 {