summaryrefslogtreecommitdiffstats
path: root/native/src/widget
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2019-12-18 09:11:33 +0100
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2019-12-18 09:11:33 +0100
commit68f3c9c4c6e98c4d68774eda52c41cb89b0cf12b (patch)
tree192409d205c521bd0891a136a4ff2061d5b0dcf9 /native/src/widget
parent5a9527894a75777c1da5c1d68864b1944994bc68 (diff)
downloadiced-68f3c9c4c6e98c4d68774eda52c41cb89b0cf12b.tar.gz
iced-68f3c9c4c6e98c4d68774eda52c41cb89b0cf12b.tar.bz2
iced-68f3c9c4c6e98c4d68774eda52c41cb89b0cf12b.zip
Implement clipboard pasting in `TextInput`
Diffstat (limited to 'native/src/widget')
-rw-r--r--native/src/widget/text_input.rs107
1 files changed, 88 insertions, 19 deletions
diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs
index 3890e9c6..71e3d75a 100644
--- a/native/src/widget/text_input.rs
+++ b/native/src/widget/text_input.rs
@@ -172,7 +172,7 @@ where
cursor_position: Point,
messages: &mut Vec<Message>,
renderer: &Renderer,
- _clipboard: Option<&dyn Clipboard>,
+ clipboard: Option<&dyn Clipboard>,
) {
match event {
Event::Mouse(mouse::Event::Input {
@@ -210,7 +210,9 @@ where
}
}
Event::Keyboard(keyboard::Event::CharacterReceived(c))
- if self.state.is_focused && !c.is_control() =>
+ if self.state.is_focused
+ && self.state.is_pasting.is_none()
+ && !c.is_control() =>
{
let cursor_position = self.state.cursor_position(&self.value);
@@ -255,26 +257,18 @@ where
}
}
keyboard::KeyCode::Left => {
- let jump_modifier_pressed = if cfg!(target_os = "macos") {
- modifiers.alt
- } else {
- modifiers.control
- };
-
- if jump_modifier_pressed && !self.is_secure {
+ if platform::is_jump_modifier_pressed(modifiers)
+ && !self.is_secure
+ {
self.state.move_cursor_left_by_words(&self.value);
} else {
self.state.move_cursor_left(&self.value);
}
}
keyboard::KeyCode::Right => {
- let jump_modifier_pressed = if cfg!(target_os = "macos") {
- modifiers.alt
- } else {
- modifiers.control
- };
-
- if jump_modifier_pressed && !self.is_secure {
+ if platform::is_jump_modifier_pressed(modifiers)
+ && !self.is_secure
+ {
self.state.move_cursor_right_by_words(&self.value);
} else {
self.state.move_cursor_right(&self.value);
@@ -286,6 +280,50 @@ where
keyboard::KeyCode::End => {
self.state.move_cursor_to_end(&self.value);
}
+ keyboard::KeyCode::V => {
+ if platform::is_copy_paste_modifier_pressed(modifiers) {
+ if let Some(clipboard) = clipboard {
+ let content = match self.state.is_pasting.take() {
+ Some(content) => content,
+ None => {
+ let content: String = clipboard
+ .content()
+ .unwrap_or(String::new())
+ .chars()
+ .filter(|c| !c.is_control())
+ .collect();
+
+ Value::new(&content)
+ }
+ };
+
+ let cursor_position =
+ self.state.cursor_position(&self.value);
+
+ self.value
+ .insert_many(cursor_position, content.clone());
+
+ self.state.cursor_position += content.len();
+ self.state.is_pasting = Some(content);
+
+ let message =
+ (self.on_change)(self.value.to_string());
+ messages.push(message);
+ }
+ } else {
+ self.state.is_pasting = None;
+ }
+ }
+ _ => {}
+ },
+ Event::Keyboard(keyboard::Event::Input {
+ key_code,
+ state: ButtonState::Released,
+ ..
+ }) => match key_code {
+ keyboard::KeyCode::V => {
+ self.state.is_pasting = None;
+ }
_ => {}
},
_ => {}
@@ -398,6 +436,7 @@ where
#[derive(Debug, Default, Clone)]
pub struct State {
is_focused: bool,
+ is_pasting: Option<Value>,
cursor_position: usize,
}
@@ -417,6 +456,7 @@ impl State {
Self {
is_focused: true,
+ is_pasting: None,
cursor_position: usize::MAX,
}
}
@@ -487,7 +527,7 @@ impl State {
///
/// [`TextInput`]: struct.TextInput.html
// TODO: Reduce allocations, cache results (?)
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct Value {
graphemes: Vec<String>,
}
@@ -574,8 +614,6 @@ impl Value {
}
/// Inserts a new `char` at the given grapheme `index`.
- ///
- /// [`Value`]: struct.Value.html
pub fn insert(&mut self, index: usize, c: char) {
self.graphemes.insert(index, c.to_string());
@@ -585,6 +623,13 @@ impl Value {
.collect();
}
+ /// Inserts a bunch of graphemes at the given grapheme `index`.
+ pub fn insert_many(&mut self, index: usize, mut value: Value) {
+ let _ = self
+ .graphemes
+ .splice(index..index, value.graphemes.drain(..));
+ }
+
/// Removes the grapheme at the given `index`.
///
/// [`Value`]: struct.Value.html
@@ -657,3 +702,27 @@ fn find_cursor_position<Renderer: self::Renderer>(
)
}
}
+
+mod platform {
+ use crate::input::keyboard;
+
+ pub fn is_jump_modifier_pressed(
+ modifiers: keyboard::ModifiersState,
+ ) -> bool {
+ if cfg!(target_os = "macos") {
+ modifiers.alt
+ } else {
+ modifiers.control
+ }
+ }
+
+ pub fn is_copy_paste_modifier_pressed(
+ modifiers: keyboard::ModifiersState,
+ ) -> bool {
+ if cfg!(target_os = "macos") {
+ modifiers.logo
+ } else {
+ modifiers.control
+ }
+ }
+}