mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-05 18:25:57 +00:00
Merge pull request #1167 from zed-industries/block-scroll-width
Introduce a new `BlockStyle` field for blocks
This commit is contained in:
commit
799b32c8a9
5 changed files with 239 additions and 170 deletions
|
@ -4,7 +4,7 @@ use anyhow::Result;
|
|||
use collections::{BTreeMap, HashSet};
|
||||
use editor::{
|
||||
diagnostic_block_renderer,
|
||||
display_map::{BlockDisposition, BlockId, BlockProperties, RenderBlock},
|
||||
display_map::{BlockDisposition, BlockId, BlockProperties, BlockStyle, RenderBlock},
|
||||
highlight_diagnostic_message, Autoscroll, Editor, ExcerptId, ExcerptRange, MultiBuffer,
|
||||
ToOffset,
|
||||
};
|
||||
|
@ -348,6 +348,7 @@ impl ProjectDiagnosticsEditor {
|
|||
blocks_to_add.push(BlockProperties {
|
||||
position: header_position,
|
||||
height: 2,
|
||||
style: BlockStyle::Sticky,
|
||||
render: diagnostic_header_renderer(primary),
|
||||
disposition: BlockDisposition::Above,
|
||||
});
|
||||
|
@ -366,6 +367,7 @@ impl ProjectDiagnosticsEditor {
|
|||
blocks_to_add.push(BlockProperties {
|
||||
position: (excerpt_id.clone(), entry.range.start.clone()),
|
||||
height: diagnostic.message.matches('\n').count() as u8 + 1,
|
||||
style: BlockStyle::Fixed,
|
||||
render: diagnostic_block_renderer(diagnostic, true),
|
||||
disposition: BlockDisposition::Below,
|
||||
});
|
||||
|
@ -402,6 +404,7 @@ impl ProjectDiagnosticsEditor {
|
|||
BlockProperties {
|
||||
position: excerpts_snapshot.anchor_in_excerpt(excerpt_id, text_anchor),
|
||||
height: block.height,
|
||||
style: block.style,
|
||||
render: block.render,
|
||||
disposition: block.disposition,
|
||||
}
|
||||
|
@ -621,7 +624,6 @@ fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock {
|
|||
.with_color(theme.warning_diagnostic.message.text.color)
|
||||
};
|
||||
|
||||
let x_padding = cx.gutter_padding + cx.scroll_x * cx.em_width;
|
||||
Flex::row()
|
||||
.with_child(
|
||||
icon.constrained()
|
||||
|
@ -651,8 +653,8 @@ fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock {
|
|||
}))
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
.with_padding_left(x_padding)
|
||||
.with_padding_right(x_padding)
|
||||
.with_padding_left(cx.gutter_padding)
|
||||
.with_padding_right(cx.gutter_padding)
|
||||
.expanded()
|
||||
.named("diagnostic header")
|
||||
})
|
||||
|
|
|
@ -20,7 +20,7 @@ use wrap_map::WrapMap;
|
|||
|
||||
pub use block_map::{
|
||||
BlockBufferRows as DisplayBufferRows, BlockChunks as DisplayChunks, BlockContext,
|
||||
BlockDisposition, BlockId, BlockProperties, RenderBlock, TransformBlock,
|
||||
BlockDisposition, BlockId, BlockProperties, BlockStyle, RenderBlock, TransformBlock,
|
||||
};
|
||||
|
||||
pub trait ToDisplayPoint {
|
||||
|
@ -650,6 +650,7 @@ pub mod tests {
|
|||
height
|
||||
);
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
position,
|
||||
height,
|
||||
disposition,
|
||||
|
|
|
@ -56,6 +56,7 @@ pub struct Block {
|
|||
id: BlockId,
|
||||
position: Anchor,
|
||||
height: u8,
|
||||
style: BlockStyle,
|
||||
render: Mutex<RenderBlock>,
|
||||
disposition: BlockDisposition,
|
||||
}
|
||||
|
@ -67,10 +68,18 @@ where
|
|||
{
|
||||
pub position: P,
|
||||
pub height: u8,
|
||||
pub style: BlockStyle,
|
||||
pub render: Arc<dyn Fn(&mut BlockContext) -> ElementBox>,
|
||||
pub disposition: BlockDisposition,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum BlockStyle {
|
||||
Fixed,
|
||||
Flex,
|
||||
Sticky,
|
||||
}
|
||||
|
||||
pub struct BlockContext<'a, 'b> {
|
||||
pub cx: &'b mut RenderContext<'a, crate::Editor>,
|
||||
pub anchor_x: f32,
|
||||
|
@ -513,6 +522,7 @@ impl<'a> BlockMapWriter<'a> {
|
|||
height: block.height,
|
||||
render: Mutex::new(block.render),
|
||||
disposition: block.disposition,
|
||||
style: block.style,
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -940,6 +950,10 @@ impl Block {
|
|||
pub fn position(&self) -> &Anchor {
|
||||
&self.position
|
||||
}
|
||||
|
||||
pub fn style(&self) -> BlockStyle {
|
||||
self.style
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Block {
|
||||
|
@ -1018,18 +1032,21 @@ mod tests {
|
|||
let mut writer = block_map.write(wraps_snapshot.clone(), Default::default());
|
||||
let block_ids = writer.insert(vec![
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
position: buffer_snapshot.anchor_after(Point::new(1, 0)),
|
||||
height: 1,
|
||||
disposition: BlockDisposition::Above,
|
||||
render: Arc::new(|_| Empty::new().named("block 1")),
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
position: buffer_snapshot.anchor_after(Point::new(1, 2)),
|
||||
height: 2,
|
||||
disposition: BlockDisposition::Above,
|
||||
render: Arc::new(|_| Empty::new().named("block 2")),
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
position: buffer_snapshot.anchor_after(Point::new(3, 3)),
|
||||
height: 3,
|
||||
disposition: BlockDisposition::Below,
|
||||
|
@ -1183,12 +1200,14 @@ mod tests {
|
|||
let mut writer = block_map.write(wraps_snapshot.clone(), Default::default());
|
||||
writer.insert(vec![
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
position: buffer_snapshot.anchor_after(Point::new(1, 12)),
|
||||
disposition: BlockDisposition::Above,
|
||||
render: Arc::new(|_| Empty::new().named("block 1")),
|
||||
height: 1,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
position: buffer_snapshot.anchor_after(Point::new(1, 1)),
|
||||
disposition: BlockDisposition::Below,
|
||||
render: Arc::new(|_| Empty::new().named("block 2")),
|
||||
|
@ -1286,6 +1305,7 @@ mod tests {
|
|||
height
|
||||
);
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
position,
|
||||
height,
|
||||
disposition,
|
||||
|
|
|
@ -4801,6 +4801,7 @@ impl Editor {
|
|||
cx.focus(&rename_editor);
|
||||
let block_id = this.insert_blocks(
|
||||
[BlockProperties {
|
||||
style: BlockStyle::Flex,
|
||||
position: range.start.clone(),
|
||||
height: 1,
|
||||
render: Arc::new({
|
||||
|
@ -4985,6 +4986,7 @@ impl Editor {
|
|||
let diagnostic = entry.diagnostic.clone();
|
||||
let message_height = diagnostic.message.lines().count() as u8;
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
position: buffer.anchor_after(entry.range.start),
|
||||
height: message_height,
|
||||
render: diagnostic_block_renderer(diagnostic, true),
|
||||
|
@ -7932,6 +7934,7 @@ mod tests {
|
|||
editor.update(cx, |editor, cx| {
|
||||
editor.insert_blocks(
|
||||
[BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
position: snapshot.anchor_after(Point::new(2, 0)),
|
||||
disposition: BlockDisposition::Below,
|
||||
height: 1,
|
||||
|
|
|
@ -3,9 +3,9 @@ use super::{
|
|||
Anchor, DisplayPoint, Editor, EditorMode, EditorSnapshot, Input, Scroll, Select, SelectPhase,
|
||||
SoftWrap, ToPoint, MAX_LINE_LEN,
|
||||
};
|
||||
use crate::hover_popover::HoverAt;
|
||||
use crate::{
|
||||
display_map::{DisplaySnapshot, TransformBlock},
|
||||
display_map::{BlockStyle, DisplaySnapshot, TransformBlock},
|
||||
hover_popover::HoverAt,
|
||||
EditorStyle,
|
||||
};
|
||||
use clock::ReplicaId;
|
||||
|
@ -617,10 +617,13 @@ impl EditorElement {
|
|||
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 = bounds.origin()
|
||||
+ vec2f(-scroll_left, *row as f32 * layout.line_height - scroll_top);
|
||||
element.paint(origin, visible_bounds, cx);
|
||||
for block in &mut layout.blocks {
|
||||
let mut origin =
|
||||
bounds.origin() + vec2f(0., block.row as f32 * layout.line_height - scroll_top);
|
||||
if !matches!(block.style, BlockStyle::Sticky) {
|
||||
origin += vec2f(-scroll_left, 0.);
|
||||
}
|
||||
block.element.paint(origin, visible_bounds, cx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -788,7 +791,8 @@ impl EditorElement {
|
|||
&mut self,
|
||||
rows: Range<u32>,
|
||||
snapshot: &EditorSnapshot,
|
||||
width: f32,
|
||||
editor_width: f32,
|
||||
scroll_width: f32,
|
||||
gutter_padding: f32,
|
||||
gutter_width: f32,
|
||||
em_width: f32,
|
||||
|
@ -797,7 +801,7 @@ impl EditorElement {
|
|||
style: &EditorStyle,
|
||||
line_layouts: &[text_layout::Line],
|
||||
cx: &mut LayoutContext,
|
||||
) -> Vec<(u32, ElementBox)> {
|
||||
) -> (f32, Vec<BlockLayout>) {
|
||||
let editor = if let Some(editor) = self.view.upgrade(cx) {
|
||||
editor
|
||||
} else {
|
||||
|
@ -806,158 +810,189 @@ impl EditorElement {
|
|||
|
||||
let tooltip_style = cx.global::<Settings>().theme.tooltip.clone();
|
||||
let scroll_x = snapshot.scroll_position.x();
|
||||
snapshot
|
||||
let (fixed_blocks, non_fixed_blocks) = snapshot
|
||||
.blocks_in_range(rows.clone())
|
||||
.map(|(block_row, block)| {
|
||||
let mut element = match block {
|
||||
TransformBlock::Custom(block) => {
|
||||
let align_to = block
|
||||
.position()
|
||||
.to_point(&snapshot.buffer_snapshot)
|
||||
.to_display_point(snapshot);
|
||||
let anchor_x = text_x
|
||||
+ if rows.contains(&align_to.row()) {
|
||||
line_layouts[(align_to.row() - rows.start) as usize]
|
||||
.x_for_index(align_to.column() as usize)
|
||||
} else {
|
||||
layout_line(align_to.row(), snapshot, style, cx.text_layout_cache)
|
||||
.x_for_index(align_to.column() as usize)
|
||||
};
|
||||
.partition::<Vec<_>, _>(|(_, block)| match block {
|
||||
TransformBlock::ExcerptHeader { .. } => false,
|
||||
TransformBlock::Custom(block) => block.style() == BlockStyle::Fixed,
|
||||
});
|
||||
let mut render_block = |block: &TransformBlock, width: f32| {
|
||||
let mut element = match block {
|
||||
TransformBlock::Custom(block) => {
|
||||
let align_to = block
|
||||
.position()
|
||||
.to_point(&snapshot.buffer_snapshot)
|
||||
.to_display_point(snapshot);
|
||||
let anchor_x = text_x
|
||||
+ if rows.contains(&align_to.row()) {
|
||||
line_layouts[(align_to.row() - rows.start) as usize]
|
||||
.x_for_index(align_to.column() as usize)
|
||||
} else {
|
||||
layout_line(align_to.row(), snapshot, style, cx.text_layout_cache)
|
||||
.x_for_index(align_to.column() as usize)
|
||||
};
|
||||
|
||||
cx.render(&editor, |_, cx| {
|
||||
block.render(&mut 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 {
|
||||
key,
|
||||
buffer,
|
||||
range,
|
||||
starts_new_buffer,
|
||||
..
|
||||
} => {
|
||||
let jump_icon = project::File::from_dyn(buffer.file()).map(|file| {
|
||||
let jump_position = range
|
||||
.primary
|
||||
.as_ref()
|
||||
.map_or(range.context.start, |primary| primary.start);
|
||||
let jump_action = crate::Jump {
|
||||
path: ProjectPath {
|
||||
worktree_id: file.worktree_id(cx),
|
||||
path: file.path.clone(),
|
||||
},
|
||||
position: language::ToPoint::to_point(&jump_position, buffer),
|
||||
anchor: jump_position,
|
||||
};
|
||||
})
|
||||
}
|
||||
TransformBlock::ExcerptHeader {
|
||||
key,
|
||||
buffer,
|
||||
range,
|
||||
starts_new_buffer,
|
||||
..
|
||||
} => {
|
||||
let jump_icon = project::File::from_dyn(buffer.file()).map(|file| {
|
||||
let jump_position = range
|
||||
.primary
|
||||
.as_ref()
|
||||
.map_or(range.context.start, |primary| primary.start);
|
||||
let jump_action = crate::Jump {
|
||||
path: ProjectPath {
|
||||
worktree_id: file.worktree_id(cx),
|
||||
path: file.path.clone(),
|
||||
},
|
||||
position: language::ToPoint::to_point(&jump_position, buffer),
|
||||
anchor: jump_position,
|
||||
};
|
||||
|
||||
enum JumpIcon {}
|
||||
cx.render(&editor, |_, cx| {
|
||||
MouseEventHandler::new::<JumpIcon, _, _>(*key, cx, |state, _| {
|
||||
let style = style.jump_icon.style_for(state, false);
|
||||
Svg::new("icons/jump.svg")
|
||||
.with_color(style.color)
|
||||
.constrained()
|
||||
.with_width(style.icon_width)
|
||||
.aligned()
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
.constrained()
|
||||
.with_width(style.button_width)
|
||||
.with_height(style.button_width)
|
||||
.boxed()
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_click({
|
||||
move |_, _, cx| cx.dispatch_action(jump_action.clone())
|
||||
})
|
||||
.with_tooltip(
|
||||
*key,
|
||||
"Jump to Buffer".to_string(),
|
||||
Some(Box::new(crate::OpenExcerpts)),
|
||||
tooltip_style.clone(),
|
||||
cx,
|
||||
)
|
||||
.aligned()
|
||||
.flex_float()
|
||||
.boxed()
|
||||
})
|
||||
});
|
||||
|
||||
let padding = gutter_padding + scroll_x * em_width;
|
||||
if *starts_new_buffer {
|
||||
let style = &self.style.diagnostic_path_header;
|
||||
let font_size =
|
||||
(style.text_scale_factor * self.style.text.font_size).round();
|
||||
|
||||
let mut filename = None;
|
||||
let mut parent_path = None;
|
||||
if let Some(file) = buffer.file() {
|
||||
let path = file.path();
|
||||
filename =
|
||||
path.file_name().map(|f| f.to_string_lossy().to_string());
|
||||
parent_path =
|
||||
path.parent().map(|p| p.to_string_lossy().to_string() + "/");
|
||||
}
|
||||
|
||||
Flex::row()
|
||||
.with_child(
|
||||
Label::new(
|
||||
filename.unwrap_or_else(|| "untitled".to_string()),
|
||||
style.filename.text.clone().with_font_size(font_size),
|
||||
)
|
||||
.contained()
|
||||
.with_style(style.filename.container)
|
||||
enum JumpIcon {}
|
||||
cx.render(&editor, |_, cx| {
|
||||
MouseEventHandler::new::<JumpIcon, _, _>(*key, cx, |state, _| {
|
||||
let style = style.jump_icon.style_for(state, false);
|
||||
Svg::new("icons/jump.svg")
|
||||
.with_color(style.color)
|
||||
.constrained()
|
||||
.with_width(style.icon_width)
|
||||
.aligned()
|
||||
.boxed(),
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
.constrained()
|
||||
.with_width(style.button_width)
|
||||
.with_height(style.button_width)
|
||||
.boxed()
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_click(move |_, _, cx| cx.dispatch_action(jump_action.clone()))
|
||||
.with_tooltip(
|
||||
*key,
|
||||
"Jump to Buffer".to_string(),
|
||||
Some(Box::new(crate::OpenExcerpts)),
|
||||
tooltip_style.clone(),
|
||||
cx,
|
||||
)
|
||||
.aligned()
|
||||
.flex_float()
|
||||
.boxed()
|
||||
})
|
||||
});
|
||||
|
||||
if *starts_new_buffer {
|
||||
let style = &self.style.diagnostic_path_header;
|
||||
let font_size =
|
||||
(style.text_scale_factor * self.style.text.font_size).round();
|
||||
|
||||
let mut filename = None;
|
||||
let mut parent_path = None;
|
||||
if let Some(file) = buffer.file() {
|
||||
let path = file.path();
|
||||
filename = path.file_name().map(|f| f.to_string_lossy().to_string());
|
||||
parent_path =
|
||||
path.parent().map(|p| p.to_string_lossy().to_string() + "/");
|
||||
}
|
||||
|
||||
Flex::row()
|
||||
.with_child(
|
||||
Label::new(
|
||||
filename.unwrap_or_else(|| "untitled".to_string()),
|
||||
style.filename.text.clone().with_font_size(font_size),
|
||||
)
|
||||
.with_children(parent_path.map(|path| {
|
||||
Label::new(
|
||||
path,
|
||||
style.path.text.clone().with_font_size(font_size),
|
||||
)
|
||||
.contained()
|
||||
.with_style(style.filename.container)
|
||||
.aligned()
|
||||
.boxed(),
|
||||
)
|
||||
.with_children(parent_path.map(|path| {
|
||||
Label::new(path, style.path.text.clone().with_font_size(font_size))
|
||||
.contained()
|
||||
.with_style(style.path.container)
|
||||
.aligned()
|
||||
.boxed()
|
||||
}))
|
||||
.with_children(jump_icon)
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
.with_padding_left(padding)
|
||||
.with_padding_right(padding)
|
||||
.expanded()
|
||||
.named("path header block")
|
||||
} else {
|
||||
let text_style = self.style.text.clone();
|
||||
Flex::row()
|
||||
.with_child(Label::new("…".to_string(), text_style).boxed())
|
||||
.with_children(jump_icon)
|
||||
.contained()
|
||||
.with_padding_left(padding)
|
||||
.with_padding_right(padding)
|
||||
.expanded()
|
||||
.named("collapsed context")
|
||||
}
|
||||
}))
|
||||
.with_children(jump_icon)
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
.with_padding_left(gutter_padding)
|
||||
.with_padding_right(gutter_padding)
|
||||
.expanded()
|
||||
.named("path header block")
|
||||
} else {
|
||||
let text_style = self.style.text.clone();
|
||||
Flex::row()
|
||||
.with_child(Label::new("…".to_string(), text_style).boxed())
|
||||
.with_children(jump_icon)
|
||||
.contained()
|
||||
.with_padding_left(gutter_padding)
|
||||
.with_padding_right(gutter_padding)
|
||||
.expanded()
|
||||
.named("collapsed context")
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
element.layout(
|
||||
SizeConstraint {
|
||||
min: Vector2F::zero(),
|
||||
max: vec2f(width, block.height() as f32 * line_height),
|
||||
},
|
||||
cx,
|
||||
);
|
||||
(block_row, element)
|
||||
})
|
||||
.collect()
|
||||
element.layout(
|
||||
SizeConstraint {
|
||||
min: Vector2F::zero(),
|
||||
max: vec2f(width, block.height() as f32 * line_height),
|
||||
},
|
||||
cx,
|
||||
);
|
||||
element
|
||||
};
|
||||
|
||||
let mut fixed_block_max_width = 0f32;
|
||||
let mut blocks = Vec::new();
|
||||
for (row, block) in fixed_blocks {
|
||||
let element = render_block(block, f32::INFINITY);
|
||||
fixed_block_max_width = fixed_block_max_width.max(element.size().x() + em_width);
|
||||
blocks.push(BlockLayout {
|
||||
row,
|
||||
element,
|
||||
style: BlockStyle::Fixed,
|
||||
});
|
||||
}
|
||||
for (row, block) in non_fixed_blocks {
|
||||
let style = match block {
|
||||
TransformBlock::Custom(block) => block.style(),
|
||||
TransformBlock::ExcerptHeader { .. } => BlockStyle::Sticky,
|
||||
};
|
||||
let width = match style {
|
||||
BlockStyle::Sticky => editor_width,
|
||||
BlockStyle::Flex => editor_width
|
||||
.max(fixed_block_max_width)
|
||||
.max(gutter_width + scroll_width),
|
||||
BlockStyle::Fixed => unreachable!(),
|
||||
};
|
||||
let element = render_block(block, width);
|
||||
blocks.push(BlockLayout {
|
||||
row,
|
||||
element,
|
||||
style,
|
||||
});
|
||||
}
|
||||
(
|
||||
scroll_width.max(fixed_block_max_width - gutter_width),
|
||||
blocks,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1148,6 +1183,21 @@ impl Element for EditorElement {
|
|||
.width();
|
||||
let scroll_width = longest_line_width.max(max_visible_line_width) + overscroll.x();
|
||||
let em_width = style.text.em_width(cx.font_cache);
|
||||
let (scroll_width, blocks) = self.layout_blocks(
|
||||
start_row..end_row,
|
||||
&snapshot,
|
||||
size.x(),
|
||||
scroll_width,
|
||||
gutter_padding,
|
||||
gutter_width,
|
||||
em_width,
|
||||
gutter_width + gutter_margin,
|
||||
line_height,
|
||||
&style,
|
||||
&line_layouts,
|
||||
cx,
|
||||
);
|
||||
|
||||
let max_row = snapshot.max_point().row();
|
||||
let scroll_max = vec2f(
|
||||
((scroll_width - text_size.x()) / em_width).max(0.0),
|
||||
|
@ -1246,20 +1296,6 @@ impl Element for EditorElement {
|
|||
);
|
||||
}
|
||||
|
||||
let blocks = self.layout_blocks(
|
||||
start_row..end_row,
|
||||
&snapshot,
|
||||
size.x().max(scroll_width + gutter_width),
|
||||
gutter_padding,
|
||||
gutter_width,
|
||||
em_width,
|
||||
gutter_width + gutter_margin,
|
||||
line_height,
|
||||
&style,
|
||||
&line_layouts,
|
||||
cx,
|
||||
);
|
||||
|
||||
(
|
||||
size,
|
||||
LayoutState {
|
||||
|
@ -1353,8 +1389,8 @@ impl Element for EditorElement {
|
|||
}
|
||||
}
|
||||
|
||||
for (_, block) in &mut layout.blocks {
|
||||
if block.dispatch_event(event, cx) {
|
||||
for block in &mut layout.blocks {
|
||||
if block.element.dispatch_event(event, cx) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1440,7 +1476,7 @@ pub struct LayoutState {
|
|||
highlighted_rows: Option<Range<u32>>,
|
||||
line_layouts: Vec<text_layout::Line>,
|
||||
line_number_layouts: Vec<Option<text_layout::Line>>,
|
||||
blocks: Vec<(u32, ElementBox)>,
|
||||
blocks: Vec<BlockLayout>,
|
||||
line_height: f32,
|
||||
em_width: f32,
|
||||
em_advance: f32,
|
||||
|
@ -1451,6 +1487,12 @@ pub struct LayoutState {
|
|||
hover: Option<(DisplayPoint, ElementBox)>,
|
||||
}
|
||||
|
||||
struct BlockLayout {
|
||||
row: u32,
|
||||
element: ElementBox,
|
||||
style: BlockStyle,
|
||||
}
|
||||
|
||||
fn layout_line(
|
||||
row: u32,
|
||||
snapshot: &EditorSnapshot,
|
||||
|
@ -1763,6 +1805,7 @@ mod tests {
|
|||
editor.set_placeholder_text("hello", cx);
|
||||
editor.insert_blocks(
|
||||
[BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
disposition: BlockDisposition::Above,
|
||||
height: 3,
|
||||
position: Anchor::min(),
|
||||
|
|
Loading…
Reference in a new issue