From aefdde66a6e2f064ddd941a9852601b45db6c2f8 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 31 May 2022 15:44:35 +0200 Subject: [PATCH] Pass a `&mut BlockContext` when rendering blocks This wraps and derefs to `RenderContext`, so that we can easily use `MouseEventHandler`s in blocks. --- crates/diagnostics/src/diagnostics.rs | 86 +++++++++++----------- crates/editor/src/display_map/block_map.rs | 51 ++++++------- crates/editor/src/editor.rs | 4 +- crates/editor/src/element.rs | 24 ++++-- 4 files changed, 83 insertions(+), 82 deletions(-) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index b5361b4e5b0d7595bde196064c3e18bceca0500c..cd258b98f11fedb7689bd58170ca123ee55bae73 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -702,7 +702,7 @@ mod tests { use super::*; use editor::{ display_map::{BlockContext, TransformBlock}, - DisplayPoint, EditorSnapshot, + DisplayPoint, }; use gpui::TestAppContext; use language::{Diagnostic, DiagnosticEntry, DiagnosticSeverity, PointUtf16}; @@ -835,10 +835,8 @@ mod tests { view.next_notification(&cx).await; view.update(cx, |view, cx| { - let editor = view.editor.update(cx, |editor, cx| editor.snapshot(cx)); - assert_eq!( - editor_blocks(&editor, cx), + editor_blocks(&view.editor, cx), [ (0, "path header block".into()), (2, "diagnostic header".into()), @@ -848,7 +846,7 @@ mod tests { ] ); assert_eq!( - editor.text(), + view.editor.update(cx, |editor, cx| editor.display_text(cx)), concat!( // // main.rs @@ -923,10 +921,8 @@ mod tests { view.next_notification(&cx).await; view.update(cx, |view, cx| { - let editor = view.editor.update(cx, |editor, cx| editor.snapshot(cx)); - assert_eq!( - editor_blocks(&editor, cx), + editor_blocks(&view.editor, cx), [ (0, "path header block".into()), (2, "diagnostic header".into()), @@ -938,7 +934,7 @@ mod tests { ] ); assert_eq!( - editor.text(), + view.editor.update(cx, |editor, cx| editor.display_text(cx)), concat!( // // consts.rs @@ -1038,10 +1034,8 @@ mod tests { view.next_notification(&cx).await; view.update(cx, |view, cx| { - let editor = view.editor.update(cx, |editor, cx| editor.snapshot(cx)); - assert_eq!( - editor_blocks(&editor, cx), + editor_blocks(&view.editor, cx), [ (0, "path header block".into()), (2, "diagnostic header".into()), @@ -1055,7 +1049,7 @@ mod tests { ] ); assert_eq!( - editor.text(), + view.editor.update(cx, |editor, cx| editor.display_text(cx)), concat!( // // consts.rs @@ -1115,36 +1109,44 @@ mod tests { }); } - fn editor_blocks(editor: &EditorSnapshot, cx: &AppContext) -> Vec<(u32, String)> { - editor - .blocks_in_range(0..editor.max_point().row()) - .filter_map(|(row, block)| { - let name = match block { - TransformBlock::Custom(block) => block - .render(&BlockContext { - cx, - anchor_x: 0., - scroll_x: 0., - gutter_padding: 0., - gutter_width: 0., - line_height: 0., - em_width: 0., - }) - .name()? - .to_string(), - TransformBlock::ExcerptHeader { - starts_new_buffer, .. - } => { - if *starts_new_buffer { - "path header block".to_string() - } else { - "collapsed context".to_string() + fn editor_blocks( + editor: &ViewHandle, + cx: &mut MutableAppContext, + ) -> Vec<(u32, String)> { + let mut presenter = cx.build_presenter(editor.id(), 0.); + let mut cx = presenter.build_layout_context(Default::default(), false, cx); + cx.render(editor, |editor, cx| { + let snapshot = editor.snapshot(cx); + snapshot + .blocks_in_range(0..snapshot.max_point().row()) + .filter_map(|(row, block)| { + let name = match block { + TransformBlock::Custom(block) => block + .render(&mut BlockContext { + cx, + anchor_x: 0., + scroll_x: 0., + gutter_padding: 0., + gutter_width: 0., + line_height: 0., + em_width: 0., + }) + .name()? + .to_string(), + TransformBlock::ExcerptHeader { + starts_new_buffer, .. + } => { + if *starts_new_buffer { + "path header block".to_string() + } else { + "collapsed context".to_string() + } } - } - }; + }; - Some((row, name)) - }) - .collect() + Some((row, name)) + }) + .collect() + }) } } diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index c5c06048e58d6c3ce9f210d98a878bc2ae240163..bdfff4862c41d156cfad9c5bf8376e0e84a6a9e7 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -4,14 +4,14 @@ use super::{ }; use crate::{Anchor, ToPoint as _}; use collections::{Bound, HashMap, HashSet}; -use gpui::{AppContext, ElementBox}; +use gpui::{ElementBox, RenderContext}; use language::{BufferSnapshot, Chunk, Patch}; use parking_lot::Mutex; use std::{ cell::RefCell, cmp::{self, Ordering}, fmt::Debug, - ops::{Deref, Range}, + ops::{Deref, DerefMut, Range}, sync::{ atomic::{AtomicUsize, Ordering::SeqCst}, Arc, @@ -50,7 +50,7 @@ struct BlockRow(u32); #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] struct WrapRow(u32); -pub type RenderBlock = Arc ElementBox>; +pub type RenderBlock = Arc ElementBox>; pub struct Block { id: BlockId, @@ -67,12 +67,12 @@ where { pub position: P, pub height: u8, - pub render: Arc ElementBox>, + pub render: Arc ElementBox>, pub disposition: BlockDisposition, } -pub struct BlockContext<'a> { - pub cx: &'a AppContext, +pub struct BlockContext<'a, 'b> { + pub cx: &'b mut RenderContext<'a, crate::Editor>, pub anchor_x: f32, pub scroll_x: f32, pub gutter_width: f32, @@ -916,16 +916,22 @@ impl BlockDisposition { } } -impl<'a> Deref for BlockContext<'a> { - type Target = AppContext; +impl<'a, 'b> Deref for BlockContext<'a, 'b> { + type Target = RenderContext<'a, crate::Editor>; fn deref(&self) -> &Self::Target { - &self.cx + self.cx + } +} + +impl<'a, 'b> DerefMut for BlockContext<'a, 'b> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.cx } } impl Block { - pub fn render(&self, cx: &BlockContext) -> ElementBox { + pub fn render(&self, cx: &mut BlockContext) -> ElementBox { self.render.lock()(cx) } @@ -1008,7 +1014,7 @@ mod tests { let mut block_map = BlockMap::new(wraps_snapshot.clone(), 1, 1); let mut writer = block_map.write(wraps_snapshot.clone(), Default::default()); - writer.insert(vec![ + let block_ids = writer.insert(vec![ BlockProperties { position: buffer_snapshot.anchor_after(Point::new(1, 0)), height: 1, @@ -1036,22 +1042,7 @@ mod tests { .blocks_in_range(0..8) .map(|(start_row, block)| { let block = block.as_custom().unwrap(); - ( - start_row..start_row + block.height as u32, - block - .render(&BlockContext { - cx, - anchor_x: 0., - gutter_padding: 0., - scroll_x: 0., - gutter_width: 0., - line_height: 0., - em_width: 0., - }) - .name() - .unwrap() - .to_string(), - ) + (start_row..start_row + block.height as u32, block.id) }) .collect::>(); @@ -1059,9 +1050,9 @@ mod tests { assert_eq!( blocks, &[ - (1..2, "block 1".to_string()), - (2..4, "block 2".to_string()), - (7..10, "block 3".to_string()), + (1..2, block_ids[0]), + (2..4, block_ids[1]), + (7..10, block_ids[2]), ] ); diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index d82a5baece26eed60bff60eefc043f517d9dd8df..32773c9d28ac010c39e9b05a8183df96a202e3fb 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -4745,7 +4745,7 @@ impl Editor { height: 1, render: Arc::new({ let editor = rename_editor.clone(); - move |cx: &BlockContext| { + move |cx: &mut BlockContext| { ChildView::new(editor.clone()) .contained() .with_padding_left(cx.anchor_x) @@ -5866,7 +5866,7 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend highlighted_lines.push(highlight_diagnostic_message(line)); } - Arc::new(move |cx: &BlockContext| { + Arc::new(move |cx: &mut BlockContext| { let settings = cx.global::(); let theme = &settings.theme.editor; let style = diagnostic_style(diagnostic.severity, is_valid, theme); diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index d5a4f22eb563d6525c9c5594fb6c9af67de84ee8..39091ecad1f557190f3bdeceae5dd96333e75a97 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -755,6 +755,12 @@ impl EditorElement { line_layouts: &[text_layout::Line], cx: &mut LayoutContext, ) -> Vec<(u32, ElementBox)> { + let editor = if let Some(editor) = self.view.upgrade(cx) { + editor + } else { + return Default::default(); + }; + let scroll_x = snapshot.scroll_position.x(); snapshot .blocks_in_range(rows.clone()) @@ -774,14 +780,16 @@ impl EditorElement { .x_for_index(align_to.column() as usize) }; - block.render(&BlockContext { - cx, - anchor_x, - gutter_padding, - line_height, - scroll_x, - gutter_width, - em_width, + cx.render(&editor, |_, cx| { + block.render(&mut BlockContext { + cx, + anchor_x, + gutter_padding, + line_height, + scroll_x, + gutter_width, + em_width, + }) }) } TransformBlock::ExcerptHeader {