1use crate::Anchor;
2use crate::{rope::TextDimension, BufferSnapshot};
3use std::cmp::Ordering;
4
5#[derive(Copy, Clone, Debug, Eq, PartialEq)]
6pub enum SelectionGoal {
7 None,
8 Column(u32),
9 ColumnRange { start: u32, end: u32 },
10}
11
12#[derive(Clone, Debug, Eq, PartialEq)]
13pub struct Selection<T> {
14 pub id: usize,
15 pub start: T,
16 pub end: T,
17 pub reversed: bool,
18 pub goal: SelectionGoal,
19}
20
21impl<T: Clone> Selection<T> {
22 pub fn head(&self) -> T {
23 if self.reversed {
24 self.start.clone()
25 } else {
26 self.end.clone()
27 }
28 }
29
30 pub fn tail(&self) -> T {
31 if self.reversed {
32 self.end.clone()
33 } else {
34 self.start.clone()
35 }
36 }
37}
38
39impl<T: Copy + Ord> Selection<T> {
40 pub fn is_empty(&self) -> bool {
41 self.start == self.end
42 }
43
44 pub fn set_head(&mut self, head: T, new_goal: SelectionGoal) {
45 if head.cmp(&self.tail()) < Ordering::Equal {
46 if !self.reversed {
47 self.end = self.start;
48 self.reversed = true;
49 }
50 self.start = head;
51 } else {
52 if self.reversed {
53 self.start = self.end;
54 self.reversed = false;
55 }
56 self.end = head;
57 }
58 self.goal = new_goal;
59 }
60
61 pub fn collapse_to(&mut self, point: T, new_goal: SelectionGoal) {
62 self.start = point;
63 self.end = point;
64 self.goal = new_goal;
65 self.reversed = false;
66 }
67}
68
69impl Selection<Anchor> {
70 pub fn resolve<'a, D: 'a + TextDimension>(
71 &'a self,
72 snapshot: &'a BufferSnapshot,
73 ) -> Selection<D> {
74 Selection {
75 id: self.id,
76 start: snapshot.summary_for_anchor(&self.start),
77 end: snapshot.summary_for_anchor(&self.end),
78 reversed: self.reversed,
79 goal: self.goal,
80 }
81 }
82}