makepad_code_editor/
decoration.rs

1use {
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}