diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index 1cb5d961eb..9b973d2457 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -66,7 +66,6 @@ where pub struct BlockContext<'a> { pub cx: &'a AppContext, - pub gutter_width: f32, pub anchor_x: f32, } @@ -822,6 +821,10 @@ impl AlignedBlock { pub fn render(&self, cx: &BlockContext) -> ElementBox { self.render.lock()(cx) } + + pub fn disposition(&self) -> BlockDisposition { + self.block.disposition + } } impl Deref for AlignedBlock { @@ -935,11 +938,7 @@ mod tests { start_row..start_row + block.height(), block.column(), block - .render(&BlockContext { - cx, - gutter_width: 0., - anchor_x: 0., - }) + .render(&BlockContext { cx, anchor_x: 0. }) .name() .unwrap() .to_string(), diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index c419b1dab5..539736aca2 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -2883,7 +2883,7 @@ impl Editor { new_styles.insert(*block_id, move |cx: &BlockContext| { let diagnostic = diagnostic.clone(); let settings = build_settings.borrow()(cx.cx); - render_diagnostic(diagnostic, &settings.style) + render_diagnostic(diagnostic, &settings.style, is_valid, cx.anchor_x) }); } self.display_map @@ -2931,7 +2931,7 @@ impl Editor { render: Arc::new(move |cx| { let settings = build_settings.borrow()(cx.cx); let diagnostic = diagnostic.clone(); - render_diagnostic(diagnostic, &settings.style) + render_diagnostic(diagnostic, &settings.style, true, cx.anchor_x) }), disposition: BlockDisposition::Below, } @@ -3641,10 +3641,18 @@ impl SelectionExt for Selection { } } -fn render_diagnostic(diagnostic: Diagnostic, style: &EditorStyle) -> ElementBox { +fn render_diagnostic( + diagnostic: Diagnostic, + style: &EditorStyle, + valid: bool, + anchor_x: f32, +) -> ElementBox { let mut text_style = style.text.clone(); - text_style.color = diagnostic_style(diagnostic.severity, true, &style).text; - Text::new(diagnostic.message, text_style).boxed() + text_style.color = diagnostic_style(diagnostic.severity, valid, &style).text; + Text::new(diagnostic.message, text_style) + .contained() + .with_margin_left(anchor_x) + .boxed() } pub fn diagnostic_style( diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 13dd5cfdc7..b50aa2d9c5 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1,4 +1,4 @@ -use crate::display_map::BlockContext; +use crate::display_map::{BlockContext, BlockDisposition}; use super::{ DisplayPoint, Editor, EditorMode, EditorSettings, EditorStyle, Input, Scroll, Select, @@ -220,7 +220,6 @@ impl EditorElement { ) { let bounds = gutter_bounds.union_rect(text_bounds); let scroll_top = layout.snapshot.scroll_position().y() * layout.line_height; - let start_row = layout.snapshot.scroll_position().y() as u32; let editor = self.view(cx.app); let style = &self.settings.style; cx.scene.push_quad(Quad { @@ -419,13 +418,19 @@ impl EditorElement { fn paint_blocks( &mut self, - bounds: RectF, + text_bounds: RectF, visible_bounds: RectF, - layout: &LayoutState, + layout: &mut LayoutState, cx: &mut PaintContext, ) { - for (row_range, block) in &layout.blocks { - // + let scroll_position = layout.snapshot.scroll_position(); + let scroll_left = scroll_position.x() * layout.em_width; + let scroll_top = scroll_position.y() * layout.line_height; + + for (row, element) in &mut layout.blocks { + let origin = text_bounds.origin() + + vec2f(-scroll_left, *row as f32 * layout.line_height - scroll_top); + element.paint(origin, visible_bounds, cx); } } @@ -619,19 +624,37 @@ impl EditorElement { &mut self, rows: Range, snapshot: &Snapshot, - cx: &LayoutContext, - ) -> Vec<(Range, ElementBox)> { + text_width: f32, + line_height: f32, + style: &EditorStyle, + line_layouts: &[text_layout::Line], + cx: &mut LayoutContext, + ) -> Vec<(u32, ElementBox)> { snapshot - .blocks_in_range(rows) + .blocks_in_range(rows.clone()) .map(|(start_row, block)| { - ( - start_row..start_row + block.height(), - block.render(&BlockContext { - cx, - gutter_width: 0.0, - anchor_x: 0.0, - }), - ) + let anchor_row = match block.disposition() { + BlockDisposition::Above => start_row + block.height(), + BlockDisposition::Below => start_row - 1, + }; + + let anchor_x = if rows.contains(&anchor_row) { + line_layouts[(anchor_row - rows.start) as usize] + .x_for_index(block.column() as usize) + } else { + layout_line(anchor_row, snapshot, style, cx.text_layout_cache) + .x_for_index(block.column() as usize) + }; + + let mut element = block.render(&BlockContext { cx, anchor_x }); + element.layout( + SizeConstraint { + min: Vector2F::zero(), + max: vec2f(text_width, block.height() as f32 * line_height), + }, + cx, + ); + (start_row, element) }) .collect() } @@ -750,7 +773,15 @@ impl Element for EditorElement { } } - let blocks = self.layout_blocks(start_row..end_row, &snapshot, cx); + let blocks = self.layout_blocks( + start_row..end_row, + &snapshot, + text_size.x(), + line_height, + &style, + &line_layouts, + cx, + ); let mut layout = LayoutState { size, @@ -896,7 +927,7 @@ pub struct LayoutState { highlighted_row: Option, line_layouts: Vec, line_number_layouts: Vec>, - blocks: Vec<(Range, ElementBox)>, + blocks: Vec<(u32, ElementBox)>, line_height: f32, em_width: f32, em_advance: f32, @@ -909,7 +940,8 @@ pub struct LayoutState { impl LayoutState { fn scroll_width(&self, layout_cache: &TextLayoutCache) -> f32 { let row = self.snapshot.longest_row(); - let longest_line_width = self.layout_line(row, &self.snapshot, layout_cache).width(); + let longest_line_width = + layout_line(row, &self.snapshot, &self.style, layout_cache).width(); longest_line_width.max(self.max_visible_line_width) + self.overscroll.x() } @@ -924,36 +956,36 @@ impl LayoutState { max_row.saturating_sub(1) as f32, ) } +} - pub fn layout_line( - &self, - row: u32, - snapshot: &Snapshot, - layout_cache: &TextLayoutCache, - ) -> text_layout::Line { - let mut line = snapshot.line(row); +fn layout_line( + row: u32, + snapshot: &Snapshot, + style: &EditorStyle, + layout_cache: &TextLayoutCache, +) -> text_layout::Line { + let mut line = snapshot.line(row); - if line.len() > MAX_LINE_LEN { - let mut len = MAX_LINE_LEN; - while !line.is_char_boundary(len) { - len -= 1; - } - line.truncate(len); + if line.len() > MAX_LINE_LEN { + let mut len = MAX_LINE_LEN; + while !line.is_char_boundary(len) { + len -= 1; } - - layout_cache.layout_str( - &line, - self.style.text.font_size, - &[( - snapshot.line_len(row) as usize, - RunStyle { - font_id: self.style.text.font_id, - color: Color::black(), - underline: None, - }, - )], - ) + line.truncate(len); } + + layout_cache.layout_str( + &line, + style.text.font_size, + &[( + snapshot.line_len(row) as usize, + RunStyle { + font_id: style.text.font_id, + color: Color::black(), + underline: None, + }, + )], + ) } pub struct PaintState {