1use std::{
2 collections::{BTreeSet, HashSet},
3 hash::Hash,
4};
5
6pub trait Selector {
7 type Selectable: Selectable<Position = Self::Position>;
8 type Position: Copy;
9
10 fn moved(&self, moved: Self::Position, cursor: Self::Position) -> bool;
11 fn stop(
12 &self,
13 selectable: &mut Self::Selectable,
14 index: <Self::Selectable as Selectable>::Index,
15 );
16
17 fn add(
18 &self,
19 selectable: &mut Self::Selectable,
20 pos: Self::Position,
21 from: Option<<Self::Selectable as Selectable>::Index>,
22 ) -> <Self::Selectable as Selectable>::Index {
23 selectable.add(pos, from)
24 }
25 fn get(
26 &self,
27 selectable: &Self::Selectable,
28 pos: Self::Position,
29 ) -> Option<<Self::Selectable as Selectable>::Index> {
30 selectable.get(pos)
31 }
32
33 fn connect(
34 &self,
35 selectable: &mut Self::Selectable,
36 index: <Self::Selectable as Selectable>::Index,
37 selected: &[<Self::Selectable as Selectable>::Index],
38 ) {
39 selectable.connect(index, selected)
40 }
41 fn special(
42 &self,
43 selectable: &mut Self::Selectable,
44 index: <Self::Selectable as Selectable>::Index,
45 selected: &[<Self::Selectable as Selectable>::Index],
46 ) {
47 selectable.connect(index, selected)
48 }
49}
50
51pub trait Selectable {
52 type Position: Copy;
53 type Index;
54
55 fn add(&mut self, pos: Self::Position, from: Option<Self::Index>) -> Self::Index;
56 fn get(&self, pos: Self::Position) -> Option<Self::Index>;
57
58 fn connect(&mut self, _index: Self::Index, _selected: &[Self::Index]) {}
59 fn special(&mut self, _index: Self::Index, _selected: &[Self::Index]) {}
60}
61
62#[derive(Copy, Clone, PartialEq, Eq)]
63pub enum Action {
64 Connect,
65 Move,
66}
67
68pub struct ObjectGrabState<I> {
69 pub index: I,
70 pub action: Action,
71}
72
73pub enum GrabState<I> {
74 Object(ObjectGrabState<I>),
75 Empty,
76}
77
78pub struct GrabInfo<P, I> {
79 pub pos: P,
80 pub state: GrabState<I>,
81 pub time: f32,
82 pub moved: Option<P>,
83 created: bool,
84}
85
86impl<P: Copy, I: Copy> GrabInfo<P, I> {
87 fn new(pos: P, state: GrabState<I>, cursor: P) -> Self {
88 Self {
89 pos,
90 state,
91 time: 0.0,
92 moved: Some(cursor),
93 created: false,
94 }
95 }
96
97 pub fn hold<S: Selector<Position = P>>(&mut self, selector: &S, selectable: &mut S::Selectable)
98 where
99 S::Selectable: Selectable<Index = I>,
100 {
101 use GrabState::*;
102 match &mut self.state {
103 Empty => {
104 self.created = true;
105 let index = selector.add(selectable, self.pos, None);
106 self.state = Object(ObjectGrabState {
107 index,
108 action: Action::Connect,
109 });
110 selector.stop(selectable, index);
111 }
112 Object(ObjectGrabState { action, .. }) => *action = Action::Connect,
113 }
114 }
115}
116
117pub trait SelectionSet {
118 type Index;
119
120 fn to_vec(&self) -> Vec<Self::Index>;
121 fn contains(&self, index: &Self::Index) -> bool;
122
123 fn insert(&mut self, index: Self::Index);
124 fn remove(&mut self, index: &Self::Index);
125 fn clear(&mut self);
126
127 fn single(&mut self, index: Self::Index) {
128 self.clear();
129 self.insert(index);
130 }
131}
132
133impl<I: Clone + Eq + Hash> SelectionSet for HashSet<I> {
134 type Index = I;
135
136 fn to_vec(&self) -> Vec<I> {
137 self.iter().cloned().collect()
138 }
139
140 fn contains(&self, index: &I) -> bool {
141 self.contains(index)
142 }
143
144 fn insert(&mut self, index: I) {
145 self.insert(index);
146 }
147
148 fn remove(&mut self, index: &I) {
149 self.remove(index);
150 }
151
152 fn clear(&mut self) {
153 self.clear()
154 }
155
156 fn single(&mut self, index: I) {
157 self.clear();
158 self.insert(index);
159 }
160}
161
162impl<I: Clone + Ord> SelectionSet for BTreeSet<I> {
163 type Index = I;
164
165 fn to_vec(&self) -> Vec<I> {
166 self.iter().cloned().collect()
167 }
168
169 fn contains(&self, index: &I) -> bool {
170 self.contains(index)
171 }
172
173 fn insert(&mut self, index: I) {
174 self.insert(index);
175 }
176
177 fn remove(&mut self, index: &I) {
178 self.remove(index);
179 }
180
181 fn clear(&mut self) {
182 self.clear()
183 }
184
185 fn single(&mut self, index: I) {
186 self.clear();
187 self.insert(index);
188 }
189}
190
191#[derive(Default)]
192pub struct Selection<P, C: SelectionSet> {
193 pub selected: C,
194 pub grab: Option<GrabInfo<P, C::Index>>,
195}
196
197impl<P: Copy, C: SelectionSet> Selection<P, C>
198where
199 C::Index: Copy,
200{
201 pub fn new(selected: C) -> Self {
202 Self {
203 selected,
204 grab: None,
205 }
206 }
207
208 pub fn press<S: Selector<Position = P>>(
209 &mut self,
210 pos: P,
211 cursor: P,
212 selector: &S,
213 selectable: &S::Selectable,
214 ) where
215 S::Selectable: Selectable<Index = C::Index>,
216 {
217 use GrabState::*;
218
219 self.grab = Some(GrabInfo::new(
220 pos,
221 if let Some(index) = selector.get(selectable, pos) {
222 Object(ObjectGrabState {
223 index,
224 action: Action::Move,
225 })
226 } else {
227 Empty
228 },
229 cursor,
230 ));
231 }
232
233 pub fn release<S: Selector<Position = P>>(
234 &mut self,
235 pos: P,
236 selector: &S,
237 selectable: &mut S::Selectable,
238 ) where
239 S::Selectable: Selectable<Index = C::Index>,
240 {
241 let Some(mut grab_info) = self.grab.take() else {
242 return;
243 };
244
245 let GrabState::Object(ObjectGrabState {
246 action,
247 index: event,
248 }) = grab_info.state
249 else {
250 if grab_info.moved.is_some() {
251 self.selected.clear();
252 }
253
254 return;
255 };
256
257 for index in self.selected.to_vec() {
258 selector.stop(selectable, index);
259 }
260
261 use Action::*;
262 match action {
263 Connect => {
264 if grab_info.moved.is_none() {
265 let index = selector.get(selectable, pos).unwrap_or_else(|| {
266 let index = selector.add(selectable, pos, Some(event));
267 selector.stop(selectable, index);
268 index
269 });
270 selector.connect(selectable, index, &self.selected.to_vec());
271 self.selected.single(index);
272 } else if self.selected.contains(&event) {
273 self.selected.single(event);
274 } else if grab_info.created {
275 grab_info.created = false;
276 self.selected.insert(event);
277 } else {
278 selector.special(selectable, event, &self.selected.to_vec());
279 }
280 }
281 Move => {
282 if grab_info.moved.is_none() {
283 return;
284 }
285
286 if self.selected.contains(&event) {
287 self.selected.remove(&event);
288 } else {
289 self.selected.insert(event);
290 }
291 }
292 }
293 }
294
295 pub fn on_moved<S: Selector<Position = P>>(&mut self, cursor: P, selector: &S) {
296 let Some(grab_info) = &mut self.grab else {
297 return;
298 };
299
300 let &Some(moved) = &grab_info.moved else {
301 return;
302 };
303
304 if !selector.moved(moved, cursor) {
305 return;
306 }
307
308 grab_info.created = false;
309 grab_info.moved = None;
310
311 let &GrabState::Object(ObjectGrabState { index, .. }) = &grab_info.state else {
312 return;
313 };
314
315 if !self.selected.contains(&index) {
316 self.selected.single(index);
317 }
318 }
319}
320
321impl<P, S: SelectionSet + IntoIterator> IntoIterator for Selection<P, S> {
322 type Item = <S as IntoIterator>::Item;
323 type IntoIter = <S as IntoIterator>::IntoIter;
324
325 fn into_iter(self) -> Self::IntoIter {
326 self.selected.into_iter()
327 }
328}
329
330impl<'a, P, S: SelectionSet> IntoIterator for &'a Selection<P, S>
331where
332 &'a S: IntoIterator,
333{
334 type Item = <&'a S as IntoIterator>::Item;
335 type IntoIter = <&'a S as IntoIterator>::IntoIter;
336
337 fn into_iter(self) -> Self::IntoIter {
338 self.selected.into_iter()
339 }
340}
341
342impl<P, S: SelectionSet> Selection<P, S> {
343 pub fn iter<'a>(&'a self) -> <&'a S as IntoIterator>::IntoIter
344 where
345 &'a S: IntoIterator,
346 {
347 self.into_iter()
348 }
349}