aboutsummaryrefslogtreecommitdiff
path: root/src/text.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/text.rs')
-rw-r--r--src/text.rs88
1 files changed, 84 insertions, 4 deletions
diff --git a/src/text.rs b/src/text.rs
index 851e77b..acc7d2c 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -177,6 +177,8 @@ pub struct State {
selection: Selection,
dragging: Option<Dragging>,
last_click: Option<mouse::Click>,
+ potential_click: Option<mouse::Click>,
+ has_cleared_clipboard: bool,
keyboard_modifiers: keyboard::Modifiers,
visual_lines_bounds: Vec<core::Rectangle>,
}
@@ -434,6 +436,14 @@ where
shell.capture_event();
} else {
+ if let Some(position) = cursor.land().position() {
+ let potential_click = mouse::Click::new(
+ position,
+ mouse::Button::Left,
+ state.potential_click,
+ );
+ state.potential_click = Some(potential_click);
+ }
state.selection = Selection::default();
}
}
@@ -441,6 +451,7 @@ where
| Event::Touch(touch::Event::FingerLifted { .. })
| Event::Touch(touch::Event::FingerLost { .. }) => {
state.dragging = None;
+ state.potential_click = None;
}
Event::Mouse(mouse::Event::CursorMoved { .. })
| Event::Touch(touch::Event::FingerMoved { .. }) => {
@@ -472,6 +483,65 @@ where
);
}
};
+ } else if let Some(potential_click) = state.potential_click
+ && let Some(position) = cursor.position_over(bounds)
+ {
+ // We had a click outside of bounds that dragged inside bounds
+ let (line, index) = state
+ .grapheme_line_and_index(
+ potential_click.position(),
+ bounds,
+ )
+ .unwrap_or((0, 0));
+ let new_start = SelectionEnd { line, index };
+ state.selection.select_range(new_start, new_start);
+
+ let (line, index) = state
+ .grapheme_line_and_index(position, bounds)
+ .unwrap_or((0, 0));
+
+ match potential_click.kind() {
+ click::Kind::Single => {
+ let new_end = SelectionEnd { line, index };
+
+ state.selection.change_selection(new_end);
+
+ state.dragging = Some(Dragging::Grapheme);
+ }
+ click::Kind::Double => {
+ let new_end = SelectionEnd { line, index };
+
+ state.selection.select_word(
+ new_start.line,
+ new_start.index,
+ &state.paragraph,
+ );
+ state.selection.change_selection_by_word(
+ new_end,
+ &state.paragraph,
+ );
+
+ state.dragging = Some(Dragging::Word);
+ }
+ click::Kind::Triple => {
+ state
+ .selection
+ .select_line(new_start.line, &state.paragraph);
+ state.selection.change_selection_by_line(
+ line,
+ &state.paragraph,
+ );
+ state.dragging = Some(Dragging::Line);
+ }
+ }
+
+ state.last_click = Some(potential_click);
+ state.potential_click = None;
+
+ // Clear the clipboard so that we can append to it if the user presses the copy
+ // shortcut to be able to include all selected texts.
+ clipboard.write(clipboard::Kind::Standard, String::new());
+ state.has_cleared_clipboard = true;
}
}
Event::Keyboard(keyboard::Event::KeyPressed { key, .. }) => {
@@ -480,10 +550,20 @@ where
if state.keyboard_modifiers.command()
&& !state.selection.is_empty() =>
{
- clipboard.write(
- clipboard::Kind::Standard,
- state.selection.text(&state.paragraph),
- );
+ let contents =
+ if state.has_cleared_clipboard {
+ state.has_cleared_clipboard = false;
+ clipboard
+ .read(clipboard::Kind::Standard)
+ .map(|c| {
+ if !c.is_empty() { c + "\n" } else { c }
+ })
+ .unwrap_or_default()
+ + &state.selection.text(&state.paragraph)
+ } else {
+ state.selection.text(&state.paragraph)
+ };
+ clipboard.write(clipboard::Kind::Standard, contents);
shell.capture_event();
}