Sfoglia il codice sorgente

app/edit: adjust action bar overlay so its always right adjusted and never crosses RHS of the editor

jkds 6 mesi fa
parent
commit
c6481578d0

+ 0 - 1
bin/app/src/app/node.rs

@@ -392,7 +392,6 @@ pub fn create_baseedit(name: &str) -> SceneNode {
 
     node.add_signal("enter_pressed", "Enter key pressed", vec![]).unwrap();
     node.add_signal("focus_request", "Request to gain focus", vec![]).unwrap();
-    node.add_signal("paste_request", "Request to show paste dialog", vec![]).unwrap();
 
     // Used by emoji_picker
     node.add_method("insert_text", vec![("text", "Text", CallArgType::Str)], None).unwrap();

+ 0 - 4
bin/app/src/app/schema/chat.rs

@@ -48,8 +48,6 @@ use super::{ColorScheme, COLOR_SCHEME};
 
 #[cfg(any(target_os = "android", feature = "emulate-android"))]
 mod android_ui_consts {
-    use crate::gfx::{Point, Rectangle};
-
     pub const CHANNEL_LABEL_Y: f32 = 30.;
     pub const BACKARROW_SCALE: f32 = 30.;
     pub const BACKARROW_X: f32 = 50.;
@@ -112,8 +110,6 @@ mod ui_consts {
     not(feature = "emulate-android")
 ))]
 mod ui_consts {
-    use crate::gfx::{Point, Rectangle};
-
     // Chat UI
     pub const CHANNEL_LABEL_Y: f32 = 12.;
     pub const BACKARROW_SCALE: f32 = 15.;

+ 8 - 0
bin/app/src/gfx/linalg.rs

@@ -157,6 +157,14 @@ impl Mul<f32> for Point {
     }
 }
 
