iced_widget/text_input/
cursor.rs1use 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 } => Some((start.min(end), start.max(end))),
57 State::Index(_) => None,
58 }
59 }
60
61 pub(crate) fn move_to(&mut self, position: usize) {
62 self.state = State::Index(position);
63 }
64
65 pub(crate) fn move_right(&mut self, value: &Value) {
66 self.move_right_by_amount(value, 1);
67 }
68
69 pub(crate) fn move_right_by_words(&mut self, value: &Value) {
70 self.move_to(value.next_end_of_word(self.right(value)));
71 }
72
73 pub(crate) fn move_right_by_amount(&mut self, value: &Value, amount: usize) {
74 match self.state(value) {
75 State::Index(index) => {
76 self.move_to(index.saturating_add(amount).min(value.len()));
77 }
78 State::Selection { start, end } => self.move_to(end.max(start)),
79 }
80 }
81
82 pub(crate) fn move_left(&mut self, value: &Value) {
83 match self.state(value) {
84 State::Index(index) if index > 0 => self.move_to(index - 1),
85 State::Selection { start, end } => self.move_to(start.min(end)),
86 State::Index(_) => self.move_to(0),
87 }
88 }
89
90 pub(crate) fn move_left_by_words(&mut self, value: &Value) {
91 self.move_to(value.previous_start_of_word(self.left(value)));
92 }
93
94 pub(crate) fn select_range(&mut self, start: usize, end: usize) {
95 if start == end {
96 self.state = State::Index(start);
97 } else {
98 self.state = State::Selection { start, end };
99 }
100 }
101
102 pub(crate) fn select_left(&mut self, value: &Value) {
103 match self.state(value) {
104 State::Index(index) if index > 0 => {
105 self.select_range(index, index - 1);
106 }
107 State::Selection { start, end } if end > 0 => {
108 self.select_range(start, end - 1);
109 }
110 _ => {}
111 }
112 }
113
114 pub(crate) fn select_right(&mut self, value: &Value) {
115 match self.state(value) {
116 State::Index(index) if index < value.len() => {
117 self.select_range(index, index + 1);
118 }
119 State::Selection { start, end } if end < value.len() => {
120 self.select_range(start, end + 1);
121 }
122 _ => {}
123 }
124 }
125
126 pub(crate) fn select_left_by_words(&mut self, value: &Value) {
127 match self.state(value) {
128 State::Index(index) => {
129 self.select_range(index, value.previous_start_of_word(index));
130 }
131 State::Selection { start, end } => {
132 self.select_range(start, value.previous_start_of_word(end));
133 }
134 }
135 }
136
137 pub(crate) fn select_right_by_words(&mut self, value: &Value) {
138 match self.state(value) {
139 State::Index(index) => {
140 self.select_range(index, value.next_end_of_word(index));
141 }
142 State::Selection { start, end } => {
143 self.select_range(start, value.next_end_of_word(end));
144 }
145 }
146 }
147
148 pub(crate) fn select_all(&mut self, value: &Value) {
149 self.select_range(0, value.len());
150 }
151
152 pub(crate) fn start(&self, value: &Value) -> usize {
153 let start = match self.state {
154 State::Index(index) => index,
155 State::Selection { start, .. } => start,
156 };
157
158 start.min(value.len())
159 }
160
161 pub(crate) fn end(&self, value: &Value) -> usize {
162 let end = match self.state {
163 State::Index(index) => index,
164 State::Selection { end, .. } => end,
165 };
166
167 end.min(value.len())
168 }
169
170 fn left(&self, value: &Value) -> usize {
171 match self.state(value) {
172 State::Index(index) => index,
173 State::Selection { start, end } => start.min(end),
174 }
175 }
176
177 fn right(&self, value: &Value) -> usize {
178 match self.state(value) {
179 State::Index(index) => index,
180 State::Selection { start, end } => start.max(end),
181 }
182 }
183}