Przeglądaj źródła

fix gaps in layout

Evan Almloff 2 lat temu
rodzic
commit
4be64cb9f0

+ 2 - 4
packages/native-core/src/utils.rs

@@ -125,7 +125,7 @@ impl PersistantElementIter {
 
     /// get the next element
     pub fn next<S: State>(&mut self, rdom: &RealDom<S>) -> 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

+ 9 - 1
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())

+ 4 - 2
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<T> {
     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()
             };

+ 17 - 8
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<InputEvent>,
@@ -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,

+ 16 - 7
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<Size<u32>> {
-        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<Point<u32>> {
         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<Layout> {
+        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),
+            },
+        })
     }
 }

+ 9 - 11
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 {