From 3bf47be51e1f7d5ab79b0d8dceb9d49494a83fbe Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 24 Jul 2021 08:09:04 -0600 Subject: [PATCH] WIP --- zed/src/editor.rs | 23 +++--- zed/src/editor/display_map.rs | 4 +- zed/src/editor/display_map/wrap_map.rs | 6 +- zed/src/editor/element.rs | 104 +++++++++++++------------ 4 files changed, 76 insertions(+), 61 deletions(-) diff --git a/zed/src/editor.rs b/zed/src/editor.rs index f004828e1bc05105f2e50e359d9cbedcea424b89..f177fb36903f607383bbff8c95ffdab4cc92769c 100644 --- a/zed/src/editor.rs +++ b/zed/src/editor.rs @@ -385,12 +385,12 @@ pub struct Editor { } struct Snapshot { - display_snapshot: DisplayMapSnapshot, - gutter_visible: bool, - scroll_position: Vector2F, - theme: Arc, - font_family: FamilyId, - font_size: f32, + pub display_snapshot: DisplayMapSnapshot, + pub gutter_visible: bool, + pub scroll_position: Vector2F, + pub theme: Arc, + pub font_family: FamilyId, + pub font_size: f32, } struct AddSelectionsState { @@ -2176,8 +2176,8 @@ impl Editor { self.settings.borrow().buffer_font_size } - pub fn set_wrap_width(&self, width: f32, cx: &mut MutableAppContext) { - self.display_map.set_wrap_width(Some(width), cx); + pub fn set_wrap_width(&self, width: f32, cx: &mut MutableAppContext) -> bool { + self.display_map.set_wrap_width(Some(width), cx) } fn next_blink_epoch(&mut self) -> usize { @@ -2254,6 +2254,10 @@ impl Editor { } impl Snapshot { + pub fn max_point(&self) -> DisplayPoint { + self.display_snapshot.max_point() + } + pub fn font_ascent(&self, font_cache: &FontCache) -> f32 { let font_id = font_cache.default_font(self.font_family); let ascent = font_cache.metric(font_id, |m| m.ascent); @@ -2348,7 +2352,7 @@ impl Snapshot { let mut prev_font_properties = FontProperties::new(); let mut prev_font_id = font_cache - .select_font(font_family, &prev_font_properties) + .select_font(self.font_family, &prev_font_properties) .unwrap(); let mut layouts = Vec::with_capacity(rows.len()); @@ -2708,6 +2712,7 @@ mod tests { let layouts = view .read(cx) + .snapshot(cx) .layout_line_numbers(1000.0, &font_cache, &layout_cache, cx) .unwrap(); assert_eq!(layouts.len(), 6); diff --git a/zed/src/editor/display_map.rs b/zed/src/editor/display_map.rs index 8004bb7b1850fbccf62cbb854f8908cb03165795..bfef58d7bebeec3d26de637be4c316c5d9c5edce 100644 --- a/zed/src/editor/display_map.rs +++ b/zed/src/editor/display_map.rs @@ -75,8 +75,8 @@ impl DisplayMap { self.wrap_map.sync(snapshot, edits, cx); } - pub fn set_wrap_width(&self, width: Option, cx: &mut MutableAppContext) { - self.wrap_map.set_wrap_width(width, cx); + pub fn set_wrap_width(&self, width: Option, cx: &mut MutableAppContext) -> bool { + self.wrap_map.set_wrap_width(width, cx) } pub fn notifications(&self) -> impl Stream { diff --git a/zed/src/editor/display_map/wrap_map.rs b/zed/src/editor/display_map/wrap_map.rs index fd2522661e1dd907fc79e6cede3febde45569093..63071a47f24bc99211c5cfb725daa729ca125bef 100644 --- a/zed/src/editor/display_map/wrap_map.rs +++ b/zed/src/editor/display_map/wrap_map.rs @@ -123,10 +123,10 @@ impl WrapMap { self.0.lock().snapshot.clone() } - pub fn set_wrap_width(&self, wrap_width: Option, cx: &mut MutableAppContext) { + pub fn set_wrap_width(&self, wrap_width: Option, cx: &mut MutableAppContext) -> bool { let mut state = self.0.lock(); if wrap_width == state.wrap_width { - return; + return false; } state.wrap_width = wrap_width; @@ -173,6 +173,8 @@ impl WrapMap { } } } + + true } fn flush_edits(&self, executor: &Arc) { diff --git a/zed/src/editor/element.rs b/zed/src/editor/element.rs index 5916d7d1575550b760a2dc2a9baebfa90a1bfb23..7dcbf407bd38a50e225a16982fe4c63cc6dea943 100644 --- a/zed/src/editor/element.rs +++ b/zed/src/editor/element.rs @@ -339,17 +339,16 @@ impl Element for EditorElement { unimplemented!("we don't yet handle an infinite width constraint on buffer elements"); } - let view = self.view(cx.app); - let font_cache = &cx.font_cache; let layout_cache = &cx.text_layout_cache; - let line_height = view.line_height(font_cache); + let snapshot = self.update_view(cx.app, |view, cx| view.snapshot(cx)); + let line_height = snapshot.line_height(font_cache); let gutter_padding; let gutter_width; - if view.is_gutter_visible() { - gutter_padding = view.em_width(cx.font_cache); - match view.max_line_number_width(cx.font_cache, cx.text_layout_cache, cx.app) { + if snapshot.gutter_visible { + gutter_padding = snapshot.em_width(cx.font_cache); + match snapshot.max_line_number_width(cx.font_cache, cx.text_layout_cache, cx.app) { Err(error) => { log::error!("error computing max line number width: {}", error); return (size, None); @@ -363,24 +362,35 @@ impl Element for EditorElement { let gutter_size = vec2f(gutter_width, size.y()); let text_size = size - vec2f(gutter_width, 0.0); - let text_offset = vec2f(-view.font_descent(cx.font_cache), 0.); - let em_width = view.em_width(cx.font_cache); + let text_offset = vec2f(-snapshot.font_descent(cx.font_cache), 0.); + let em_width = snapshot.em_width(font_cache); let overscroll = vec2f(em_width, 0.); - let wrap_width = text_size.x() - text_offset.x() - overscroll.x(); - // TODO: Core text doesn't seem to be keeping our lines below the specified wrap width. Find out why. - let wrap_width = wrap_width - em_width; - self.update_view(cx.app, |view, cx| { - view.set_wrap_width(wrap_width, cx); + let wrap_width = text_size.x() - text_offset.x() - overscroll.x() - em_width; + let snapshot = self.update_view(cx.app, |view, cx| { + if view.set_wrap_width(wrap_width, cx) { + view.snapshot(cx) + } else { + snapshot + } }); if size.y().is_infinite() { - size.set_y((view.max_point(cx.app).row() + 1) as f32 * view.line_height(cx.font_cache)); + size.set_y((snapshot.max_point().row() + 1) as f32 * line_height); } - let autoscroll_horizontally = view.autoscroll_vertically(size.y(), line_height, cx.app); + let (autoscroll_horizontally, snapshot) = self.update_view(cx.app, |view, cx| { + let autoscroll_horizontally = view.autoscroll_vertically(size.y(), line_height, cx); + let snapshot = view.snapshot(cx); + (autoscroll_horizontally, snapshot) + }); - let line_number_layouts = if view.is_gutter_visible() { - match view.layout_line_numbers(size.y(), cx.font_cache, cx.text_layout_cache, cx.app) { + let line_number_layouts = if snapshot.gutter_visible { + match snapshot.layout_line_numbers( + size.y(), + cx.font_cache, + cx.text_layout_cache, + cx.app, + ) { Err(error) => { log::error!("error laying out line numbers: {}", error); return (size, None); @@ -391,13 +401,13 @@ impl Element for EditorElement { Vec::new() }; - let start_row = view.scroll_position().y() as u32; - let scroll_top = view.scroll_position().y() * line_height; + let start_row = snapshot.scroll_position.y() as u32; + let scroll_top = snapshot.scroll_position.y() * line_height; let end_row = ((scroll_top + size.y()) / line_height).ceil() as u32 + 1; // Add 1 to ensure selections bleed off screen let mut max_visible_line_width = 0.0; let line_layouts = - match view.layout_lines(start_row..end_row, font_cache, layout_cache, cx.app) { + match snapshot.layout_lines(start_row..end_row, font_cache, layout_cache, cx.app) { Err(error) => { log::error!("error laying out lines: {}", error); return (size, None); @@ -413,6 +423,7 @@ impl Element for EditorElement { } }; + let view = self.view(cx.app); let mut selections = HashMap::new(); for selection_set_id in view.active_selection_sets(cx.app) { selections.insert( @@ -426,7 +437,7 @@ impl Element for EditorElement { ); } - let layout_state = Some(LayoutState { + let layout = LayoutState { size, gutter_size, gutter_padding, @@ -437,37 +448,35 @@ impl Element for EditorElement { line_number_layouts, selections, max_visible_line_width, - autoscroll_horizontally, - }); + }; - (size, layout_state) + let view = self.view(cx.app); + view.clamp_scroll_left( + layout + .scroll_max(view, cx.font_cache, cx.text_layout_cache, cx.app) + .x(), + ); + + if autoscroll_horizontally { + view.autoscroll_horizontally( + view.scroll_position().y() as u32, + layout.text_size.x(), + layout.scroll_width(view, cx.font_cache, cx.text_layout_cache, cx.app), + snapshot.em_width(cx.font_cache), + &layout.line_layouts, + cx.app, + ); + } + + (size, Some(layout)) } fn after_layout( &mut self, - _: Vector2F, - layout: &mut Option, + size: Vector2F, + layout: &mut Self::LayoutState, cx: &mut AfterLayoutContext, ) { - if let Some(layout) = layout { - let view = self.view(cx.app); - view.clamp_scroll_left( - layout - .scroll_max(view, cx.font_cache, cx.text_layout_cache, cx.app) - .x(), - ); - - if layout.autoscroll_horizontally { - view.autoscroll_horizontally( - view.scroll_position().y() as u32, - layout.text_size.x(), - layout.scroll_width(view, cx.font_cache, cx.text_layout_cache, cx.app), - view.em_width(cx.font_cache), - &layout.line_layouts, - cx.app, - ); - } - } } fn paint( @@ -483,7 +492,7 @@ impl Element for EditorElement { layout.text_size, ); - if self.view(cx.app).is_gutter_visible() { + if layout.gutter_size.x() > 0. { self.paint_gutter(gutter_bounds, layout, cx); } self.paint_text(text_bounds, layout, cx); @@ -552,7 +561,6 @@ pub struct LayoutState { overscroll: Vector2F, text_offset: Vector2F, max_visible_line_width: f32, - autoscroll_horizontally: bool, } impl LayoutState { @@ -604,7 +612,7 @@ impl PaintState { let scroll_position = view.scroll_position(); let position = position - self.text_bounds.origin(); let y = position.y().max(0.0).min(layout.size.y()); - let row = ((y / view.line_height(font_cache)) + scroll_position.y()) as u32; + let row = ((y / line_h) + scroll_position.y()) as u32; let row = cmp::min(row, view.max_point(cx).row()); let line = &layout.line_layouts[(row - scroll_position.y() as u32) as usize]; let x = position.x() + (scroll_position.x() * view.em_width(font_cache));