selection.rs

  1use crate::Anchor;
  2use crate::{rope::TextDimension, BufferSnapshot};
  3use std::cmp::Ordering;
  4use std::ops::Range;
  5
  6#[derive(Copy, Clone, Debug, Eq, PartialEq)]
  7pub enum SelectionGoal {
  8    None,
  9    Column(u32),
 10    ColumnRange { start: u32, end: u32 },
 11}
 12
 13#[derive(Clone, Debug, Eq, PartialEq)]
 14pub struct Selection<T> {
 15    pub id: usize,
 16    pub start: T,
 17    pub end: T,
 18    pub reversed: bool,
 19    pub goal: SelectionGoal,
 20}
 21
 22impl Default for SelectionGoal {
 23    fn default() -> Self {
 24        Self::None
 25    }
 26}
 27
 28impl<T: Clone> Selection<T> {
 29    pub fn head(&self) -> T {
 30        if self.reversed {
 31            self.start.clone()
 32        } else {
 33            self.end.clone()
 34        }
 35    }
 36
 37    pub fn tail(&self) -> T {
 38        if self.reversed {
 39            self.end.clone()
 40        } else {
 41            self.start.clone()
 42        }
 43    }
 44
 45    pub fn map<F, S>(&self, f: F) -> Selection<S>
 46    where
 47        F: Fn(T) -> S,
 48    {
 49        Selection::<S> {
 50            id: self.id,
 51            start: f(self.start.clone()),
 52            end: f(self.end.clone()),
 53            reversed: self.reversed,
 54            goal: self.goal,
 55        }
 56    }
 57}
 58
 59impl<T: Copy + Ord> Selection<T> {
 60    pub fn is_empty(&self) -> bool {
 61        self.start == self.end
 62    }
 63
 64    pub fn set_head(&mut self, head: T, new_goal: SelectionGoal) {
 65        if head.cmp(&self.tail()) < Ordering::Equal {
 66            if !self.reversed {
 67                self.end = self.start;
 68                self.reversed = true;
 69            }
 70            self.start = head;
 71        } else {
 72            if self.reversed {
 73                self.start = self.end;
 74                self.reversed = false;
 75            }
 76            self.end = head;
 77        }
 78        self.goal = new_goal;
 79    }
 80
 81    pub fn collapse_to(&mut self, point: T, new_goal: SelectionGoal) {
 82        self.start = point;
 83        self.end = point;
 84        self.goal = new_goal;
 85        self.reversed = false;
 86    }
 87
 88    pub fn range(&self) -> Range<T> {
 89        self.start..self.end
 90    }
 91}
 92
 93impl Selection<usize> {
 94    #[cfg(feature = "test-support")]
 95    pub fn from_offset(offset: usize) -> Self {
 96        Selection {
 97            id: 0,
 98            start: offset,
 99            end: offset,
100            goal: SelectionGoal::None,
101            reversed: false,
102        }
103    }
104}
105
106impl Selection<Anchor> {
107    pub fn resolve<'a, D: 'a + TextDimension>(
108        &'a self,
109        snapshot: &'a BufferSnapshot,
110    ) -> Selection<D> {
111        Selection {
112            id: self.id,
113            start: snapshot.summary_for_anchor(&self.start),
114            end: snapshot.summary_for_anchor(&self.end),
115            reversed: self.reversed,
116            goal: self.goal,
117        }
118    }
119}