use super::place::{Place, Range};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Selection {
pub begin: Place,
pub end: Place,
}
impl Selection {
#[must_use]
pub fn empty() -> Selection {
Selection {
begin: Place::start(),
end: Place::start(),
}
}
#[must_use]
pub fn new(begin: Place, end: Place) -> Selection {
Selection { begin, end }
}
#[must_use]
pub fn collapsed_at(place: Place) -> Selection {
Selection {
begin: place,
end: place,
}
}
#[must_use]
pub fn reset() -> Selection {
Selection {
begin: Place {
section: u32::MAX,
line: u32::MAX,
word: None,
},
end: Place {
section: u32::MAX,
line: u32::MAX,
word: None,
},
}
}
#[must_use]
pub fn is_empty(self) -> bool {
self.begin == self.end
}
#[must_use]
pub fn is_reset(self) -> bool {
self.begin
== Place {
section: u32::MAX,
line: u32::MAX,
word: None,
}
&& self.end
== Place {
section: u32::MAX,
line: u32::MAX,
word: None,
}
}
#[must_use]
pub fn is_backwards(self) -> bool {
self.end < self.begin
}
#[must_use]
pub fn range(self) -> Range {
Range::new(self.begin, self.end)
}
pub fn set_active(&mut self, place: Place) {
self.end = place;
}
}
impl Default for Selection {
fn default() -> Selection {
Selection::empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_selection_keeps_the_direction_it_was_built_with() {
let lo = Place::new(0, 0, Some(1));
let hi = Place::new(0, 0, Some(5));
let forwards = Selection::new(lo, hi);
let backwards = Selection::new(hi, lo);
assert!(!forwards.is_backwards());
assert!(backwards.is_backwards());
assert_ne!(forwards, backwards);
assert_eq!(forwards.range(), backwards.range());
}
#[test]
fn collapsed_and_reset_are_different_states() {
let here = Place::new(0, 0, Some(3));
let collapsed = Selection::collapsed_at(here);
let reset = Selection::reset();
assert!(collapsed.is_empty());
assert!(reset.is_empty());
assert!(!collapsed.is_reset());
assert!(reset.is_reset());
assert_ne!(collapsed, reset);
}
#[test]
fn extending_moves_only_the_active_end() {
let anchor = Place::new(0, 0, Some(1));
let mut sel = Selection::collapsed_at(anchor);
sel.set_active(Place::new(0, 0, Some(4)));
assert_eq!(sel.begin, anchor);
assert_eq!(sel.end, Place::new(0, 0, Some(4)));
assert!(!sel.is_empty());
}
#[test]
fn the_range_is_always_ordered() {
let sel = Selection::new(Place::new(0, 0, Some(7)), Place::new(0, 0, Some(2)));
assert!(sel.range().begin() <= sel.range().end());
assert_eq!(sel.range().begin(), Place::new(0, 0, Some(2)));
}
}