gpui_base/input/editor/display_map/
display_map.rs1use std::ops::Range;
8
9use gpui::{App, Font, Pixels};
10use ropey::Rope;
11
12use super::fold_map::FoldMap;
13use super::folding::FoldRange;
14pub use super::text_wrapper::WrappingIndent;
15use super::text_wrapper::{LineItem, WrapDisplayPoint};
16use super::wrap_map::WrapMap;
17use super::{BufferPoint, DisplayPoint};
18use crate::input::Point as TreeSitterPoint;
19use crate::input::display_map::WrapPoint;
20use crate::input::rope_ext::RopeExt as _;
21
22pub struct DisplayMap {
30 wrap_map: WrapMap,
31 fold_map: FoldMap,
32}
33
34impl DisplayMap {
35 pub fn new(font: Font, font_size: Pixels, wrap_width: Option<Pixels>) -> Self {
36 Self {
37 wrap_map: WrapMap::new(font, font_size, wrap_width),
38 fold_map: FoldMap::new(),
39 }
40 }
41
42 pub fn buffer_pos_to_display_pos(&self, pos: BufferPoint) -> DisplayPoint {
46 let wrap_pos = self.wrap_map.buffer_pos_to_wrap_pos(pos);
48
49 if let Some(display_row) = self.fold_map.wrap_row_to_display_row(wrap_pos.row) {
51 DisplayPoint::new(display_row, wrap_pos.col)
52 } else {
53 let display_row = self.fold_map.nearest_visible_display_row(wrap_pos.row);
55 DisplayPoint::new(display_row, 0) }
57 }
58
59 pub fn display_pos_to_buffer_pos(&self, pos: DisplayPoint) -> BufferPoint {
61 let wrap_row = self.fold_map.display_row_to_wrap_row(pos.row).unwrap_or(0);
63
64 let wrap_pos = WrapPoint::new(wrap_row, pos.col);
66 self.wrap_map.wrap_pos_to_buffer_pos(wrap_pos)
67 }
68
69 #[inline]
71 pub fn display_row_count(&self) -> usize {
72 self.fold_map.display_row_count()
73 }
74
75 pub fn display_row_to_buffer_line(&self, display_row: usize) -> usize {
77 let wrap_row = self
79 .fold_map
80 .display_row_to_wrap_row(display_row)
81 .unwrap_or(0);
82
83 self.wrap_map.wrap_row_to_buffer_line(wrap_row)
85 }
86
87 pub fn buffer_line_to_display_row_range(&self, line: usize) -> Option<Range<usize>> {
90 let wrap_row_range = self.wrap_map.buffer_line_to_wrap_row_range(line);
92
93 let mut first_display_row = None;
95 let mut last_display_row = None;
96
97 for wrap_row in wrap_row_range {
98 if let Some(display_row) = self.fold_map.wrap_row_to_display_row(wrap_row) {
99 if first_display_row.is_none() {
100 first_display_row = Some(display_row);
101 }
102 last_display_row = Some(display_row);
103 }
104 }
105
106 if let (Some(start), Some(end)) = (first_display_row, last_display_row) {
107 Some(start..end + 1)
108 } else {
109 None }
111 }
112
113 #[inline]
115 pub fn is_buffer_line_hidden(&self, line: usize) -> bool {
116 self.buffer_line_to_display_row_range(line).is_none()
117 }
118
119 pub fn buffer_line_to_display_row(&self, line: usize) -> usize {
122 match self.buffer_line_to_display_row_range(line) {
123 Some(range) => range.start,
124 None => {
125 let wrap_row = self.wrap_map.buffer_line_to_first_wrap_row(line);
126 self.fold_map.nearest_visible_display_row(wrap_row)
127 }
128 }
129 }
130
131 pub fn set_fold_candidates(&mut self, candidates: Vec<FoldRange>) {
133 self.fold_map.set_candidates(candidates);
134 self.rebuild_fold_projection();
135 }
136
137 pub fn set_folded(&mut self, start_line: usize, folded: bool) {
139 self.fold_map.set_folded(start_line, folded);
140 self.rebuild_fold_projection();
141 }
142
143 pub fn toggle_fold(&mut self, start_line: usize) {
145 self.fold_map.toggle_fold(start_line);
146 self.rebuild_fold_projection();
147 }
148
149 #[inline]
151 pub fn is_folded_at(&self, start_line: usize) -> bool {
152 self.fold_map.is_folded_at(start_line)
153 }
154
155 #[inline]
157 pub fn is_fold_candidate(&self, start_line: usize) -> bool {
158 self.fold_map.is_fold_candidate(start_line)
159 }
160
161 #[inline]
163 pub fn folded_ranges(&self) -> &[FoldRange] {
164 self.fold_map.folded_ranges()
165 }
166
167 pub fn clear_folds(&mut self) {
169 self.fold_map.clear_folds();
170 self.rebuild_fold_projection();
171 }
172
173 pub fn adjust_folds_for_edit(&mut self, old_text: &Rope, range: &Range<usize>, new_text: &str) {
180 if self.fold_map.folded_ranges().is_empty() && self.fold_map.fold_candidates().is_empty() {
181 return;
182 }
183
184 let edit_start_line = old_text.offset_to_point(range.start).row;
185 let edit_end_line = old_text.offset_to_point(range.end.min(old_text.len())).row;
186
187 let old_lines_in_range = edit_end_line.saturating_sub(edit_start_line);
188 let new_lines_in_range = new_text.chars().filter(|c| *c == '\n').count();
189 let line_delta = new_lines_in_range as isize - old_lines_in_range as isize;
190
191 self.fold_map
192 .adjust_folds_for_edit(edit_start_line, edit_end_line, line_delta);
193 }
194
195 pub fn update_fold_candidates_for_edit(
200 &mut self,
201 extract_fold_ranges: impl FnOnce(Range<usize>, &Rope) -> Vec<FoldRange>,
202 edit_byte_range: Range<usize>,
203 new_text: &Rope,
204 ) {
205 let new_start_line = new_text.offset_to_point(edit_byte_range.start).row;
206 let new_end_line = new_text
207 .offset_to_point(edit_byte_range.end.min(new_text.len()))
208 .row;
209
210 let new_candidates = extract_fold_ranges(edit_byte_range, new_text);
211 self.fold_map
212 .merge_candidates_for_edit(new_start_line, new_end_line, new_candidates);
213 }
214
215 pub fn on_text_changed(
217 &mut self,
218 changed_text: &Rope,
219 range: &Range<usize>,
220 new_text: &Rope,
221 cx: &mut App,
222 ) {
223 self.wrap_map
224 .on_text_changed(changed_text, range, new_text, cx);
225 self.rebuild_fold_projection();
226 }
227
228 pub fn on_layout_changed(&mut self, wrap_width: Option<Pixels>, cx: &mut App) {
230 self.wrap_map.on_layout_changed(wrap_width, cx);
231 self.rebuild_fold_projection();
232 }
233
234 pub fn set_wrapping_indent(&mut self, wrapping_indent: WrappingIndent, cx: &mut App) {
236 self.wrap_map.set_wrapping_indent(wrapping_indent, cx);
237 self.rebuild_fold_projection();
238 }
239
240 pub fn set_font(&mut self, font: Font, font_size: Pixels, cx: &mut App) {
242 self.wrap_map.set_font(font, font_size, cx);
243 self.rebuild_fold_projection();
244 }
245
246 pub fn ensure_text_prepared(&mut self, text: &Rope, cx: &mut App) {
248 let did_initialize = self.wrap_map.ensure_text_prepared(text, cx);
249 if did_initialize {
250 self.rebuild_fold_projection();
251 }
252 }
253
254 pub fn set_text(&mut self, text: &Rope, cx: &mut App) {
256 self.wrap_map.set_text(text, cx);
257 self.rebuild_fold_projection();
258 }
259
260 fn rebuild_fold_projection(&mut self) {
265 if !self.fold_map.folded_ranges().is_empty() {
266 self.fold_map.rebuild(&self.wrap_map);
267 } else {
268 self.fold_map
271 .mark_dirty_with_wrap_count(self.wrap_map.wrap_row_count());
272 }
273 }
274
275 #[inline]
279 pub(crate) fn offset_to_wrap_display_point(&self, offset: usize) -> WrapDisplayPoint {
280 self.wrap_map.wrapper().offset_to_display_point(offset)
281 }
282
283 #[inline]
286 pub(crate) fn offset_to_wrap_display_point_with_affinity(
287 &self,
288 offset: usize,
289 line_end_affinity: bool,
290 ) -> WrapDisplayPoint {
291 self.wrap_map
292 .wrapper()
293 .offset_to_display_point_with_affinity(offset, line_end_affinity)
294 }
295
296 #[inline]
298 pub(crate) fn wrap_display_point_to_offset(&self, point: WrapDisplayPoint) -> usize {
299 self.wrap_map.wrapper().display_point_to_offset(point)
300 }
301
302 #[inline]
304 pub(crate) fn wrap_display_point_to_point(&self, point: WrapDisplayPoint) -> TreeSitterPoint {
305 self.wrap_map.wrapper().display_point_to_point(point)
306 }
307
308 #[inline]
311 pub fn wrap_row_to_display_row(&self, wrap_row: usize) -> Option<usize> {
312 self.fold_map.wrap_row_to_display_row(wrap_row)
313 }
314
315 #[inline]
317 pub fn nearest_visible_display_row(&self, wrap_row: usize) -> usize {
318 self.fold_map.nearest_visible_display_row(wrap_row)
319 }
320
321 #[inline]
323 pub fn display_row_to_wrap_row(&self, display_row: usize) -> Option<usize> {
324 self.fold_map.display_row_to_wrap_row(display_row)
325 }
326
327 #[inline]
329 pub(crate) fn longest_row(&self) -> usize {
330 self.wrap_map.wrapper().longest_row()
331 }
332
333 #[inline]
337 pub(crate) fn line(&self, row: usize) -> Option<&LineItem> {
338 self.wrap_map.line(row)
339 }
340
341 #[inline]
343 pub fn text(&self) -> &Rope {
344 self.wrap_map.text()
345 }
346
347 #[inline]
349 pub fn visible_wrap_row_count_for_buffer_line(&self, line: usize) -> usize {
350 self.wrap_map
351 .visible_wrap_row_count_for_line(line, &self.fold_map)
352 }
353
354 #[inline]
356 pub fn wrap_row_count(&self) -> usize {
357 self.wrap_map.wrap_row_count()
358 }
359
360 #[inline]
362 pub fn buffer_line_count(&self) -> usize {
363 self.wrap_map.buffer_line_count()
364 }
365}