1use crate::Anchor;
2use crate::{rope::TextDimension, BufferSnapshot, ToOffset, ToPoint};
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 Default for SelectionGoal {
22 fn default() -> Self {
23 Self::None
24 }
25}
26
27impl<T: Clone> Selection<T> {
28 pub fn head(&self) -> T {
29 if self.reversed {
30 self.start.clone()
31 } else {
32 self.end.clone()
33 }
34 }
35
36 pub fn tail(&self) -> T {
37 if self.reversed {
38 self.end.clone()
39 } else {
40 self.start.clone()
41 }
42 }
43}
44
45impl<T: ToOffset + ToPoint + Copy + Ord> Selection<T> {
46 pub fn is_empty(&self) -> bool {
47 self.start == self.end
48 }
49
50 pub fn set_head(&mut self, head: T) {
51 if head.cmp(&self.tail()) < Ordering::Equal {
52 if !self.reversed {
53 self.end = self.start;
54 self.reversed = true;
55 }
56 self.start = head;
57 } else {
58 if self.reversed {
59 self.start = self.end;
60 self.reversed = false;
61 }
62 self.end = head;
63 }
64 }
65}
66
67impl Selection<Anchor> {
68 pub fn resolve<'a, D: 'a + TextDimension>(
69 &'a self,
70 snapshot: &'a BufferSnapshot,
71 ) -> Selection<D> {
72 Selection {
73 id: self.id,
74 start: snapshot.summary_for_anchor(&self.start),
75 end: snapshot.summary_for_anchor(&self.end),
76 reversed: self.reversed,
77 goal: self.goal,
78 }
79 }
80}