wallet: editbox copy/pasta from clipboard

This commit is contained in:
darkfi
2024-07-06 12:52:57 +02:00
parent e0336f4a03
commit 1b8e7b3d06

View File

@@ -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,