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

wallet: editbox copy/pasta from clipboard

darkfi 2 лет назад
Родитель
Сommit
1b8e7b3d06
1 измененных файлов с 89 добавлено и 9 удалено
  1. 89 9
      bin/darkwallet/src/ui/editbox.rs

+ 89 - 9
bin/darkwallet/src/ui/editbox.rs

@@ -311,7 +311,12 @@ impl EditBox {
         TextRenderInfo { mesh, texture_id: atlas.texture_id }
     }
 
-    fn draw_selected(&self, mesh: &mut MeshBuilder, glyphs: &Vec<Glyph>, clip_h: f32) -> Result<()> {
+    fn draw_selected(
+        &self,
+        mesh: &mut MeshBuilder,
+        glyphs: &Vec<Glyph>,
+        clip_h: f32,
+    ) -> Result<()> {
         if self.selected.is_null(0)? || self.selected.is_null(1)? {
             // Nothing selected so do nothing
             return Ok(())
@@ -355,12 +360,7 @@ impl EditBox {
         }
 
         // We don't need to do manual clipping since MeshBuilder should do that
-        let select_rect = Rectangle {
-            x: start_x,
-            y: 0.,
-            w: end_x - start_x,
-            h: clip_h
-        };
+        let select_rect = Rectangle { x: start_x, y: 0., w: end_x - start_x, h: clip_h };
         mesh.draw_box(&select_rect, hi_bg_color, &Rectangle::zero());
         Ok(())
     }
@@ -379,8 +379,7 @@ impl EditBox {
         };
 
         // First filter for only single digit keys
-        let disallowed_keys = ['\r', '\u{8}', '\u{7f}', '\t', '\n'];
-        if disallowed_keys.contains(&key) {
+        if DISALLOWED_CHARS.contains(&key) {
             return
         }
 
@@ -389,6 +388,14 @@ impl EditBox {
             panic!("self destroyed before char_task was stopped!");
         };
 
+        if mods.ctrl || mods.alt {
+            if repeat {
+                return
+            }
+            self_.handle_shortcut(key, &mods).await;
+            return
+        }
+
         let actions = {
             let mut repeater = self_.key_repeat.lock().unwrap();
             repeater.key_down(PressedKey::Char(key), repeat)
@@ -462,6 +469,26 @@ impl EditBox {
         self.redraw().await;
     }
 
+    async fn handle_shortcut(&self, key: char, mods: &KeyMods) {
+        debug!(target: "ui::editbox", "handle_shortcut({:?}, {:?})", key, mods);
+
+        match key {
+            'c' => {
+                if mods.ctrl {
+                    self.copy_highlighted().unwrap();
+                }
+            }
+            'v' => {
+                if mods.ctrl {
+                    if let Some(text) = window::clipboard_get() {
+                        self.paste_text(text).await;
+                    }
+                }
+            }
+            _ => {}
+        }
+    }
+
     async fn handle_key(&self, key: &KeyCode, mods: &KeyMods) {
         debug!(target: "ui::editbox", "handle_key({:?}, {:?})", key, mods);
         match key {
@@ -625,6 +652,52 @@ impl EditBox {
         self.cursor_pos.set(sel_start as u32);
     }
 
+    fn copy_highlighted(&self) -> Result<()> {
+        let start = self.selected.get_u32(0)? as usize;
+        let end = self.selected.get_u32(1)? as usize;
+
+        let sel_start = std::cmp::min(start, end);
+        let sel_end = std::cmp::max(start, end);
+
+        let mut text = String::new();
+
+        let glyphs = self.glyphs.lock().unwrap().clone();
+        for (glyph_idx, glyph) in glyphs.iter().enumerate() {
+            if sel_start <= glyph_idx && glyph_idx < sel_end {
+                text.push_str(&glyph.substr);
+            }
+        }
+
+        info!(target: "ui::editbox", "Copied '{}'", text);
+        window::clipboard_set(&text);
+        Ok(())
+    }
+
+    async fn paste_text(&self, key: String) {
+        let mut text = String::new();
+
+        let cursor_pos = self.cursor_pos.get();
+
+        if cursor_pos == 0 {
+            text = key.clone();
+        }
+
+        let glyphs = self.glyphs.lock().unwrap().clone();
+        for (glyph_idx, glyph) in glyphs.iter().enumerate() {
+            text.push_str(&glyph.substr);
+            if cursor_pos == glyph_idx as u32 + 1 {
+                text.push_str(&key);
+            }
+        }
+
+        self.text.set(text);
+        // Not always true lol
+        self.cursor_pos.set(cursor_pos + 1);
+
+        self.apply_cursor_scrolling();
+        self.redraw().await;
+    }
+
     /// Beware of this method. Here be dragons.
     /// Possibly racy so we limit it just to cursor scrolling.
     fn cached_rect(&self) -> Rectangle {
@@ -780,6 +853,13 @@ impl Stoppable for EditBox {
     }
 }
 
+/// Filter these char events from being handled since we handle them
+/// using the key_up/key_down events.
+/// Avoids duplicate processing of keyboard input events.
+static DISALLOWED_CHARS: &'static [char] = &['\r', '\u{8}', '\u{7f}', '\t', '\n'];
+
+/// These keycodes are handled via normal key_up/key_down events.
+/// Anything in this list must be disallowed char events.
 static ALLOWED_KEYCODES: &'static [KeyCode] = &[
     KeyCode::Left,
     KeyCode::Right,