Pass a &mut BlockContext when rendering blocks

This wraps and derefs to `RenderContext<Editor>`, so that we can
easily use `MouseEventHandler`s in blocks.
This commit is contained in:
Antonio Scandurra 2022-05-31 15:44:35 +02:00
parent 9fa03b2f28
commit aefdde66a6
4 changed files with 83 additions and 82 deletions

View File

@ -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<Editor>,
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()
})
}
}

View File

@ -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<dyn Fn(&BlockContext) -> ElementBox>;
pub type RenderBlock = Arc<dyn Fn(&mut BlockContext) -> ElementBox>;
pub struct Block {
id: BlockId,
@ -67,12 +67,12 @@ where
{
pub position: P,
pub height: u8,
pub render: Arc<dyn Fn(&BlockContext) -> ElementBox>,
pub render: Arc<dyn Fn(&mut BlockContext) -> 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::<Vec<_>>();
@ -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]),
]
);

View File

@ -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::<Settings>();
let theme = &settings.theme.editor;
let style = diagnostic_style(diagnostic.severity, is_valid, theme);

View File

@ -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 {