iced_widget/text_input/
cursor.rs
1use crate::text_input::Value;
3
4#[derive(Debug, Copy, Clone, PartialEq, Eq)]
6pub struct Cursor {
7 state: State,
8}
9
10#[derive(Debug, Copy, Clone, PartialEq, Eq)]
12pub enum State {
13 Index(usize),
15
16 Selection {
18 start: usize,
20 end: usize,
22 },
23}
24
25impl Default for Cursor {
26 fn default() -> Self {
27 Cursor {
28 state: State::Index(0),
29 }
30 }
31}
32
33impl Cursor {
34 pub fn state(&self, value: &Value) -> State {
36 match self.state {
37 State::Index(index) => State::Index(index.min(value.len())),
38 State::Selection { start, end } => {
39 let start = start.min(value.len());
40 let end = end.min(value.len());
41
42 if start == end {
43 State::Index(start)
44 } else {
45 State::Selection { start, end }
46 }
47 }
48 }
49 }
50
51 pub fn selection(&self, value: &Value) -> Option<(usize, usize)> {
55 match self.state(value) {
56 State::Selection { start, end } => {
57 Some((start.min(end), start.max(end)))
58 }
59 State::Index(_) => None,
60 }
61 }
62
63 pub(crate) fn move_to(&mut self, position: usize) {
64 self.state = State::Index(position);
65 }
66
67 pub(crate) fn move_right(&mut self, value: &Value) {
68 self.move_right_by_amount(value, 1);
69 }
70
71 pub(crate) fn move_right_by_words(&mut self, value: &Value) {
72 self.move_to(value.next_end_of_word(self.right(value)));
73 }
74
75 pub(crate) fn move_right_by_amount(
76 &mut self,
77 value: &Value,
78 amount: usize,
79 ) {
80 match self.state(value) {
81 State::Index(index) => {
82 self.move_to(index.saturating_add(amount).min(value.len()));
83 }
84 State::Selection { start, end } => self.move_to(end.max(start)),
85 }
86 }
87
88 pub(crate) fn move_left(&mut self, value: &Value) {
89 match self.state(value) {
90 State::Index(index) if index > 0 => self.move_to(index - 1),
91 State::Selection { start, end } => self.move_to(start.min(end)),
92 State::Index(_) => self.move_to(0),
93 }
94 }
95
96 pub(crate) fn move_left_by_words(&mut self, value: &Value) {
97 self.move_to(value.previous_start_of_word(self.left(value)));
98 }
99
100 pub(crate) fn select_range(&mut self, start: usize, end: usize) {
101 if start == end {
102 self.state = State::Index(start);
103 } else {
104 self.state = State::Selection { start, end };
105 }
106 }
107
108 pub(crate) fn select_left(&mut self, value: &Value) {
109 match self.state(value) {
110 State::Index(index) if index > 0 => {
111 self.select_range(index, index - 1);
112 }
113 State::Selection { start, end } if end > 0 => {
114 self.select_range(start, end - 1);
115 }
116 _ => {}
117 }
118 }
119
120 pub(crate) fn select_right(&mut self, value: &Value) {
121 match self.state(value) {
122 State::Index(index) if index < value.len() => {
123 self.select_range(index, index + 1);
124 }
125 State::Selection { start, end } if end < value.len() => {
126 self.select_range(start, end + 1);
127 }
128 _ => {}
129 }
130 }
131
132 pub(crate) fn select_left_by_words(&mut self, value: &Value) {
133 match self.state(value) {
134 State::Index(index) => {
135 self.select_range(index, value.previous_start_of_word(index));
136 }
137 State::Selection { start, end } => {
138 self.select_range(start, value.previous_start_of_word(end));
139 }
140 }
141 }
142
143 pub(crate) fn select_right_by_words(&mut self, value: &Value) {
144 match self.state(value) {
145 State::Index(index) => {
146 self.select_range(index, value.next_end_of_word(index));
147 }
148 State::Selection { start, end } => {
149 self.select_range(start, value.next_end_of_word(end));
150 }
151 }
152 }
153
154 pub(crate) fn select_all(&mut self, value: &Value) {
155 self.select_range(0, value.len());
156 }
157
158 pub(crate) fn start(&self, value: &Value) -> usize {
159 let start = match self.state {
160 State::Index(index) => index,
161 State::Selection { start, .. } => start,
162 };
163
164 start.min(value.len())
165 }
166
167 pub(crate) fn end(&self, value: &Value) -> usize {
168 let end = match self.state {
169 State::Index(index) => index,
170 State::Selection { end, .. } => end,
171 };
172
173 end.min(value.len())
174 }
175
176 fn left(&self, value: &Value) -> usize {
177 match self.state(value) {
178 State::Index(index) => index,
179 State::Selection { start, end } => start.min(end),
180 }
181 }
182
183 fn right(&self, value: &Value) -> usize {
184 match self.state(value) {
185 State::Index(index) => index,
186 State::Selection { start, end } => start.max(end),
187 }
188 }
189}