Просмотр исходного кода

app: apply cursor scroll working for selections

darkfi 10 месяцев назад
Родитель
Сommit
98a381e9e6
4 измененных файлов с 58 добавлено и 47 удалено
  1. 6 12
      bin/app/src/app/node.rs
  2. 11 7
      bin/app/src/app/schema/test.rs
  3. 31 10
      bin/app/src/ui/edit/behave.rs
  4. 10 18
      bin/app/src/ui/edit/mod.rs

+ 6 - 12
bin/app/src/app/node.rs

@@ -363,6 +363,12 @@ pub fn create_baseedit(name: &str) -> SceneNode {
     prop.set_range_f32(0., f32::MAX);
     node.add_property(prop).unwrap();
 
+    let mut prop = Property::new("padding", PropertyType::Float32, PropertySubType::Pixel);
+    prop.set_ui_text("Inner Padding", "Padding inside - top, right, bottom, left");
+    prop.set_range_f32(0., f32::MAX);
+    prop.set_array_len(4);
+    node.add_property(prop).unwrap();
+
     // Deprecate this
     // No need to be a property
     let mut prop = Property::new("scroll", PropertyType::Float32, PropertySubType::Pixel);
@@ -489,12 +495,6 @@ pub fn create_singleline_edit(name: &str) -> SceneNode {
     prop.set_ui_text("Content Height", "The actual text's inner height");
     node.add_property(prop).unwrap();
 
-    let mut prop = Property::new("padding", PropertyType::Float32, PropertySubType::Pixel);
-    prop.set_ui_text("Inner Padding", "Top and bottom padding inside");
-    prop.set_range_f32(0., f32::MAX);
-    prop.set_array_len(2);
-    node.add_property(prop).unwrap();
-
     node
 }
 
@@ -511,12 +511,6 @@ pub fn create_multiline_edit(name: &str) -> SceneNode {
     prop.set_ui_text("Content Height", "The actual text's inner height");
     node.add_property(prop).unwrap();
 
-    let mut prop = Property::new("padding", PropertyType::Float32, PropertySubType::Pixel);
-    prop.set_ui_text("Inner Padding", "Top and bottom padding inside");
-    prop.set_range_f32(0., f32::MAX);
-    prop.set_array_len(2);
-    node.add_property(prop).unwrap();
-
     node
 }
 

+ 11 - 7
bin/app/src/app/schema/test.rs

@@ -385,8 +385,8 @@ pub async fn make(app: &App, window: SceneNodePtr, i18n_fish: &I18nBabelFish) {
     */
 
     // Text edit
-    let node = create_singleline_edit("editz");
-    //let node = create_multiline_edit("editz");
+    //let node = create_singleline_edit("editz");
+    let node = create_multiline_edit("editz");
     node.set_property_bool(atom, Role::App, "is_active", true).unwrap();
     node.set_property_bool(atom, Role::App, "is_focused", true).unwrap();
 
@@ -416,12 +416,16 @@ pub async fn make(app: &App, window: SceneNodePtr, i18n_fish: &I18nBabelFish) {
     let prop = node.get_property("padding").unwrap();
     prop.set_f32(atom, Role::App, 0, 20.).unwrap();
     prop.set_f32(atom, Role::App, 1, 20.).unwrap();
+    prop.set_f32(atom, Role::App, 2, 20.).unwrap();
+    prop.set_f32(atom, Role::App, 3, 20.).unwrap();
 
     #[cfg(target_os = "android")]
     {
-        let prop = node.get_property("padding").unwrap();
-        prop.set_f32(atom, Role::App, 0, 80.).unwrap();
-        prop.set_f32(atom, Role::App, 1, 80.).unwrap();
+        //let prop = node.get_property("padding").unwrap();
+        //prop.set_f32(atom, Role::App, 0, 80.).unwrap();
+        //prop.set_f32(atom, Role::App, 1, 80.).unwrap();
+        //prop.set_f32(atom, Role::App, 2, 80.).unwrap();
+        //prop.set_f32(atom, Role::App, 3, 80.).unwrap();
 
         node.set_property_f32(atom, Role::App, "font_size", 60.).unwrap();
     }
@@ -461,8 +465,8 @@ pub async fn make(app: &App, window: SceneNodePtr, i18n_fish: &I18nBabelFish) {
                 me,
                 window_scale.clone(),
                 app.render_api.clone(),
-                BaseEditType::SingleLine,
-                //BaseEditType::MultiLine,
+                //BaseEditType::SingleLine,
+                BaseEditType::MultiLine,
             )
         })
         .await;

+ 31 - 10
bin/app/src/ui/edit/behave.rs

@@ -1,5 +1,4 @@
 /* This file is part of DarkFi (https://dark.fi)
- *
  * Copyright (C) 2020-2025 Dyne.org foundation
  *
  * This program is free software: you can redistribute it and/or modify
@@ -133,8 +132,11 @@ impl EditorBehavior for MultiLine {
             )
             .unwrap();
 
+        let pad_right = self.padding.get_f32(1).unwrap();
+        let pad_left = self.padding.get_f32(3).unwrap();
+
         // Use the width to adjust the height calcs
-        let rect_w = self.rect.get_width();
+        let rect_w = self.rect.get_width() - pad_left - pad_right;
         let content_height = {
             let mut editor = self.lock_editor().await;
             editor.set_width(rect_w);
@@ -162,8 +164,11 @@ impl EditorBehavior for MultiLine {
     }
 
     async fn apply_cursor_scroll(&self, atom: &mut PropertyAtomicGuard) {
+        //let pad_top = self.padding_top();
+        let pad_bot = self.padding_bottom();
+
         let mut scroll = self.scroll.get();
-        let rect_h = self.rect.get_height();
+        let rect_h = self.max_height.get() - pad_bot;
         let cursor_y0 = self.get_cursor_pos().await.y;
         let cursor_h = self.baseline.get() + self.cursor_descent.get();
         // The bottom
@@ -171,13 +176,15 @@ impl EditorBehavior for MultiLine {
         //t!("apply_cursor_scrolling() cursor = [{cursor_y0}, {cursor_y1}] rect_h={rect_h} scroll={scroll}");
 
         if cursor_y1 > rect_h + scroll {
+            let max_scroll = self.max_scroll().await;
             //t!("  cursor bottom below rect");
             // We want cursor_y1 = rect_h + scroll by adjusting scroll
-            scroll = cursor_y1 - rect_h;
+            scroll = (cursor_y1 - rect_h).clamp(0., max_scroll);
             self.scroll.set(atom, scroll);
         } else if cursor_y0 < scroll {
             //t!("  cursor top above rect");
-            scroll = cursor_y0;
+            scroll = cursor_y0.max(0.);
+            assert!(scroll >= 0.);
             self.scroll.set(atom, scroll);
         }
     }
@@ -203,10 +210,13 @@ impl EditorBehavior for MultiLine {
     fn inner_pos(&self) -> Point {
         let pad_top = self.padding_top();
         let pad_bot = self.padding_bottom();
+        let pad_left = self.padding.get_f32(3).unwrap();
+
         let content_height = self.content_height.get();
         let outer_height = content_height + pad_top + pad_bot;
         let rect_h = self.rect.get_height();
         let mut inner_pos = Point::zero();
+        inner_pos.x = pad_left;
         if outer_height < rect_h {
             // Min was applied to clip. Center content inside the rect.
             inner_pos.y = (rect_h - content_height) / 2.;
@@ -229,6 +239,7 @@ pub(super) struct SingleLine {
     pub content_height: PropertyFloat32,
     pub scroll: PropertyFloat32,
     pub rect: PropertyRect,
+    pub padding: PropertyPtr,
     pub cursor_width: PropertyFloat32,
     pub parent_rect: Arc<SyncMutex<Option<Rectangle>>>,
     pub editor: Arc<AsyncMutex<Option<Editor>>>,
@@ -266,14 +277,20 @@ impl EditorBehavior for SingleLine {
     }
 
     async fn apply_cursor_scroll(&self, atom: &mut PropertyAtomicGuard) {
-        let scroll = self.scroll.get();
-        let rect_w = self.rect.get_width();
-        let cursor_x0 = self.lock_editor().await.get_cursor_pos().x;
+        let pad_right = self.padding.get_f32(1).unwrap();
+        let pad_left = self.padding.get_f32(3).unwrap();
+        let mut scroll = self.scroll.get();
+        let rect_w = self.rect.get_width() - pad_right;
+        let cursor_x0 = self.lock_editor().await.get_cursor_pos().x + pad_left;
         let cursor_x1 = cursor_x0 + self.cursor_width.get();
+
         if cursor_x0 < scroll {
+            assert!(cursor_x0 >= 0.);
+            scroll = cursor_x0.max(0.);
             self.scroll.set(atom, cursor_x0);
         } else if cursor_x1 > rect_w + scroll {
-            let scroll = cursor_x1 - rect_w;
+            let max_scroll = self.max_scroll().await;
+            let scroll = (cursor_x1 - rect_w).clamp(0., max_scroll);
             self.scroll.set(atom, scroll);
         }
     }
@@ -283,15 +300,19 @@ impl EditorBehavior for SingleLine {
     }
 
     async fn max_scroll(&self) -> f32 {
+        let pad_right = self.padding.get_f32(1).unwrap();
+        let pad_left = self.padding.get_f32(3).unwrap();
         let rect_w = self.rect.get_width();
         let content_w = self.lock_editor().await.width() + self.cursor_width.get();
-        (content_w - rect_w).max(0.)
+        (pad_left + pad_right + content_w - rect_w).max(0.)
     }
 
     fn inner_pos(&self) -> Point {
+        let pad_left = self.padding.get_f32(3).unwrap();
         let content_height = self.content_height.get();
         let rect_h = self.rect.get_height();
         let mut inner_pos = Point::zero();
+        inner_pos.x = pad_left;
         inner_pos.y = (rect_h - content_height) / 2.;
         inner_pos
     }

+ 10 - 18
bin/app/src/ui/edit/mod.rs

@@ -319,6 +319,7 @@ impl BaseEdit {
                 content_height: content_height.clone(),
                 scroll: scroll.clone(),
                 rect: rect.clone(),
+                padding: padding.clone(),
                 cursor_width: cursor_width.clone(),
                 parent_rect: parent_rect.clone(),
                 editor: editor.clone(),
@@ -406,13 +407,6 @@ impl BaseEdit {
         self.node.upgrade().unwrap()
     }
 
-    fn padding_top(&self) -> f32 {
-        self.padding.get_f32(0).unwrap()
-    }
-    fn padding_bottom(&self) -> f32 {
-        self.padding.get_f32(1).unwrap()
-    }
-
     fn abs_to_local(&self, point: &mut Point) {
         let rect = self.rect.get();
         *point -= rect.pos();
@@ -928,7 +922,6 @@ impl BaseEdit {
     async fn redraw_scroll(&self, batch_id: BatchGuardId) {
         let timest = unixtime();
         let rect = self.rect.get();
-        let scroll = self.scroll.get();
 
         let phone_sel_instrs = self.regen_phone_select_handle_mesh().await;
 
@@ -994,16 +987,20 @@ impl BaseEdit {
             return vec![]
         }
 
-        let padding_top = self.padding_top();
-        let padding_bottom = self.padding_bottom();
-
         let mut rect = self.rect.get().with_zero_pos();
 
         let mut mesh = MeshBuilder::new(gfxtag!("chatedit_bg"));
         mesh.draw_outline(&rect, [0., 1., 0., 1.], 1.);
 
-        rect.y = padding_top;
-        rect.h -= padding_top + padding_bottom;
+        let pad_top = self.padding.get_f32(0).unwrap();
+        let pad_right = self.padding.get_f32(1).unwrap();
+        let pad_bottom = self.padding.get_f32(2).unwrap();
+        let pad_left = self.padding.get_f32(3).unwrap();
+
+        rect.x = pad_left;
+        rect.y = pad_top;
+        rect.w -= pad_left + pad_right;
+        rect.h -= pad_top + pad_bottom;
         mesh.draw_outline(&rect, [0., 1., 0., 0.5], 1.);
 
         vec![DrawInstruction::Draw(mesh.alloc(&self.render_api).draw_untextured())]
@@ -1067,12 +1064,7 @@ impl BaseEdit {
 
     async fn make_draw_calls(&self, _trace_id: u32, atom: &mut PropertyAtomicGuard) -> DrawUpdate {
         self.behave.eval_rect(atom).await;
-
         let rect = self.rect.get();
-        let max_scroll = self.behave.max_scroll().await;
-        if self.scroll.get() > max_scroll {
-            self.scroll.set(atom, max_scroll);
-        }
 
         let cursor_instrs = self.get_cursor_instrs().await;
         let txt_instrs = self.regen_txt_mesh().await;