1use std::ops::Mul;
2
3use freya_core::{
4 elements::paragraph::ParagraphHolderInner,
5 prelude::*,
6};
7use keyboard_types::NamedKey;
8use torin::prelude::CursorPoint;
9
10use crate::{
11 EditableConfig,
12 EditorLine,
13 TextSelection,
14 text_editor::{
15 TextEditor,
16 TextEvent,
17 },
18};
19
20#[derive(Debug)]
21pub enum EditableEvent<'a> {
22 Release,
23 Move {
24 location: CursorPoint,
25 editor_line: EditorLine,
26 holder: &'a ParagraphHolder,
27 },
28 Down {
29 location: CursorPoint,
30 editor_line: EditorLine,
31 holder: &'a ParagraphHolder,
32 },
33 KeyDown {
34 key: &'a Key,
35 modifiers: Modifiers,
36 },
37 KeyUp {
38 key: &'a Key,
39 },
40}
41
42impl EditableEvent<'_> {
43 pub fn process<T: TextEditor>(
44 self,
45 mut editor: Writable<T>,
46 mut dragging: Writable<TextDragging>,
47 config: &'_ EditableConfig,
48 ) {
49 match self {
50 EditableEvent::Down {
51 location,
52 editor_line,
53 holder,
54 } => {
55 let holder = holder.0.borrow();
56 let ParagraphHolderInner {
57 paragraph,
58 scale_factor,
59 } = holder.as_ref().unwrap();
60
61 let mut text_editor = editor.write();
62
63 if dragging.peek().shift || dragging.peek().clicked {
64 text_editor.selection_mut().set_as_range();
65 } else {
66 text_editor.clear_selection();
67 }
68
69 dragging.write().clicked = true;
70
71 match EventsCombos::pressed(location) {
72 PressEventType::Triple => {
73 let current_selection = text_editor.selection().clone();
74
75 let char_position = paragraph.get_glyph_position_at_coordinate(
76 location.mul(*scale_factor).to_i32().to_tuple(),
77 );
78 let press_selection = text_editor
79 .measure_selection(char_position.position as usize, editor_line);
80
81 let line = text_editor.char_to_line(press_selection.pos());
83 let line_char = text_editor.line_to_char(line);
84 let line_len = text_editor.line(line).unwrap().utf16_len();
85 let new_selection =
86 TextSelection::new_range((line_char, line_char + line_len));
87
88 if current_selection != new_selection {
90 *text_editor.selection_mut() = new_selection;
91 }
92 }
93 PressEventType::Double => {
94 let current_selection = text_editor.selection().clone();
95
96 let new_selection = if config.select_all_on_double_click {
97 TextSelection::new_range((0, text_editor.len_utf16_cu()))
98 } else {
99 let char_position = paragraph.get_glyph_position_at_coordinate(
100 location.mul(*scale_factor).to_i32().to_tuple(),
101 );
102 let press_selection = text_editor
103 .measure_selection(char_position.position as usize, editor_line);
104
105 let range = text_editor.find_word_boundaries(press_selection.pos());
106 TextSelection::new_range(range)
107 };
108
109 if current_selection != new_selection {
110 *text_editor.selection_mut() = new_selection;
111 }
112 }
113 PressEventType::Quadruple => {
114 let current_selection = text_editor.selection().clone();
115 let new_selection =
116 TextSelection::new_range((0, text_editor.len_utf16_cu()));
117
118 if current_selection != new_selection {
119 *text_editor.selection_mut() = new_selection;
120 }
121 }
122 PressEventType::Single => {
123 let current_selection = text_editor.selection().clone();
124
125 let char_position = paragraph.get_glyph_position_at_coordinate(
126 location.mul(*scale_factor).to_i32().to_tuple(),
127 );
128 let new_selection = text_editor
129 .measure_selection(char_position.position as usize, editor_line);
130
131 if current_selection != new_selection {
133 *text_editor.selection_mut() = new_selection;
134 }
135 }
136 }
137 }
138 EditableEvent::Move {
139 location,
140 editor_line,
141 holder,
142 } => {
143 if dragging.peek().clicked {
144 let paragraph = holder.0.borrow();
145 let ParagraphHolderInner {
146 paragraph,
147 scale_factor,
148 } = paragraph.as_ref().unwrap();
149
150 let dist_position = location.mul(*scale_factor);
151
152 let dist_char = paragraph
154 .get_glyph_position_at_coordinate(dist_position.to_i32().to_tuple());
155 let to = dist_char.position as usize;
156
157 if editor.peek().get_selection().is_none() {
158 editor.write().selection_mut().set_as_range();
159 }
160
161 let current_selection = editor.peek().selection().clone();
162
163 let new_selection = editor.peek().measure_selection(to, editor_line);
164
165 if current_selection != new_selection {
167 let mut text_editor = editor.write();
168 *text_editor.selection_mut() = new_selection;
169 }
170 }
171 }
172 EditableEvent::Release => {
173 dragging.write().clicked = false;
174 }
175 EditableEvent::KeyDown { key, modifiers } => {
176 match key {
177 Key::Named(NamedKey::Shift) => {
179 dragging.write().shift = true;
180 }
181 _ => {
183 editor.write_if(|mut editor| {
184 let event = editor.process_key(
185 key,
186 &modifiers,
187 config.allow_tabs,
188 config.allow_changes,
189 config.allow_read_clipboard,
190 config.allow_write_clipboard,
191 );
192 if event.contains(TextEvent::TEXT_CHANGED) {
193 *dragging.write() = TextDragging::default();
194 }
195 !event.is_empty()
196 });
197 }
198 }
199 }
200 EditableEvent::KeyUp { key, .. } => {
201 if *key == Key::Named(NamedKey::Shift) {
202 dragging.write().shift = false;
203 }
204 }
205 };
206 }
207}
208
209#[derive(Debug, PartialEq, Clone, Default)]
210pub struct TextDragging {
211 pub shift: bool,
212 pub clicked: bool,
213}