makepad_code_editor/
decoration.rs1use {
2 crate::text::{Edit, Length, Position},
3 std::{ops::Deref, slice::Iter},
4};
5
6#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
7pub enum DecorationType {
8 Error,
9 Warning,
10}
11
12#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
13pub struct Decoration {
14 pub id: usize,
15 pub ty: DecorationType,
16 start: Position,
17 end: Position,
18}
19
20impl Decoration {
21 pub fn new(id: usize, start: Position, end: Position, ty: DecorationType) -> Self {
22 if start > end {
23 return Self {
24 ty,
25 id,
26 start: end,
27 end: start,
28 };
29 }
30 Self { ty, id, start, end }
31 }
32
33 pub fn is_empty(self) -> bool {
34 self.start == self.end
35 }
36
37 pub fn overlaps_with(self, other: Self) -> bool {
38 self.end() > other.start()
39 }
40
41 pub fn length(self) -> Length {
42 self.end - self.start
43 }
44
45 pub fn start(self) -> Position {
46 self.start
47 }
48
49 pub fn end(self) -> Position {
50 self.end
51 }
52
53 pub fn apply_edit(self, edit: &Edit) -> Self {
54 Self {
55 start: self.start.apply_edit(edit),
56 end: self.end.apply_edit(edit),
57 ..self
58 }
59 }
60}
61
62#[derive(Clone, Debug, Eq, Hash, PartialEq)]
63pub struct DecorationSet {
64 decorations: Vec<Decoration>,
65}
66
67impl DecorationSet {
68 pub fn new() -> Self {
69 Self::default()
70 }
71
72 pub fn as_decorations(&self) -> &[Decoration] {
73 &self.decorations
74 }
75
76 pub fn add_decoration(&mut self, decoration: Decoration) {
77 let index = match self
78 .decorations
79 .binary_search_by_key(&decoration.start(), |decoration| decoration.start())
80 {
81 Ok(index) => {
82 self.decorations[index] = decoration;
83 index
84 }
85 Err(index) => {
86 self.decorations.insert(index, decoration);
87 index
88 }
89 };
90 self.remove_overlapping_decorations(index);
91 }
92
93 pub fn clear(&mut self) {
94 self.decorations.clear();
95 }
96
97 pub fn apply_edit(&mut self, edit: &Edit) {
98 for decoration in &mut self.decorations {
99 *decoration = decoration.apply_edit(edit);
100 }
101 }
102
103 fn remove_overlapping_decorations(&mut self, index: usize) {
104 let mut index = index;
105 while index > 0 {
106 let prev_index = index - 1;
107 if !self.decorations[prev_index].overlaps_with(self.decorations[index]) {
108 break;
109 }
110 self.decorations.remove(prev_index);
111 index -= 1;
112 }
113 while index + 1 < self.decorations.len() {
114 let next_index = index + 1;
115 if !self.decorations[index].overlaps_with(self.decorations[next_index]) {
116 break;
117 }
118 self.decorations.remove(next_index);
119 }
120 }
121}
122
123impl Default for DecorationSet {
124 fn default() -> Self {
125 Self {
126 decorations: vec![],
127 }
128 }
129}
130
131impl Deref for DecorationSet {
132 type Target = [Decoration];
133
134 fn deref(&self) -> &Self::Target {
135 self.decorations.as_slice()
136 }
137}
138
139impl<'a> IntoIterator for &'a DecorationSet {
140 type Item = &'a Decoration;
141 type IntoIter = Iter<'a, Decoration>;
142
143 fn into_iter(self) -> Self::IntoIter {
144 self.iter()
145 }
146}