+impl Div<f32> for Point {
+    type Output = Self;
+
+    fn div(self, div: f32) -> Self {
+        Point::new(self.x / div, self.y / div)
+    }
+}
+
 #[derive(Clone, Copy, SerialEncodable, SerialDecodable)]
 pub struct Rectangle {
     pub x: f32,

+ 16 - 3
bin/app/src/gfx/mod.rs

@@ -576,6 +576,7 @@ struct GfxDrawCall {
 }
 
 struct OverlayDefer {
+    scale: f32,
     pos: Point,
     instrs: Vec<GfxDrawInstruction>,
 }
@@ -614,8 +615,16 @@ impl<'a> RenderContext<'a> {
     }
 
     fn draw_overlays(&mut self) {
+        let (screen_w, screen_h) = miniquad::window::screen_size();
+
         let overlays = std::mem::take(&mut self.overlays);
         for overlay in overlays {
+            self.view = Rectangle::new(0., 0., screen_w, screen_h);
+            self.scale = overlay.scale;
+            self.view.w /= self.scale;
+            self.view.h /= self.scale;
+            self.apply_view();
+
             self.cursor = overlay.pos;
             self.apply_model();
 
@@ -788,9 +797,13 @@ impl<'a> RenderContext<'a> {
                         d!("{ws}set_pipeline({pipeline:?})");
                     }
                 }
-               GfxDrawInstruction::Overlay(instrs) => {
-                    let pos = self.view.pos() + (self.cursor * self.scale);
-                    self.overlays.push(OverlayDefer { pos, instrs: instrs.clone() });
+                GfxDrawInstruction::Overlay(instrs) => {
+                    let pos = self.view.pos() / self.scale + self.cursor;
+                    self.overlays.push(OverlayDefer {
+                        scale: self.scale,
+                        pos,
+                        instrs: instrs.clone(),
+                    });
                 }
             }
         }

+ 7 - 0
bin/app/src/text/editor/android.rs

@@ -220,6 +220,13 @@ impl Editor {
         self.input.set_select(select_start, select_end);
     }
 
+    pub fn select_all(&mut self) {
+        let text_len = self.state.text.len();
+        self.state.select = (0, text_len);
+        self.state.compose = None;
+        self.input.set_select(0, text_len);
+    }
+
     #[allow(dead_code)]
     pub fn buffer(&self) -> String {
         self.state.text.clone()

+ 4 - 0
bin/app/src/text/editor/parley.rs

@@ -141,6 +141,10 @@ impl Editor {
         self.driver().select_byte_range(select_start, select_end);
     }
 
+    pub fn select_all(&mut self) {
+        self.driver().select_all();
+    }
+
     #[allow(dead_code)]
     pub fn buffer(&self) -> String {
         self.editor.raw_text().to_string()

+ 27 - 15
bin/app/src/ui/edit/action.rs

@@ -41,13 +41,12 @@ pub struct Menu {
     padding: f32,
     spacing: f32,
     window_scale: f32,
-    pos: Point,
+    pub pos: Point,
     items: Vec<MenuItem>,
 }
 
 impl Menu {
     pub fn new(
-        pos: Point,
         font_size: f32,
         fg_color: Color,
         bg_color: Color,
@@ -55,7 +54,16 @@ impl Menu {
         spacing: f32,
         window_scale: f32,
     ) -> Self {
-        Self { font_size, fg_color, bg_color, padding, spacing, window_scale, pos, items: vec![] }
+        Self {
+            font_size,
+            fg_color,
+            bg_color,
+            padding,
+            spacing,
+            window_scale,
+            pos: Point::zero(),
+            items: vec![],
+        }
     }
 
     pub fn add(&mut self, label: &str, action: u32) {
@@ -74,18 +82,21 @@ impl Menu {
 
         let x_offset = match self.items.last() {
             Some(item) => item.rect.rhs() + self.spacing,
-            None => self.pos.x,
+            None => 0.,
         };
 
-        let rect = Rectangle::new(
-            x_offset,
-            self.pos.y - item_height,
-            item_width + 2. * self.padding,
-            item_height,
-        );
+        let rect =
+            Rectangle::new(x_offset, -item_height, item_width + 2. * self.padding, item_height);
 
         self.items.push(MenuItem { layout, action_id: action, rect });
     }
+
+    pub fn total_width(&self) -> f32 {
+        match self.items.last() {
+            Some(item) => item.rect.rhs(),
+            None => 0.,
+        }
+    }
 }
 
 pub struct ActionMode {
@@ -106,12 +117,13 @@ impl ActionMode {
 
     /// Returns `Some(n)` if item n is selected.
     pub fn interact(&self, pos: Point) -> Option<u32> {
-        let Some(menu) = std::mem::take(&mut *self.menu.lock()) else {
-            return None
-        };
+        let menu = std::mem::take(&mut *self.menu.lock())?;
+
+        let local_pos = pos - menu.pos;
+        //d!("interact: pos={:?}, menu.pos={:?}, local_pos={:?}", pos, menu.pos, local_pos);
 
         for item in &menu.items {
-            if item.rect.contains(pos) {
+            if item.rect.contains(local_pos) {
                 d!("Action clicked: {}", item.action_id);
                 return Some(item.action_id);
             }
@@ -125,7 +137,7 @@ impl ActionMode {
     pub fn get_instrs(&self) -> Vec<DrawInstruction> {
         let Some(menu) = &*self.menu.lock() else { return vec![] };
 
-        let mut instrs = vec![];
+        let mut instrs = vec![DrawInstruction::Move(menu.pos)];
 
         for item in &menu.items {
             // Used to reset the pos again

+ 25 - 11
bin/app/src/ui/edit/mod.rs

@@ -679,8 +679,9 @@ impl BaseEdit {
                     }
                 }
                 ACTION_SELALL => {
-                    self.editor.lock().driver().select_all();
-                    if let Some(seltext) = self.editor.lock().selected_text() {
+                    let mut editor = self.editor.lock();
+                    editor.select_all();
+                    if let Some(seltext) = editor.selected_text() {
                         self.select_text.clone().set_str(atom, Role::Internal, 0, seltext).unwrap();
                     }
                 }
@@ -790,9 +791,7 @@ impl BaseEdit {
         match &touch_state {
             TouchStateAction::Inactive => return false,
             TouchStateAction::StartSelect => {
-                let cursor_pos = self.get_cursor_pos();
                 let mut menu = action::Menu::new(
-                    cursor_pos,
                     self.font_size.get(),
                     self.action_fg_color.get(),
                     self.action_bg_color.get(),
@@ -807,6 +806,8 @@ impl BaseEdit {
 
                 if self.text.get().is_empty() {
                     menu.add("Paste", ACTION_PASTE);
+                    // Set the menu pos to the current cursor pos
+                    menu.pos = self.get_cursor_pos();
 
                     self.touch_info.lock().state = TouchStateAction::Inactive;
                 } else {
@@ -818,6 +819,19 @@ impl BaseEdit {
                     self.start_touch_select(touch_pos, atom);
                     self.redraw_select(atom.batch_id);
 
+                    {
+                        let editor = self.editor.lock();
+                        let (curs_lhs, _) = self.get_select_handles(&editor).unwrap();
+                        // Set the menu pos to the LHS of the selection
+                        menu.pos = curs_lhs + self.behave.inner_pos();
+                    }
+
+                    // Adjust menu pos so RHS doesnt leave the RHS of this widget
+                    let rect = self.rect.get();
+                    if menu.pos.x + menu.total_width() > rect.w {
+                        menu.pos.x = rect.w - menu.total_width();
+                    }
+
                     d!("touch state: StartSelect -> Select");
                     self.touch_info.lock().state = TouchStateAction::Select;
                 }
@@ -1374,8 +1388,6 @@ impl UIObject for BaseEdit {
         self.priority.get()
     }
 
-    fn init(&self) {}
-
     async fn start(self: Arc<Self>, ex: ExecutorPtr) {
         let me = Arc::downgrade(&self);
 
@@ -1648,9 +1660,7 @@ impl UIObject for BaseEdit {
         }
 
         if btn == MouseButton::Right {
-            let cursor_pos = self.get_cursor_pos();
             let mut menu = action::Menu::new(
-                cursor_pos,
                 self.font_size.get(),
                 self.action_fg_color.get(),
                 self.action_bg_color.get(),
@@ -1660,13 +1670,16 @@ impl UIObject for BaseEdit {
             );
 
             if self.text.get().is_empty() {
-                //self.node().trigger("paste_request", vec![]).await.unwrap();
                 menu.add("Paste", ACTION_PASTE);
             } else {
                 menu.add("Copy", ACTION_COPY);
                 menu.add("Paste", ACTION_PASTE);
                 menu.add("Select All", ACTION_SELALL);
             }
+
+            // Mouse pos relative to root layout
+            menu.pos = mouse_pos - rect.pos();
+
             self.action_mode.set(menu);
             let atom = &mut self.render_api.make_guard(gfxtag!("BaseEdit::handle_mouse_btn_down"));
             self.action_mode.redraw(atom.batch_id);
@@ -1738,8 +1751,9 @@ impl UIObject for BaseEdit {
                     }
                 }
                 ACTION_SELALL => {
-                    self.editor.lock().driver().select_all();
-                    if let Some(seltext) = self.editor.lock().selected_text() {
+                    let mut editor = self.editor.lock();
+                    editor.select_all();
+                    if let Some(seltext) = editor.selected_text() {
                         self.select_text.clone().set_str(atom, Role::Internal, 0, seltext).unwrap();
                     }
                 }