WIP: Start on rendering a left border on diagnostic blocks

Co-Authored-By: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
Nathan Sobo 2021-11-29 18:26:17 -07:00
parent b9cee0cc53
commit b608d78b40
5 changed files with 78 additions and 40 deletions

View file

@ -439,7 +439,11 @@ impl ToDisplayPoint for Anchor {
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DisplayRow { pub enum DisplayRow {
Buffer(u32), Buffer(u32),
Block(BlockId, Option<BlockStyle>), Block {
id: BlockId,
column: u32,
style: Option<BlockStyle>,
},
Wrap, Wrap,
} }

View file

@ -915,7 +915,11 @@ impl<'a> Iterator for BufferRows<'a> {
let style = self let style = self
.cx .cx
.and_then(|cx| block.build_style.lock().as_ref().map(|f| f(cx))); .and_then(|cx| block.build_style.lock().as_ref().map(|f| f(cx)));
Some(DisplayRow::Block(block.id, style)) Some(DisplayRow::Block {
id: block.id,
style,
column: block.column,
})
} else { } else {
Some(self.input_buffer_rows.next().unwrap()) Some(self.input_buffer_rows.next().unwrap())
} }
@ -1217,12 +1221,24 @@ mod tests {
snapshot.buffer_rows(0, None).collect::<Vec<_>>(), snapshot.buffer_rows(0, None).collect::<Vec<_>>(),
&[ &[
DisplayRow::Buffer(0), DisplayRow::Buffer(0),
DisplayRow::Block(block_ids[0], None), DisplayRow::Block {
DisplayRow::Block(block_ids[1], None), id: block_ids[0],
style: None,
column: 0
},
DisplayRow::Block {
id: block_ids[1],
style: None,
column: 0
},
DisplayRow::Buffer(1), DisplayRow::Buffer(1),
DisplayRow::Buffer(2), DisplayRow::Buffer(2),
DisplayRow::Buffer(3), DisplayRow::Buffer(3),
DisplayRow::Block(block_ids[2], None) DisplayRow::Block {
id: block_ids[2],
style: None,
column: 0
}
] ]
); );

View file

