Browse Source

Correct display of text cursor at end of a text edit widget.

Kestrel 1 tháng trước cách đây
mục cha
commit
f54c24213f
3 tập tin đã thay đổi với 63 bổ sung44 xóa
  1. 35 1
      src/render.rs
  2. 24 41
      src/widget/text_edit.rs
  3. 4 2
      src/window.rs

+ 35 - 1
src/render.rs

@@ -1,6 +1,6 @@
 use kahlo::{
     colour::Colour,
-    math::PixelBox,
+    math::{PixelBox, PixelSideOffsets},
     prelude::{BitmapAccess, KahloOps},
 };
 
@@ -95,6 +95,19 @@ impl<'l, 'r: 'l, 'data: 'r> NodeRenderTarget<'l, 'r, 'data> {
         self
     }
 
+    pub fn fill_relative_box(mut self, mut bx: PixelBox, cc: ColourChoice) -> Self {
+        if let Self::Render { rt, area, .. } = &mut self {
+            let shift = area.min.to_vector();
+            bx.min += shift;
+            bx.max += shift;
+            if let Some(region) = bx.intersection(area) {
+                rt.target
+                    .fill_region(region, cc.get(rt.theme, ColourChoice::Background));
+            }
+        }
+        self
+    }
+
     pub fn draw_foreground_outline(self) -> Self {
         self
     }
@@ -129,4 +142,25 @@ impl<'l, 'r: 'l, 'data: 'r> NodeRenderTarget<'l, 'r, 'data> {
         }
         self
     }
+
+    pub fn seq(self, f: impl FnOnce(NodeRenderTarget)) -> Self {
+        if let Self::Render { rt, area, lnode } = self {
+            f(NodeRenderTarget::Render { rt, area, lnode });
+            NodeRenderTarget::Render { rt, area, lnode }
+        } else {
+            self
+        }
+    }
+
+    pub fn shrink(self, by: PixelSideOffsets) -> Self {
+        if let Self::Render { rt, area, lnode } = self {
+            Self::Render {
+                rt,
+                lnode,
+                area: area.inner_box(by),
+            }
+        } else {
+            self
+        }
+    }
 }

+ 24 - 41
src/widget/text_edit.rs

@@ -1,10 +1,14 @@
 use crate::{
     input::MouseButton,
-    layout::{HorizontalAlignment, LayoutNode, LayoutNodeAccess, LayoutTreeNode, LeafLayoutNode, SizePolicy},
+    layout::{
+        HorizontalAlignment, LayoutNode, LayoutNodeAccess, LayoutTreeNode, LeafLayoutNode,
+        SizePolicy,
+    },
     prelude::*,
     render::{ColourChoice, RenderTarget, TextCache},
     ui::UIHandle,
 };
