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 char_position = paragraph.get_glyph_position_at_coordinate(
97 location.mul(*scale_factor).to_i32().to_tuple(),
98 );
99 let press_selection = text_editor
100 .measure_selection(char_position.position as usize, editor_line);
101
102 let range = text_editor.find_word_boundaries(press_selection.pos());
104 let new_selection = TextSelection::new_range(range);
105
106 if current_selection != new_selection {
108 *text_editor.selection_mut() = new_selection;
109 }
110 }
111 PressEventType::Quadruple => {
112 let current_selection = text_editor.selection().clone();
113 let new_selection =
114 TextSelection::new_range((0, text_editor.len_utf16_cu()));
115
116 if current_selection != new_selection {
117 *text_editor.selection_mut() = new_selection;
118 }
119 }
120 PressEventType::Single => {
121 let current_selection = text_editor.selection().clone();
122
123 let char_position = paragraph.get_glyph_position_at_coordinate(
124 location.mul(*scale_factor).to_i32().to_tuple(),
125 );
126 let new_selection = text_editor
127 .measure_selection(char_position.position as usize, editor_line);
128
129 if current_selection != new_selection {
131 *text_editor.selection_mut() = new_selection;
132 }
133 }
134 }
135 }
136 EditableEvent::Move {
137 location,
138 editor_line,
139 holder,
140 } => {
141 if dragging.peek().clicked {
142 let paragraph = holder.0.borrow();
143 let ParagraphHolderInner {
144 paragraph,
145 scale_factor,
146 } = paragraph.as_ref().unwrap();
147
148 let dist_position = location.mul(*scale_factor);
149
150 let dist_char = paragraph
152 .get_glyph_position_at_coordinate(dist_position.to_i32().to_tuple());
153 let to = dist_char.position as usize;
154
155 if editor.peek().get_selection().is_none() {
156 editor.write().selection_mut().set_as_range();
157 }
158
159 let current_selection = editor.peek().selection().clone();
160
161 let new_selection = editor.peek().measure_selection(to, editor_line);
162
163 if current_selection != new_selection {
165 let mut text_editor = editor.write();
166 *text_editor.selection_mut() = new_selection;
167 }
168 }
169 }
170 EditableEvent::Release => {
171 dragging.write().clicked = false;
172 }
173 EditableEvent::KeyDown { key, modifiers } => {
174 match key {
175 Key::Named(NamedKey::Shift) => {
177 dragging.write().shift = true;
178 }
179 _ => {
181 editor.write_if(|mut editor| {
182 let event = editor.process_key(
183 key,
184 &modifiers,
185 config.allow_tabs,
186 config.allow_changes,
187 config.allow_clipboard,
188 );
189 if event.contains(TextEvent::TEXT_CHANGED) {
190 *dragging.write() = TextDragging::default();
191 }
192 !event.is_empty()
193 });
194 }
195 }
196 }
197 EditableEvent::KeyUp { key, .. } => {
198 if *key == Key::Named(NamedKey::Shift) {
199 dragging.write().shift = false;
200 }
201 }
202 };
203 }
204}
205
206#[derive(Debug, PartialEq, Clone, Default)]
207pub struct TextDragging {
208 pub shift: bool,
209 pub clicked: bool,
210}