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

wallet/chatedit: resize with wrapped text

darkfi 1 год назад
Родитель
Сommit
a41dfb9611

+ 3 - 0
bin/darkwallet/src/app/node.rs

@@ -268,6 +268,9 @@ pub fn create_chatedit(name: &str) -> SceneNode {
     let prop = Property::new("baseline", PropertyType::Float32, PropertySubType::Pixel);
     node.add_property(prop).unwrap();
 
+    let prop = Property::new("descent", PropertyType::Float32, PropertySubType::Pixel);
+    node.add_property(prop).unwrap();
+
     let mut prop = Property::new("scroll", PropertyType::Float32, PropertySubType::Pixel);
     prop.set_range_f32(0., f32::MAX);
     node.add_property(prop).unwrap();

+ 11 - 72
bin/darkwallet/src/app/schema.rs

@@ -47,12 +47,13 @@ const LIGHTMODE: bool = false;
 
 mod android_ui_consts {
     pub const EDITCHAT_HEIGHT: f32 = 163.;
-    pub const EDITCHAT_BOTTOM_PAD: f32 = 70.;
+    pub const EDITCHAT_BOTTOM_PAD: f32 = 50.;
     pub const EDITCHAT_CURSOR_ASCENT: f32 = 50.;
     pub const EDITCHAT_CURSOR_DESCENT: f32 = 20.;
     pub const EDITCHAT_SELECT_ASCENT: f32 = 40.;
     pub const EDITCHAT_SELECT_DESCENT: f32 = 8.;
     pub const TEXTBAR_BASELINE: f32 = 93.;
+    pub const TEXT_DESCENT: f32 = 20.;
     pub const EDITCHAT_LHS_PAD: f32 = 30.;
     pub const SENDLABEL_WIDTH: f32 = 200.;
     pub const SENDLABEL_LHS_PAD: f32 = 40.;
@@ -89,12 +90,13 @@ mod ui_consts {
     pub const KING_PATH: &str = "assets/king.png";
     pub const BG_PATH: &str = "assets/bg.png";
     pub const EDITCHAT_HEIGHT: f32 = 50.;
-    pub const EDITCHAT_BOTTOM_PAD: f32 = 16.;
+    pub const EDITCHAT_BOTTOM_PAD: f32 = 6.;
     pub const EDITCHAT_CURSOR_ASCENT: f32 = 25.;
     pub const EDITCHAT_CURSOR_DESCENT: f32 = 8.;
     pub const EDITCHAT_SELECT_ASCENT: f32 = 30.;
     pub const EDITCHAT_SELECT_DESCENT: f32 = 10.;
     pub const TEXTBAR_BASELINE: f32 = 34.;
+    pub const TEXT_DESCENT: f32 = 10.;
     pub const EDITCHAT_LHS_PAD: f32 = 20.;
     pub const SENDLABEL_WIDTH: f32 = 120.;
     pub const SENDLABEL_LHS_PAD: f32 = 30.;
@@ -730,12 +732,15 @@ pub(super) async fn make(app: &App, window: SceneNodePtr) {
     let node = create_vector_art("editbox_bg");
     let prop = node.get_property("rect").unwrap();
     prop.set_f32(Role::App, 0, 0.).unwrap();
-    let code = cc.compile("h - EDITCHAT_HEIGHT").unwrap();
+    let code = cc.compile("h - editz_h").unwrap();
     prop.set_expr(Role::App, 1, code).unwrap();
     prop.set_expr(Role::App, 2, expr::load_var("w")).unwrap();
-    prop.set_f32(Role::App, 3, EDITCHAT_HEIGHT).unwrap();
+    let code = cc.compile("editz_h").unwrap();
+    prop.set_expr(Role::App, 3, code).unwrap();
     node.set_property_u32(Role::App, "z_index", 2).unwrap();
 
+    let editbox_bg_rect_prop = prop.clone();
+
     let mut shape = VectorShape::new();
     shape.add_filled_box(
         expr::const_f32(0.),
@@ -818,8 +823,10 @@ pub(super) async fn make(app: &App, window: SceneNodePtr) {
     prop.set_f32(Role::App, 3, EDITCHAT_HEIGHT).unwrap();
 
     chatview_rect_prop.add_depend(&prop, 3, "editz_h");
+    editbox_bg_rect_prop.add_depend(&prop, 3, "editz_h");
 
     node.set_property_f32(Role::App, "baseline", TEXTBAR_BASELINE).unwrap();
+    node.set_property_f32(Role::App, "descent", TEXT_DESCENT).unwrap();
     node.set_property_f32(Role::App, "font_size", FONTSIZE).unwrap();
     //node.set_property_str(Role::App, "text", "hello king!😁🍆jelly 🍆1234").unwrap();
     let prop = node.get_property("text_color").unwrap();
@@ -912,72 +919,4 @@ pub(super) async fn make(app: &App, window: SceneNodePtr) {
 
     let node = node.setup(|me| Button::new(me, app.ex.clone())).await;
     layer_node.clone().link(node);
-
-    // Create a popup layer to show upgrade msg
-    let node = create_layer("upgrade_popup");
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(Role::App, 0, 0.).unwrap();
-    prop.set_f32(Role::App, 1, 0.).unwrap();
-    prop.set_expr(Role::App, 2, expr::load_var("w")).unwrap();
-    let code = cc.compile("h / 2").unwrap();
-    prop.set_expr(Role::App, 3, code).unwrap();
-    node.set_property_bool(Role::App, "is_visible", false).unwrap();
-    node.set_property_u32(Role::App, "z_index", 10).unwrap();
-    let popup_layer_node =
-        node.setup(|me| Layer::new(me, app.render_api.clone(), app.ex.clone())).await;
-    layer_node.clone().link(popup_layer_node.clone());
-
-    // Background for popup
-    let node = create_vector_art("upgradebg");
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(Role::App, 0, 0.).unwrap();
-    prop.set_f32(Role::App, 1, 0.).unwrap();
-    prop.set_expr(Role::App, 2, expr::load_var("w")).unwrap();
-    prop.set_expr(Role::App, 3, expr::load_var("h")).unwrap();
-    node.set_property_u32(Role::App, "z_index", 0).unwrap();
-
-    // Setup the pimpl
-    let verts = vec![
-        ShapeVertex::from_xy(0., 0., [1., 0., 0., 1.]),
-        ShapeVertex::new(expr::load_var("w"), expr::const_f32(0.), [1., 0., 1., 1.]),
-        ShapeVertex::new(expr::const_f32(0.), expr::load_var("h"), [0., 0., 1., 1.]),
-        ShapeVertex::new(expr::load_var("w"), expr::load_var("h"), [1., 1., 0., 1.]),
-    ];
-    let indices = vec![0, 2, 1, 1, 2, 3];
-    let shape = VectorShape { verts, indices };
-    let node =
-        node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
-    popup_layer_node.clone().link(node);
-
-    // Create some text
-    let node = create_text("send_label");
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(Role::App, 0, 10.).unwrap();
-    prop.set_f32(Role::App, 1, 10.).unwrap();
-    prop.set_expr(Role::App, 2, expr::load_var("w")).unwrap();
-    prop.set_expr(Role::App, 3, expr::load_var("h")).unwrap();
-    node.set_property_f32(Role::App, "baseline", TEXTBAR_BASELINE).unwrap();
-    node.set_property_f32(Role::App, "font_size", 2. * FONTSIZE).unwrap();
-    node.set_property_str(Role::App, "text", "YO THERE'S A NEW VERSION!!! UPGRADE TIEM!!!")
-        .unwrap();
-    //node.set_property_str(Role::App, "text", "anon1").unwrap();
-    let prop = node.get_property("text_color").unwrap();
-    prop.set_f32(Role::App, 0, 0.).unwrap();
-    prop.set_f32(Role::App, 1, 1.).unwrap();
-    prop.set_f32(Role::App, 2, 0.94).unwrap();
-    prop.set_f32(Role::App, 3, 1.).unwrap();
-    node.set_property_u32(Role::App, "z_index", 1).unwrap();
-
-    let node = node
-        .setup(|me| {
-            Text::new(
-                me,
-                window_scale.clone(),
-                app.render_api.clone(),
-                app.text_shaper.clone(),
-                app.ex.clone(),
-            )
-        })
-        .await;
-    popup_layer_node.clone().link(node);
 }

+ 55 - 28
bin/darkwallet/src/ui/chatedit.rs

@@ -147,6 +147,7 @@ pub struct ChatEdit {
     max_height: PropertyFloat32,
     rect: PropertyRect,
     baseline: PropertyFloat32,
+    descent: PropertyFloat32,
     scroll: PropertyFloat32,
     scroll_speed: PropertyFloat32,
     cursor_pos: PropertyUint32,
@@ -201,6 +202,7 @@ impl ChatEdit {
         let max_height = PropertyFloat32::wrap(node_ref, Role::Internal, "max_height", 0).unwrap();
         let rect = PropertyRect::wrap(node_ref, Role::Internal, "rect").unwrap();
         let baseline = PropertyFloat32::wrap(node_ref, Role::Internal, "baseline", 0).unwrap();
+        let descent = PropertyFloat32::wrap(node_ref, Role::Internal, "descent", 0).unwrap();
         let scroll = PropertyFloat32::wrap(node_ref, Role::Internal, "scroll", 0).unwrap();
         let scroll_speed =
             PropertyFloat32::wrap(node_ref, Role::Internal, "scroll_speed", 0).unwrap();
@@ -252,6 +254,7 @@ impl ChatEdit {
             max_height,
             rect,
             baseline: baseline.clone(),
+            descent,
             scroll: scroll.clone(),
             scroll_speed,
             cursor_pos,
@@ -326,8 +329,7 @@ impl ChatEdit {
 
         let total_height = wrapped_lines_len as f32 * baseline;
         //let height = std::cmp::min(total_height, self.max_height.get());
-        let height = total_height;
-        debug!("height = {height}");
+        let height = total_height + self.descent.get();
 
         self.rect.prop().set_f32(Role::Internal, 3, height);
 
@@ -341,7 +343,6 @@ impl ChatEdit {
                 ("rect_h".to_string(), height),
             ],
         );
-        debug!("rect = {:?}", self.rect.get());
 
         let mut clip = self.rect.get();
         clip.x = 0.;
@@ -416,43 +417,60 @@ impl ChatEdit {
         mesh.alloc(&self.render_api).draw_untextured()
     }
 
-    fn cursor_px_offset(&self) -> f32 {
+    fn get_cursor_pos(&self) -> Point {
         assert!(self.is_focused.get());
 
-        let (cursor_pos, glyphs) = {
+        let font_size = self.font_size.get();
+        let window_scale = self.window_scale.get();
+        let baseline = self.baseline.get();
+
+        let width = self.rect.prop().get_f32(2).unwrap();
+
+        let (cursor_pos, wrap_glyphs) = {
             let editable = self.editable.lock().unwrap();
             let rendered = editable.render();
             let cursor_pos = editable.get_cursor_pos(&rendered);
-            (cursor_pos, rendered.glyphs)
+            let glyphs = text::wrap(width, font_size, window_scale, &rendered.glyphs);
+            (cursor_pos, glyphs)
         };
 
-        let font_size = self.font_size.get();
-        let window_scale = self.window_scale.get();
-        let baseline = self.baseline.get();
-        let scroll = self.scroll.get();
-        // Add composer glyphs too
-        let glyph_pos_iter = GlyphPositionIter::new(font_size, window_scale, &glyphs, baseline);
+        // Convert cursor glyph pos to a coord (x, y)
+        let mut glyph_idx = 0;
         // Used for drawing the cursor when it's at the end of the line.
         let mut rhs = 0.;
+        let mut y_pos = 0.;
 
         if cursor_pos == 0 {
-            return 0.;
+            return Point::zero();
         }
 
-        for (glyph_idx, (mut glyph_rect, glyph)) in glyph_pos_iter.zip(glyphs.iter()).enumerate() {
-            glyph_rect.x -= scroll;
+        for (line_idx, glyphs) in wrap_glyphs.iter().enumerate() {
+            debug!("glyph_idx = {glyph_idx}, y_pos = {y_pos}, rhs = {rhs}");
+            let glyph_pos_iter = GlyphPositionIter::new(font_size, window_scale, glyphs, baseline);
 
-            if cursor_pos == glyph_idx {
-                return glyph_rect.x;
+            if line_idx > 0 {
+                // +1 for the EOL whitespace
+                glyph_idx += 1;
+                y_pos += baseline;
             }
 
-            rhs = glyph_rect.rhs();
-        }
+            for (mut glyph_rect, glyph) in glyph_pos_iter.zip(glyphs.iter()) {
+                if cursor_pos == glyph_idx {
+                    let rhs = glyph_rect.rhs();
+                    debug!("retvrn {rhs}, {y_pos}");
+                    return Point::new(rhs, y_pos)
+                }
 
-        assert!(cursor_pos == glyphs.len());
+                rhs = glyph_rect.rhs();
 
-        rhs += eol_nudge(font_size, &glyphs);
-        rhs
+                glyph_idx += 1;
+            }
+        }
+
+        if !wrap_glyphs.is_empty() {
+            rhs += eol_nudge(font_size, &wrap_glyphs.last().unwrap());
+        }
+        Point::new(rhs, y_pos)
     }
 
     fn mark_selected_glyphs(&self, glyphs: &Vec<Glyph>, selections: Vec<Selection>) -> Vec<bool> {
@@ -1209,11 +1227,7 @@ impl ChatEdit {
 
         let rect_w = self.rect.get().w;
 
-        let mut cursor_pos = Point::zero();
-        cursor_pos.x += self.cursor_px_offset();
-        if cursor_pos.x > rect_w {
-            return vec![]
-        }
+        let cursor_pos = self.get_cursor_pos();
         cursor_instrs.push(GfxDrawInstruction::Move(cursor_pos));
 
         let cursor_mesh = {
@@ -1439,10 +1453,23 @@ impl UIObject for ChatEdit {
         let window_scale = self.window_scale.get();
         let baseline = self.baseline.get();
 
+        // Convert y offset within rect to an x off based off line wrapping
+        let y_off = mouse_pos.y - rect.y;
+        let mut x_off = 0.;
+
+        let width = self.rect.prop().get_f32(2).unwrap();
+        let rendered = self.editable.lock().unwrap().render();
+        let wrapped_glyphs = text::wrap(width, font_size, window_scale, &rendered.glyphs);
+        for glyphs in wrapped_glyphs {
+            let glyph_pos_iter = GlyphPositionIter::new(font_size, window_scale, &glyphs, baseline);
+            let last_rect = glyph_pos_iter.last().unwrap();
+            x_off += last_rect.rhs();
+        }
+
         {
             let mut editable = self.editable.lock().unwrap();
             let rendered = editable.render();
-            let x = mouse_pos.x - rect.x + self.scroll.get();
+            let x = x_off + mouse_pos.x - rect.x + self.scroll.get();
 
             let cpos = rendered.x_to_pos(x, font_size, window_scale, baseline);
             let cidx = rendered.pos_to_idx(cpos);

+ 0 - 1
bin/darkwallet/src/ui/vector_art/mod.rs

@@ -106,7 +106,6 @@ impl VectorArt {
 
         //debug!(target: "ui::vector_art", "=> {verts:#?}");
         let vertex_buffer = self.render_api.new_vertex_buffer(verts);
-        // You are one lazy motherfucker
         let index_buffer = self.render_api.new_index_buffer(self.shape.indices.clone());
         let mesh = GfxDrawMesh {
             vertex_buffer,