+use kahlo::math::{PixelBox, PixelPoint, PixelSideOffsets, PixelSize};
 use winit::keyboard::{Key, NamedKey};
 
 pub enum CursorPosition {
@@ -14,8 +18,7 @@ pub enum CursorPosition {
 }
 
 pub struct TextEdit<C: Component> {
-    lnode: LayoutNode,
-    cursor_node: LeafLayoutNode,
+    lnode: LeafLayoutNode,
     text: TextCache,
     cursor_pos: CursorPosition,
     onchange: Option<Box<dyn Fn(&str) -> Option<C::Msg>>>,
@@ -30,22 +33,15 @@ impl<C: Component> TextEdit<C> {
             .set_width_policy(SizePolicy::expanding(1))
             .set_height_policy(SizePolicy::fixed(minheight));
 
-        let mut cursor_node = uih.new_layout_node();
-        cursor_node
-            .set_width_policy(SizePolicy::fixed(2))
-            .set_height_policy(SizePolicy::fixed(minheight))
-            .set_halign(HorizontalAlignment::Left);
-
         Self {
-            lnode,
-            cursor_node: LeafLayoutNode::new(cursor_node),
+            lnode: LeafLayoutNode::new(lnode),
             text: TextCache::new_with_font_and_size(
                 uih.theme().ui_font.clone(),
                 uih.theme().ui_font_size,
             ),
             cursor_pos: CursorPosition::End,
             onchange: None,
-            focused: false
+            focused: false,
         }
     }
 
@@ -54,24 +50,8 @@ impl<C: Component> TextEdit<C> {
     }
 
     /*pub fn set_cursor_position(&mut self, to: CursorPosition) {
-        
-    }*/
-}
 
-impl<C: Component> LayoutTreeNode<()> for TextEdit<C> {
-    fn child(&self, ndx: usize) -> Option<LayoutNodeAccess<'_>> {
-        if ndx == 0 {
-            Some(self.cursor_node.access())
-        } else {
-            None
-        }
-    }
-    fn child_count(&self) -> usize {
-        1
-    }
-    fn current_node(&self) -> &LayoutNode {
-        &self.lnode
-    }
+    }*/
 }
 
 impl<C: Component> Widget<C> for TextEdit<C> {
@@ -113,18 +93,14 @@ impl<C: Component> Widget<C> for TextEdit<C> {
             .is_click()
         {
             istate.focus_on(self.lnode.id());
-            self.focused = true;
             println!("click offset: {:?}", istate.mouse.pos - render_area.min);
-
-            let cbar_offset = self.text.size_hint().width;
-            self.cursor_node.margin_mut().left = cbar_offset;
         }
 
         let was_focused = self.focused;
         self.focused = istate.is_focused(self.lnode.id());
 
         if self.focused != was_focused {
-            self.cursor_node.render_needed();
+            println!("self.focused is now {}", self.focused);
             self.lnode.render_needed();
         }
 
@@ -132,7 +108,7 @@ impl<C: Component> Widget<C> for TextEdit<C> {
     }
 
     fn layout_node(&self) -> LayoutNodeAccess {
-        LayoutNodeAccess::new(self)
+        self.lnode.access()
     }
     fn layout_node_mut(&mut self) -> &mut LayoutNode {
         &mut self.lnode
@@ -142,11 +118,18 @@ impl<C: Component> Widget<C> for TextEdit<C> {
         target
             .with_node(&self.lnode)
             .fill(ColourChoice::Background)
-            .simple_text(&self.text, ColourChoice::Foreground);
-
-        if self.focused {
-            target.with_node(&self.cursor_node)
-                .fill(ColourChoice::Foreground);
-        }
+            .simple_text(&self.text, ColourChoice::Foreground)
+            .seq(|target| {
+                if self.focused {
+                    let cbar_offset = self.text.size_hint().width;
+                    target.fill_relative_box(
+                        PixelBox::from_origin_and_size(
+                            PixelPoint::new(cbar_offset, 0),
+                            PixelSize::new(2, self.text.size_hint().height),
+                        ),
+                        ColourChoice::Foreground,
+                    );
+                }
+            });
     }
 }

+ 4 - 2
src/window.rs

@@ -211,9 +211,11 @@ impl<WC: WindowComponent> WindowStateAccess for RefCell<WindowState<WC>> {
 
         // special handling for the F12 key, which dumps the current layout tree
         if key == winit::keyboard::Key::Named(winit::keyboard::NamedKey::F12) {
-            let layout = WindowLayoutHelper::new(&win.root_node, win.wc.root_widget().layout_node());
+            let layout =
+                WindowLayoutHelper::new(&win.root_node, win.wc.root_widget().layout_node());
 
-            let mut tree_file = std::io::BufWriter::new(std::fs::File::create("patina-tree.json").unwrap());
+            let mut tree_file =
+                std::io::BufWriter::new(std::fs::File::create("patina-tree.json").unwrap());
 
             crate::layout::dump_tree_json(LayoutNodeAccess::new(&layout), &mut tree_file).unwrap();
         } else {