atmos/os_lib/
dom_range.rs1use core::cmp::Ordering;
7
8pub const START_TO_START: u16 = 0;
10pub const START_TO_END: u16 = 1;
11pub const END_TO_END: u16 = 2;
12pub const END_TO_START: u16 = 3;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub struct BoundaryPoint {
18 pub node_order: usize,
20 pub offset: usize,
22}
23
24impl BoundaryPoint {
25 pub const fn new(node_order: usize, offset: usize) -> Self {
26 Self { node_order, offset }
27 }
28
29 pub fn compare(&self, other: &Self) -> Ordering {
32 match self.node_order.cmp(&other.node_order) {
33 Ordering::Equal => self.offset.cmp(&other.offset),
34 ord => ord,
35 }
36 }
37}
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
41pub struct RangeData {
42 pub start: BoundaryPoint,
43 pub end: BoundaryPoint,
44}
45
46impl RangeData {
47 pub const fn new(start: BoundaryPoint, end: BoundaryPoint) -> Self {
48 Self { start, end }
49 }
50
51 pub fn is_collapsed(&self) -> bool {
53 self.start == self.end
54 }
55
56 pub fn collapse(&mut self, to_start: bool) {
60 if to_start {
61 self.end = self.start;
62 } else {
63 self.start = self.end;
64 }
65 }
66
67 pub fn set_start(&mut self, point: BoundaryPoint) {
70 self.start = point;
71 if self.start.compare(&self.end) == Ordering::Greater {
72 self.end = self.start;
73 }
74 }
75
76 pub fn set_end(&mut self, point: BoundaryPoint) {
79 self.end = point;
80 if self.end.compare(&self.start) == Ordering::Less {
81 self.start = self.end;
82 }
83 }
84
85 pub fn compare_boundary_points(&self, how: u16, source: &Self) -> Result<i16, &'static str> {
88 let (this_pt, source_pt) = match how {
89 START_TO_START => (self.start, source.start),
90 START_TO_END => (self.end, source.start),
91 END_TO_END => (self.end, source.end),
92 END_TO_START => (self.start, source.end),
93 _ => return Err("Invalid compare how type"),
94 };
95 Ok(match this_pt.compare(&source_pt) {
96 Ordering::Less => -1,
97 Ordering::Equal => 0,
98 Ordering::Greater => 1,
99 })
100 }
101
102 pub fn is_point_in_range(&self, point: BoundaryPoint) -> bool {
105 self.start.compare(&point) != Ordering::Greater
106 && point.compare(&self.end) != Ordering::Greater
107 }
108
109 pub fn intersects(&self, other_start: BoundaryPoint, other_end: BoundaryPoint) -> bool {
111 other_end.compare(&self.start) != Ordering::Less
113 && other_start.compare(&self.end) != Ordering::Greater
114 }
115}
116
117#[derive(Debug, Clone, Copy, PartialEq, Eq)]
119pub enum SelectionType {
120 None,
121 Caret,
122 Range,
123}
124
125impl SelectionType {
126 pub fn as_str(&self) -> &'static str {
127 match self {
128 SelectionType::None => "None",
129 SelectionType::Caret => "Caret",
130 SelectionType::Range => "Range",
131 }
132 }
133}
134
135#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
137pub struct SelectionState {
138 pub range: Option<RangeData>,
139}
140
141impl SelectionState {
142 pub fn new() -> Self {
143 Self { range: None }
144 }
145
146 pub fn range_count(&self) -> usize {
147 if self.range.is_some() { 1 } else { 0 }
148 }
149
150 pub fn is_collapsed(&self) -> bool {
151 self.range.map(|r| r.is_collapsed()).unwrap_or(true)
152 }
153
154 pub fn selection_type(&self) -> SelectionType {
155 match self.range {
156 None => SelectionType::None,
157 Some(r) if r.is_collapsed() => SelectionType::Caret,
158 Some(_) => SelectionType::Range,
159 }
160 }
161
162 pub fn anchor_point(&self) -> Option<BoundaryPoint> {
163 self.range.map(|r| r.start)
164 }
165
166 pub fn focus_point(&self) -> Option<BoundaryPoint> {
167 self.range.map(|r| r.end)
168 }
169
170 pub fn add_range(&mut self, range: RangeData) {
171 self.range = Some(range);
172 }
173
174 pub fn remove_range(&mut self) {
175 self.range = None;
176 }
177
178 pub fn remove_all_ranges(&mut self) {
179 self.range = None;
180 }
181
182 pub fn collapse(&mut self, point: BoundaryPoint) {
183 self.range = Some(RangeData::new(point, point));
184 }
185
186 pub fn collapse_to_start(&mut self) {
187 if let Some(ref mut r) = self.range {
188 r.collapse(true);
189 }
190 }
191
192 pub fn collapse_to_end(&mut self) {
193 if let Some(ref mut r) = self.range {
194 r.collapse(false);
195 }
196 }
197}