@ -218,6 +218,7 @@ impl EditorElement {
cx: &mut PaintContext, cx: &mut PaintContext,
) { ) {
let bounds = gutter_bounds.union_rect(text_bounds); let bounds = gutter_bounds.union_rect(text_bounds);
let content_origin = text_bounds.origin() + layout.text_offset;
let scroll_top = layout.snapshot.scroll_position().y() * layout.line_height; let scroll_top = layout.snapshot.scroll_position().y() * layout.line_height;
let start_row = layout.snapshot.scroll_position().y() as u32; let start_row = layout.snapshot.scroll_position().y() as u32;
let editor = self.view(cx.app); let editor = self.view(cx.app);
@ -280,27 +281,30 @@ impl EditorElement {
} }
// Draw block backgrounds // Draw block backgrounds
for (ixs, block_style) in &layout.block_layouts { for block_layout in &layout.block_layouts {
let row = start_row + ixs.start; let row = start_row + block_layout.line_layout_ixs.start;
let offset = vec2f(0., row as f32 * layout.line_height - scroll_top); let offset = vec2f(0., row as f32 * layout.line_height - scroll_top);
let height = ixs.len() as f32 * layout.line_height; let height = block_layout.line_layout_ixs.len() as f32 * layout.line_height;
if let Some(border_left_color) = block_layout.style.border_left {
cx.scene.push_quad(Quad {
bounds: RectF::new(
content_origin + offset + vec2f(block_layout.left_edge, 0.),
vec2f(1., height),
),
background: Some(border_left_color),
border: Default::default(),
corner_radius: 0.,
})
}
cx.scene.push_quad(Quad { cx.scene.push_quad(Quad {
bounds: RectF::new( bounds: RectF::new(
text_bounds.origin() + offset, text_bounds.origin() + offset,
vec2f(text_bounds.width(), height), vec2f(text_bounds.width(), height),
), ),
background: block_style.background, background: block_layout.style.background,
border: block_style border: Default::default(),
.border
.map_or(Default::default(), |color| Border {
width: 1.,
color,
overlay: true,
top: true,
right: false,
bottom: true,
left: false,
}),
corner_radius: 0., corner_radius: 0.,
}); });
cx.scene.push_quad(Quad { cx.scene.push_quad(Quad {
@ -308,8 +312,9 @@ impl EditorElement {
gutter_bounds.origin() + offset, gutter_bounds.origin() + offset,
vec2f(gutter_bounds.width(), height), vec2f(gutter_bounds.width(), height),
), ),
background: block_style.gutter_background, background: block_layout.style.gutter_background,
border: block_style border: block_layout
.style
.gutter_border .gutter_border
.map_or(Default::default(), |color| Border { .map_or(Default::default(), |color| Border {
width: 1., width: 1.,
@ -484,17 +489,15 @@ impl EditorElement {
fn layout_rows( fn layout_rows(
&self, &self,
rows: Range<u32>, rows: Range<u32>,
line_layouts: &[text_layout::Line],
active_rows: &BTreeMap<u32, bool>, active_rows: &BTreeMap<u32, bool>,
snapshot: &Snapshot, snapshot: &Snapshot,
cx: &LayoutContext, cx: &LayoutContext,
) -> ( ) -> (Vec<Option<text_layout::Line>>, Vec<BlockLayout>) {
Vec<Option<text_layout::Line>>,
Vec<(Range<u32>, BlockStyle)>,
) {
let style = &self.settings.style; let style = &self.settings.style;
let include_line_numbers = snapshot.mode == EditorMode::Full; let include_line_numbers = snapshot.mode == EditorMode::Full;
let mut last_block_id = None; let mut last_block_id = None;
let mut blocks = Vec::<(Range<u32>, BlockStyle)>::new(); let mut blocks = Vec::<BlockLayout>::new();
let mut line_number_layouts = Vec::with_capacity(rows.len()); let mut line_number_layouts = Vec::with_capacity(rows.len());
let mut line_number = String::new(); let mut line_number = String::new();
for (ix, row) in snapshot for (ix, row) in snapshot
@ -528,17 +531,21 @@ impl EditorElement {
} }
last_block_id = None; last_block_id = None;
} }
DisplayRow::Block(block_id, style) => { DisplayRow::Block { id, style, column } => {
let ix = ix as u32; let ix = ix as u32;
if last_block_id == Some(block_id) { if last_block_id == Some(id) {
if let Some((row_range, _)) = blocks.last_mut() { if let Some(block_layout) = blocks.last_mut() {
row_range.end += 1; block_layout.line_layout_ixs.end += 1;
} }
} else if let Some(style) = style { } else if let Some(style) = style {
blocks.push((ix..ix + 1, style)); blocks.push(BlockLayout {
line_layout_ixs: ix..ix + 1,
left_edge: line_layouts[ix as usize].x_for_index(column as usize),
style,
});
} }
line_number_layouts.push(None); line_number_layouts.push(None);
last_block_id = Some(block_id); last_block_id = Some(id);
} }
DisplayRow::Wrap => { DisplayRow::Wrap => {
line_number_layouts.push(None); line_number_layouts.push(None);
@ -773,9 +780,6 @@ impl Element for EditorElement {
} }
}); });
let (line_number_layouts, block_layouts) =
self.layout_rows(start_row..end_row, &active_rows, &snapshot, cx);
let mut max_visible_line_width = 0.0; let mut max_visible_line_width = 0.0;
let line_layouts = self.layout_lines(start_row..end_row, &mut snapshot, cx); let line_layouts = self.layout_lines(start_row..end_row, &mut snapshot, cx);
for line in &line_layouts { for line in &line_layouts {
@ -784,6 +788,14 @@ impl Element for EditorElement {
} }
} }
let (line_number_layouts, block_layouts) = self.layout_rows(
start_row..end_row,
&line_layouts,
&active_rows,
&snapshot,
cx,
);
let mut layout = LayoutState { let mut layout = LayoutState {
size, size,
gutter_size, gutter_size,
@ -927,7 +939,7 @@ pub struct LayoutState {
highlighted_row: Option<u32>, highlighted_row: Option<u32>,
line_layouts: Vec<text_layout::Line>, line_layouts: Vec<text_layout::Line>,
line_number_layouts: Vec<Option<text_layout::Line>>, line_number_layouts: Vec<Option<text_layout::Line>>,
block_layouts: Vec<(Range<u32>, BlockStyle)>, block_layouts: Vec<BlockLayout>,
line_height: f32, line_height: f32,
em_width: f32, em_width: f32,
em_advance: f32, em_advance: f32,
@ -937,6 +949,12 @@ pub struct LayoutState {
max_visible_line_width: f32, max_visible_line_width: f32,
} }
struct BlockLayout {
line_layout_ixs: Range<u32>,
left_edge: f32,
style: BlockStyle,
}
impl LayoutState { impl LayoutState {
fn scroll_width(&self, layout_cache: &TextLayoutCache) -> f32 { fn scroll_width(&self, layout_cache: &TextLayoutCache) -> f32 {
let row = self.snapshot.longest_row(); let row = self.snapshot.longest_row();
@ -1189,7 +1207,7 @@ mod tests {
let snapshot = editor.snapshot(cx); let snapshot = editor.snapshot(cx);
let mut presenter = cx.build_presenter(window_id, 30.); let mut presenter = cx.build_presenter(window_id, 30.);
let mut layout_cx = presenter.build_layout_context(false, cx); let mut layout_cx = presenter.build_layout_context(false, cx);
element.layout_rows(0..6, &Default::default(), &snapshot, &mut layout_cx) element.layout_rows(0..6, &[], &Default::default(), &snapshot, &mut layout_cx)
}); });
assert_eq!(layouts.len(), 6); assert_eq!(layouts.len(), 6);
} }

View file

@ -276,7 +276,7 @@ pub struct InputEditorStyle {
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Eq)] #[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Eq)]
pub struct BlockStyle { pub struct BlockStyle {
pub background: Option<Color>, pub background: Option<Color>,
pub border: Option<Color>, pub border_left: Option<Color>,
pub gutter_background: Option<Color>, pub gutter_background: Option<Color>,
pub gutter_border: Option<Color>, pub gutter_border: Option<Color>,
} }

View file

@ -249,7 +249,7 @@ line_number_active = "$text.0.color"
selection = "$selection.host" selection = "$selection.host"
guest_selections = "$selection.guests" guest_selections = "$selection.guests"
error_color = "$status.bad" error_color = "$status.bad"
error_diagnostic = { text = { color = "$status.bad", italic = true } } error_diagnostic = { border_left = "$status.bad", text = { color = "$status.bad", italic = true } }
invalid_error_diagnostic = { text = { color = "$text.3.color", italic = true } } invalid_error_diagnostic = { text = { color = "$text.3.color", italic = true } }
warning_diagnostic = { text = { color = "$status.warn", italic = true } } warning_diagnostic = { text = { color = "$status.warn", italic = true } }
invalid_warning_diagnostic = { text = { color = "$text.3.color", italic = true } } invalid_warning_diagnostic = { text = { color = "$text.3.color", italic = true } }