Introduce "Near" block type (#28032)
A "Near" block acts similarly to a "Below" block, but can (if it's height is <= one line height) be shown on the end of the preceding line instead of adding an entire blank line to the editor. You can test it out by pasting this into `go_to_diagnostic_impl` and then press `F8` ``` let buffer = self.buffer.read(cx).snapshot(cx); let selection = self.selections.newest_anchor(); self.display_map.update(cx, |display_map, cx| { display_map.insert_blocks( [BlockProperties { placement: BlockPlacement::Near(selection.start), height: Some(1), style: BlockStyle::Flex, render: Arc::new(|_| { div() .w(px(100.)) .h(px(16.)) .bg(gpui::hsla(0., 0., 1., 0.5)) .into_any_element() }), priority: 0, }], cx, ) }); return; ``` Release Notes: - N/A --------- Co-authored-by: Antonio Scandurra <me@as-cii.com>
This commit is contained in:
parent
10821aae2c
commit
d0e82b0538
12 changed files with 246 additions and 191 deletions
|
@ -621,14 +621,14 @@ impl InlineAssistant {
|
|||
BlockProperties {
|
||||
style: BlockStyle::Sticky,
|
||||
placement: BlockPlacement::Above(range.start),
|
||||
height: prompt_editor_height,
|
||||
height: Some(prompt_editor_height),
|
||||
render: build_assist_editor_renderer(prompt_editor),
|
||||
priority: 0,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Sticky,
|
||||
placement: BlockPlacement::Below(range.end),
|
||||
height: 0,
|
||||
height: None,
|
||||
render: Arc::new(|cx| {
|
||||
v_flex()
|
||||
.h_full()
|
||||
|
@ -1392,7 +1392,7 @@ impl InlineAssistant {
|
|||
deleted_lines_editor.update(cx, |editor, cx| editor.max_point(cx).row().0 + 1);
|
||||
new_blocks.push(BlockProperties {
|
||||
placement: BlockPlacement::Above(new_row),
|
||||
height,
|
||||
height: Some(height),
|
||||
style: BlockStyle::Flex,
|
||||
render: Arc::new(move |cx| {
|
||||
div()
|
||||
|
|
|
@ -527,14 +527,14 @@ impl InlineAssistant {
|
|||
BlockProperties {
|
||||
style: BlockStyle::Sticky,
|
||||
placement: BlockPlacement::Above(range.start),
|
||||
height: prompt_editor_height,
|
||||
height: Some(prompt_editor_height),
|
||||
render: build_assist_editor_renderer(prompt_editor),
|
||||
priority: 0,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Sticky,
|
||||
placement: BlockPlacement::Below(range.end),
|
||||
height: 0,
|
||||
height: None,
|
||||
render: Arc::new(|cx| {
|
||||
v_flex()
|
||||
.h_full()
|
||||
|
@ -1301,7 +1301,7 @@ impl InlineAssistant {
|
|||
deleted_lines_editor.update(cx, |editor, cx| editor.max_point(cx).row().0 + 1);
|
||||
new_blocks.push(BlockProperties {
|
||||
placement: BlockPlacement::Above(new_row),
|
||||
height,
|
||||
height: Some(height),
|
||||
style: BlockStyle::Flex,
|
||||
render: Arc::new(move |cx| {
|
||||
div()
|
||||
|
|
|
@ -1562,7 +1562,7 @@ impl ContextEditor {
|
|||
})
|
||||
};
|
||||
let create_block_properties = |message: &Message| BlockProperties {
|
||||
height: 2,
|
||||
height: Some(2),
|
||||
style: BlockStyle::Sticky,
|
||||
placement: BlockPlacement::Above(
|
||||
buffer
|
||||
|
@ -2111,7 +2111,7 @@ impl ContextEditor {
|
|||
let image = render_image.clone();
|
||||
anchor.is_valid(&buffer).then(|| BlockProperties {
|
||||
placement: BlockPlacement::Above(anchor),
|
||||
height: MAX_HEIGHT_IN_LINES,
|
||||
height: Some(MAX_HEIGHT_IN_LINES),
|
||||
style: BlockStyle::Sticky,
|
||||
render: Arc::new(move |cx| {
|
||||
let image_size = size_for_image(
|
||||
|
|
|
@ -535,7 +535,7 @@ impl ProjectDiagnosticsEditor {
|
|||
group_state.block_count += 1;
|
||||
blocks_to_add.push(BlockProperties {
|
||||
placement: BlockPlacement::Above(header_position),
|
||||
height: 2,
|
||||
height: Some(2),
|
||||
style: BlockStyle::Sticky,
|
||||
render: diagnostic_header_renderer(primary),
|
||||
priority: 0,
|
||||
|
@ -557,7 +557,9 @@ impl ProjectDiagnosticsEditor {
|
|||
excerpt_id,
|
||||
entry.range.start,
|
||||
)),
|
||||
height: diagnostic.message.matches('\n').count() as u32 + 1,
|
||||
height: Some(
|
||||
diagnostic.message.matches('\n').count() as u32 + 1,
|
||||
),
|
||||
style: BlockStyle::Fixed,
|
||||
render: diagnostic_block_renderer(diagnostic, None, true),
|
||||
priority: 0,
|
||||
|
@ -613,9 +615,9 @@ impl ProjectDiagnosticsEditor {
|
|||
excerpts_snapshot.anchor_in_excerpt(excerpt_id, text_anchor)?,
|
||||
)
|
||||
}
|
||||
BlockPlacement::Replace(_) => {
|
||||
BlockPlacement::Replace(_) | BlockPlacement::Near(_) => {
|
||||
unreachable!(
|
||||
"no Replace block should have been pushed to blocks_to_add"
|
||||
"no Near/Replace block should have been pushed to blocks_to_add"
|
||||
)
|
||||
}
|
||||
};
|
||||
|
|
|
@ -255,7 +255,7 @@ impl DisplayMap {
|
|||
BlockProperties {
|
||||
placement: BlockPlacement::Replace(start..=end),
|
||||
render,
|
||||
height,
|
||||
height: Some(height),
|
||||
style,
|
||||
priority,
|
||||
}
|
||||
|
@ -1591,7 +1591,7 @@ pub mod tests {
|
|||
BlockProperties {
|
||||
placement,
|
||||
style: BlockStyle::Fixed,
|
||||
height,
|
||||
height: Some(height),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority,
|
||||
}
|
||||
|
@ -1953,7 +1953,7 @@ pub mod tests {
|
|||
placement: BlockPlacement::Above(
|
||||
buffer_snapshot.anchor_before(Point::new(0, 0)),
|
||||
),
|
||||
height: 2,
|
||||
height: Some(2),
|
||||
style: BlockStyle::Sticky,
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
|
@ -2148,7 +2148,7 @@ pub mod tests {
|
|||
placement: BlockPlacement::Below(
|
||||
buffer_snapshot.anchor_before(Point::new(1, 0)),
|
||||
),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
style: BlockStyle::Sticky,
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
|
@ -2157,7 +2157,7 @@ pub mod tests {
|
|||
placement: BlockPlacement::Below(
|
||||
buffer_snapshot.anchor_before(Point::new(2, 0)),
|
||||
),
|
||||
height: 0,
|
||||
height: None,
|
||||
style: BlockStyle::Sticky,
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
|
@ -2262,7 +2262,7 @@ pub mod tests {
|
|||
placement: BlockPlacement::Below(
|
||||
buffer_snapshot.anchor_before(Point::new(1, 0)),
|
||||
),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
style: BlockStyle::Sticky,
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
|
@ -2336,7 +2336,7 @@ pub mod tests {
|
|||
buffer_snapshot.anchor_before(Point::new(1, 2))
|
||||
..=buffer_snapshot.anchor_after(Point::new(2, 3)),
|
||||
),
|
||||
height: 4,
|
||||
height: Some(4),
|
||||
style: BlockStyle::Fixed,
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
|
|
|
@ -84,6 +84,7 @@ pub type RenderBlock = Arc<dyn Send + Sync + Fn(&mut BlockContext) -> AnyElement
|
|||
pub enum BlockPlacement<T> {
|
||||
Above(T),
|
||||
Below(T),
|
||||
Near(T),
|
||||
Replace(RangeInclusive<T>),
|
||||
}
|
||||
|
||||
|
@ -92,6 +93,7 @@ impl<T> BlockPlacement<T> {
|
|||
match self {
|
||||
BlockPlacement::Above(position) => position,
|
||||
BlockPlacement::Below(position) => position,
|
||||
BlockPlacement::Near(position) => position,
|
||||
BlockPlacement::Replace(range) => range.start(),
|
||||
}
|
||||
}
|
||||
|
@ -100,6 +102,7 @@ impl<T> BlockPlacement<T> {
|
|||
match self {
|
||||
BlockPlacement::Above(position) => position,
|
||||
BlockPlacement::Below(position) => position,
|
||||
BlockPlacement::Near(position) => position,
|
||||
BlockPlacement::Replace(range) => range.end(),
|
||||
}
|
||||
}
|
||||
|
@ -108,6 +111,7 @@ impl<T> BlockPlacement<T> {
|
|||
match self {
|
||||
BlockPlacement::Above(position) => BlockPlacement::Above(position),
|
||||
BlockPlacement::Below(position) => BlockPlacement::Below(position),
|
||||
BlockPlacement::Near(position) => BlockPlacement::Near(position),
|
||||
BlockPlacement::Replace(range) => BlockPlacement::Replace(range.start()..=range.end()),
|
||||
}
|
||||
}
|
||||
|
@ -116,44 +120,30 @@ impl<T> BlockPlacement<T> {
|
|||
match self {
|
||||
BlockPlacement::Above(position) => BlockPlacement::Above(f(position)),
|
||||
BlockPlacement::Below(position) => BlockPlacement::Below(f(position)),
|
||||
BlockPlacement::Near(position) => BlockPlacement::Near(f(position)),
|
||||
BlockPlacement::Replace(range) => {
|
||||
let (start, end) = range.into_inner();
|
||||
BlockPlacement::Replace(f(start)..=f(end))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn sort_order(&self) -> u8 {
|
||||
match self {
|
||||
BlockPlacement::Above(_) => 0,
|
||||
BlockPlacement::Replace(_) => 1,
|
||||
BlockPlacement::Near(_) => 2,
|
||||
BlockPlacement::Below(_) => 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockPlacement<Anchor> {
|
||||
fn cmp(&self, other: &Self, buffer: &MultiBufferSnapshot) -> Ordering {
|
||||
match (self, other) {
|
||||
(BlockPlacement::Above(anchor_a), BlockPlacement::Above(anchor_b))
|
||||
| (BlockPlacement::Below(anchor_a), BlockPlacement::Below(anchor_b)) => {
|
||||
anchor_a.cmp(anchor_b, buffer)
|
||||
}
|
||||
(BlockPlacement::Above(anchor_a), BlockPlacement::Below(anchor_b)) => {
|
||||
anchor_a.cmp(anchor_b, buffer).then(Ordering::Less)
|
||||
}
|
||||
(BlockPlacement::Below(anchor_a), BlockPlacement::Above(anchor_b)) => {
|
||||
anchor_a.cmp(anchor_b, buffer).then(Ordering::Greater)
|
||||
}
|
||||
(BlockPlacement::Above(anchor), BlockPlacement::Replace(range)) => {
|
||||
anchor.cmp(range.start(), buffer).then(Ordering::Less)
|
||||
}
|
||||
(BlockPlacement::Replace(range), BlockPlacement::Above(anchor)) => {
|
||||
range.start().cmp(anchor, buffer).then(Ordering::Greater)
|
||||
}
|
||||
(BlockPlacement::Below(anchor), BlockPlacement::Replace(range)) => {
|
||||
anchor.cmp(range.start(), buffer).then(Ordering::Greater)
|
||||
}
|
||||
(BlockPlacement::Replace(range), BlockPlacement::Below(anchor)) => {
|
||||
range.start().cmp(anchor, buffer).then(Ordering::Less)
|
||||
}
|
||||
(BlockPlacement::Replace(range_a), BlockPlacement::Replace(range_b)) => range_a
|
||||
.start()
|
||||
.cmp(range_b.start(), buffer)
|
||||
.then_with(|| range_b.end().cmp(range_a.end(), buffer)),
|
||||
}
|
||||
self.start()
|
||||
.cmp(other.start(), buffer)
|
||||
.then_with(|| other.end().cmp(self.end(), buffer))
|
||||
.then_with(|| self.sort_order().cmp(&other.sort_order()))
|
||||
}
|
||||
|
||||
fn to_wrap_row(&self, wrap_snapshot: &WrapSnapshot) -> Option<BlockPlacement<WrapRow>> {
|
||||
|
@ -165,6 +155,12 @@ impl BlockPlacement<Anchor> {
|
|||
let wrap_row = WrapRow(wrap_snapshot.make_wrap_point(position, Bias::Left).row());
|
||||
Some(BlockPlacement::Above(wrap_row))
|
||||
}
|
||||
BlockPlacement::Near(position) => {
|
||||
let mut position = position.to_point(buffer_snapshot);
|
||||
position.column = buffer_snapshot.line_len(MultiBufferRow(position.row));
|
||||
let wrap_row = WrapRow(wrap_snapshot.make_wrap_point(position, Bias::Left).row());
|
||||
Some(BlockPlacement::Near(wrap_row))
|
||||
}
|
||||
BlockPlacement::Below(position) => {
|
||||
let mut position = position.to_point(buffer_snapshot);
|
||||
position.column = buffer_snapshot.line_len(MultiBufferRow(position.row));
|
||||
|
@ -193,7 +189,7 @@ impl BlockPlacement<Anchor> {
|
|||
pub struct CustomBlock {
|
||||
id: CustomBlockId,
|
||||
placement: BlockPlacement<Anchor>,
|
||||
height: u32,
|
||||
height: Option<u32>,
|
||||
style: BlockStyle,
|
||||
render: Arc<Mutex<RenderBlock>>,
|
||||
priority: usize,
|
||||
|
@ -201,7 +197,9 @@ pub struct CustomBlock {
|
|||
|
||||
pub struct BlockProperties<P> {
|
||||
pub placement: BlockPlacement<P>,
|
||||
pub height: u32,
|
||||
// None if the block takes up no space
|
||||
// (e.g. a horizontal line)
|
||||
pub height: Option<u32>,
|
||||
pub style: BlockStyle,
|
||||
pub render: RenderBlock,
|
||||
pub priority: usize,
|
||||
|
@ -302,9 +300,16 @@ impl Block {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn has_height(&self) -> bool {
|
||||
match self {
|
||||
Block::Custom(block) => block.height.is_some(),
|
||||
Block::ExcerptBoundary { .. } | Block::FoldedBuffer { .. } => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn height(&self) -> u32 {
|
||||
match self {
|
||||
Block::Custom(block) => block.height,
|
||||
Block::Custom(block) => block.height.unwrap_or(0),
|
||||
Block::ExcerptBoundary { height, .. } | Block::FoldedBuffer { height, .. } => *height,
|
||||
}
|
||||
}
|
||||
|
@ -324,9 +329,20 @@ impl Block {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn place_near(&self) -> bool {
|
||||
match self {
|
||||
Block::Custom(block) => matches!(block.placement, BlockPlacement::Near(_)),
|
||||
Block::FoldedBuffer { .. } => false,
|
||||
Block::ExcerptBoundary { .. } => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn place_below(&self) -> bool {
|
||||
match self {
|
||||
Block::Custom(block) => matches!(block.placement, BlockPlacement::Below(_)),
|
||||
Block::Custom(block) => matches!(
|
||||
block.placement,
|
||||
BlockPlacement::Below(_) | BlockPlacement::Near(_)
|
||||
),
|
||||
Block::FoldedBuffer { .. } => false,
|
||||
Block::ExcerptBoundary { .. } => false,
|
||||
}
|
||||
|
@ -669,7 +685,7 @@ impl BlockMap {
|
|||
BlockPlacement::Above(position) => {
|
||||
rows_before_block = position.0 - new_transforms.summary().input_rows;
|
||||
}
|
||||
BlockPlacement::Below(position) => {
|
||||
BlockPlacement::Near(position) | BlockPlacement::Below(position) => {
|
||||
rows_before_block = (position.0 + 1) - new_transforms.summary().input_rows;
|
||||
}
|
||||
BlockPlacement::Replace(range) => {
|
||||
|
@ -803,60 +819,39 @@ impl BlockMap {
|
|||
|
||||
fn sort_blocks(blocks: &mut Vec<(BlockPlacement<WrapRow>, Block)>) {
|
||||
blocks.sort_unstable_by(|(placement_a, block_a), (placement_b, block_b)| {
|
||||
let placement_comparison = match (placement_a, placement_b) {
|
||||
(BlockPlacement::Above(row_a), BlockPlacement::Above(row_b))
|
||||
| (BlockPlacement::Below(row_a), BlockPlacement::Below(row_b)) => row_a.cmp(row_b),
|
||||
(BlockPlacement::Above(row_a), BlockPlacement::Below(row_b)) => {
|
||||
row_a.cmp(row_b).then(Ordering::Less)
|
||||
}
|
||||
(BlockPlacement::Below(row_a), BlockPlacement::Above(row_b)) => {
|
||||
row_a.cmp(row_b).then(Ordering::Greater)
|
||||
}
|
||||
(BlockPlacement::Above(row), BlockPlacement::Replace(range)) => {
|
||||
row.cmp(range.start()).then(Ordering::Greater)
|
||||
}
|
||||
(BlockPlacement::Replace(range), BlockPlacement::Above(row)) => {
|
||||
range.start().cmp(row).then(Ordering::Less)
|
||||
}
|
||||
(BlockPlacement::Below(row), BlockPlacement::Replace(range)) => {
|
||||
row.cmp(range.start()).then(Ordering::Greater)
|
||||
}
|
||||
(BlockPlacement::Replace(range), BlockPlacement::Below(row)) => {
|
||||
range.start().cmp(row).then(Ordering::Less)
|
||||
}
|
||||
(BlockPlacement::Replace(range_a), BlockPlacement::Replace(range_b)) => range_a
|
||||
.start()
|
||||
.cmp(range_b.start())
|
||||
.then_with(|| range_b.end().cmp(range_a.end()))
|
||||
.then_with(|| {
|
||||
if block_a.is_header() {
|
||||
Ordering::Less
|
||||
} else if block_b.is_header() {
|
||||
Ordering::Greater
|
||||
} else {
|
||||
Ordering::Equal
|
||||
}
|
||||
}),
|
||||
};
|
||||
placement_comparison.then_with(|| match (block_a, block_b) {
|
||||
(
|
||||
Block::ExcerptBoundary {
|
||||
excerpt: excerpt_a, ..
|
||||
},
|
||||
Block::ExcerptBoundary {
|
||||
excerpt: excerpt_b, ..
|
||||
},
|
||||
) => Some(excerpt_a.id).cmp(&Some(excerpt_b.id)),
|
||||
(Block::ExcerptBoundary { .. }, Block::Custom(_)) => Ordering::Less,
|
||||
(Block::Custom(_), Block::ExcerptBoundary { .. }) => Ordering::Greater,
|
||||
(Block::Custom(block_a), Block::Custom(block_b)) => block_a
|
||||
.priority
|
||||
.cmp(&block_b.priority)
|
||||
.then_with(|| block_a.id.cmp(&block_b.id)),
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
})
|
||||
placement_a
|
||||
.start()
|
||||
.cmp(placement_b.start())
|
||||
.then_with(|| placement_b.end().cmp(placement_a.end()))
|
||||
.then_with(|| {
|
||||
if block_a.is_header() {
|
||||
Ordering::Less
|
||||
} else if block_b.is_header() {
|
||||
Ordering::Greater
|
||||
} else {
|
||||
Ordering::Equal
|
||||
}
|
||||
})
|
||||
.then_with(|| placement_a.sort_order().cmp(&placement_b.sort_order()))
|
||||
.then_with(|| match (block_a, block_b) {
|
||||
(
|
||||
Block::ExcerptBoundary {
|
||||
excerpt: excerpt_a, ..
|
||||
},
|
||||
Block::ExcerptBoundary {
|
||||
excerpt: excerpt_b, ..
|
||||
},
|
||||
) => Some(excerpt_a.id).cmp(&Some(excerpt_b.id)),
|
||||
(Block::ExcerptBoundary { .. }, Block::Custom(_)) => Ordering::Less,
|
||||
(Block::Custom(_), Block::ExcerptBoundary { .. }) => Ordering::Greater,
|
||||
(Block::Custom(block_a), Block::Custom(block_b)) => block_a
|
||||
.priority
|
||||
.cmp(&block_b.priority)
|
||||
.then_with(|| block_a.id.cmp(&block_b.id)),
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
})
|
||||
});
|
||||
blocks.dedup_by(|right, left| match (left.0.clone(), right.0.clone()) {
|
||||
(BlockPlacement::Replace(range), BlockPlacement::Above(row))
|
||||
|
@ -999,7 +994,7 @@ impl BlockMapWriter<'_> {
|
|||
let mut previous_wrap_row_range: Option<Range<u32>> = None;
|
||||
for block in blocks {
|
||||
if let BlockPlacement::Replace(_) = &block.placement {
|
||||
debug_assert!(block.height > 0);
|
||||
debug_assert!(block.height.unwrap() > 0);
|
||||
}
|
||||
|
||||
let id = CustomBlockId(self.0.next_block_id.fetch_add(1, SeqCst));
|
||||
|
@ -1064,11 +1059,11 @@ impl BlockMapWriter<'_> {
|
|||
debug_assert!(new_height > 0);
|
||||
}
|
||||
|
||||
if block.height != new_height {
|
||||
if block.height != Some(new_height) {
|
||||
let new_block = CustomBlock {
|
||||
id: block.id,
|
||||
placement: block.placement.clone(),
|
||||
height: new_height,
|
||||
height: Some(new_height),
|
||||
style: block.style,
|
||||
render: block.render.clone(),
|
||||
priority: block.priority,
|
||||
|
@ -1965,21 +1960,21 @@ mod tests {
|
|||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Above(buffer_snapshot.anchor_after(Point::new(1, 0))),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Above(buffer_snapshot.anchor_after(Point::new(1, 2))),
|
||||
height: 2,
|
||||
height: Some(2),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Below(buffer_snapshot.anchor_after(Point::new(3, 3))),
|
||||
height: 3,
|
||||
height: Some(3),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
|
@ -1992,7 +1987,7 @@ mod tests {
|
|||
.blocks_in_range(0..8)
|
||||
.map(|(start_row, block)| {
|
||||
let block = block.as_custom().unwrap();
|
||||
(start_row..start_row + block.height, block.id)
|
||||
(start_row..start_row + block.height.unwrap(), block.id)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
@ -2203,21 +2198,21 @@ mod tests {
|
|||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Above(buffer_snapshot.anchor_after(Point::new(1, 0))),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Above(buffer_snapshot.anchor_after(Point::new(1, 2))),
|
||||
height: 2,
|
||||
height: Some(2),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Below(buffer_snapshot.anchor_after(Point::new(3, 3))),
|
||||
height: 3,
|
||||
height: Some(3),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
|
@ -2307,14 +2302,14 @@ mod tests {
|
|||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Above(buffer_snapshot.anchor_after(Point::new(1, 12))),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
priority: 0,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Below(buffer_snapshot.anchor_after(Point::new(1, 1))),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
priority: 0,
|
||||
},
|
||||
]);
|
||||
|
@ -2352,7 +2347,7 @@ mod tests {
|
|||
buffer_snapshot.anchor_after(Point::new(1, 3))
|
||||
..=buffer_snapshot.anchor_before(Point::new(3, 1)),
|
||||
),
|
||||
height: 4,
|
||||
height: Some(4),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
}])[0];
|
||||
|
@ -2405,21 +2400,21 @@ mod tests {
|
|||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Above(buffer_snapshot.anchor_after(Point::new(0, 3))),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Above(buffer_snapshot.anchor_after(Point::new(1, 3))),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Below(buffer_snapshot.anchor_after(Point::new(6, 2))),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
|
@ -2433,21 +2428,21 @@ mod tests {
|
|||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Below(buffer_snapshot.anchor_after(Point::new(1, 3))),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Above(buffer_snapshot.anchor_after(Point::new(2, 1))),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Above(buffer_snapshot.anchor_after(Point::new(6, 1))),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
|
@ -2546,21 +2541,21 @@ mod tests {
|
|||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Above(buffer_snapshot.anchor_after(Point::new(1, 0))),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Above(buffer_snapshot.anchor_after(Point::new(2, 0))),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Below(buffer_snapshot.anchor_after(Point::new(3, 0))),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
|
@ -2569,14 +2564,14 @@ mod tests {
|
|||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Above(buffer_snapshot.anchor_after(Point::new(4, 0))),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Below(buffer_snapshot.anchor_after(Point::new(5, 0))),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
},
|
||||
|
@ -2623,7 +2618,7 @@ mod tests {
|
|||
let excerpt_blocks_1 = writer.insert(vec![BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Above(buffer_snapshot.anchor_after(Point::new(0, 0))),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
}]);
|
||||
|
@ -2980,7 +2975,7 @@ mod tests {
|
|||
BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement,
|
||||
height,
|
||||
height: Some(height),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
}
|
||||
|
@ -3007,7 +3002,7 @@ mod tests {
|
|||
|
||||
for (block_properties, block_id) in block_properties.iter().zip(block_ids) {
|
||||
log::info!(
|
||||
"inserted block {:?} with height {} and id {:?}",
|
||||
"inserted block {:?} with height {:?} and id {:?}",
|
||||
block_properties
|
||||
.placement
|
||||
.as_ref()
|
||||
|
@ -3524,7 +3519,7 @@ mod tests {
|
|||
let _block_id = writer.insert(vec![BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Above(buffer_snapshot.anchor_after(Point::new(1, 0))),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
}])[0];
|
||||
|
|
|
@ -14,6 +14,7 @@ use std::{
|
|||
fmt, iter,
|
||||
ops::{Add, AddAssign, Deref, DerefMut, Range, Sub},
|
||||
sync::Arc,
|
||||
usize,
|
||||
};
|
||||
use sum_tree::{Bias, Cursor, FilterCursor, SumTree, Summary, TreeMap};
|
||||
use ui::IntoElement as _;
|
||||
|
|
|
@ -8717,7 +8717,7 @@ impl Editor {
|
|||
let blocks = vec![BlockProperties {
|
||||
style: BlockStyle::Sticky,
|
||||
placement: BlockPlacement::Above(anchor),
|
||||
height,
|
||||
height: Some(height),
|
||||
render: Arc::new(move |cx| {
|
||||
*cloned_prompt.read(cx).gutter_dimensions.lock() = *cx.gutter_dimensions;
|
||||
cloned_prompt.clone().into_any_element()
|
||||
|
@ -12801,7 +12801,6 @@ impl Editor {
|
|||
) {
|
||||
let buffer = self.buffer.read(cx).snapshot(cx);
|
||||
let selection = self.selections.newest::<usize>(cx);
|
||||
|
||||
// If there is an active Diagnostic Popover jump to its diagnostic instead.
|
||||
if direction == Direction::Next {
|
||||
if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
|
||||
|
@ -13806,7 +13805,7 @@ impl Editor {
|
|||
[BlockProperties {
|
||||
style: BlockStyle::Flex,
|
||||
placement: BlockPlacement::Below(range.start),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new({
|
||||
let rename_editor = rename_editor.clone();
|
||||
move |cx: &mut BlockContext| {
|
||||
|
@ -14273,7 +14272,7 @@ impl Editor {
|
|||
placement: BlockPlacement::Below(
|
||||
buffer.anchor_after(entry.range.start),
|
||||
),
|
||||
height: message_height,
|
||||
height: Some(message_height),
|
||||
render: diagnostic_block_renderer(diagnostic, None, true),
|
||||
priority: 0,
|
||||
}
|
||||
|
|
|
@ -4234,7 +4234,7 @@ fn test_move_line_up_down_with_blocks(cx: &mut TestAppContext) {
|
|||
[BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Below(snapshot.anchor_after(Point::new(2, 0))),
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
render: Arc::new(|_| div().into_any()),
|
||||
priority: 0,
|
||||
}],
|
||||
|
@ -4275,7 +4275,7 @@ async fn test_selections_and_replace_blocks(cx: &mut TestAppContext) {
|
|||
editor.insert_blocks(
|
||||
[BlockProperties {
|
||||
placement,
|
||||
height: 4,
|
||||
height: Some(4),
|
||||
style: BlockStyle::Sticky,
|
||||
render: Arc::new(|_| gpui::div().into_any_element()),
|
||||
priority: 0,
|
||||
|
|
|
@ -27,7 +27,7 @@ use crate::{
|
|||
};
|
||||
use buffer_diff::{DiffHunkStatus, DiffHunkStatusKind};
|
||||
use client::ParticipantIndex;
|
||||
use collections::{BTreeMap, HashMap, HashSet};
|
||||
use collections::{BTreeMap, HashMap};
|
||||
use feature_flags::{Debugger, FeatureFlagAppExt};
|
||||
use file_icons::FileIcons;
|
||||
use git::{Oid, blame::BlameEntry, status::FileStatus};
|
||||
|
@ -1219,7 +1219,7 @@ impl EditorElement {
|
|||
&self,
|
||||
snapshot: &EditorSnapshot,
|
||||
selections: &[(PlayerColor, Vec<SelectionLayout>)],
|
||||
block_start_rows: &HashSet<DisplayRow>,
|
||||
row_block_types: &HashMap<DisplayRow, bool>,
|
||||
visible_display_row_range: Range<DisplayRow>,
|
||||
line_layouts: &[LineWithInvisibles],
|
||||
text_hitbox: &Hitbox,
|
||||
|
@ -1246,7 +1246,7 @@ impl EditorElement {
|
|||
let in_range = visible_display_row_range.contains(&cursor_position.row());
|
||||
if (selection.is_local && !show_local_cursors)
|
||||
|| !in_range
|
||||
|| block_start_rows.contains(&cursor_position.row())
|
||||
|| row_block_types.get(&cursor_position.row()) == Some(&true)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -1571,6 +1571,7 @@ impl EditorElement {
|
|||
&self,
|
||||
line_layouts: &[LineWithInvisibles],
|
||||
crease_trailers: &[Option<CreaseTrailerLayout>],
|
||||
row_block_types: &HashMap<DisplayRow, bool>,
|
||||
content_origin: gpui::Point<Pixels>,
|
||||
scroll_pixel_position: gpui::Point<Pixels>,
|
||||
inline_completion_popover_origin: Option<gpui::Point<Pixels>>,
|
||||
|
@ -1616,6 +1617,7 @@ impl EditorElement {
|
|||
.map(|(point, diag)| (point.to_display_point(&snapshot), diag.clone()))
|
||||
.skip_while(|(point, _)| point.row() < start_row)
|
||||
.take_while(|(point, _)| point.row() < end_row)
|
||||
.filter(|(point, _)| !row_block_types.contains_key(&point.row()))
|
||||
.fold(HashMap::default(), |mut acc, (point, diagnostic)| {
|
||||
acc.entry(point.row())
|
||||
.or_insert_with(Vec::new)
|
||||
|
@ -2614,34 +2616,41 @@ impl EditorElement {
|
|||
editor_width: Pixels,
|
||||
scroll_width: &mut Pixels,
|
||||
resized_blocks: &mut HashMap<CustomBlockId, u32>,
|
||||
row_block_types: &mut HashMap<DisplayRow, bool>,
|
||||
selections: &[Selection<Point>],
|
||||
selected_buffer_ids: &Vec<BufferId>,
|
||||
is_row_soft_wrapped: impl Copy + Fn(usize) -> bool,
|
||||
sticky_header_excerpt_id: Option<ExcerptId>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> (AnyElement, Size<Pixels>) {
|
||||
) -> (AnyElement, Size<Pixels>, DisplayRow, Pixels) {
|
||||
let mut x_position = None;
|
||||
let mut element = match block {
|
||||
Block::Custom(block) => {
|
||||
let block_start = block.start().to_point(&snapshot.buffer_snapshot);
|
||||
let block_end = block.end().to_point(&snapshot.buffer_snapshot);
|
||||
let align_to = block_start.to_display_point(snapshot);
|
||||
let anchor_x = text_x
|
||||
+ if rows.contains(&align_to.row()) {
|
||||
line_layouts[align_to.row().minus(rows.start) as usize]
|
||||
.x_for_index(align_to.column() as usize)
|
||||
} else {
|
||||
layout_line(
|
||||
align_to.row(),
|
||||
snapshot,
|
||||
&self.style,
|
||||
editor_width,
|
||||
is_row_soft_wrapped,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.x_for_index(align_to.column() as usize)
|
||||
};
|
||||
let x_and_width = |layout: &LineWithInvisibles| {
|
||||
Some((
|
||||
text_x + layout.x_for_index(align_to.column() as usize),
|
||||
text_x + layout.width,
|
||||
))
|
||||
};
|
||||
x_position = if rows.contains(&align_to.row()) {
|
||||
x_and_width(&line_layouts[align_to.row().minus(rows.start) as usize])
|
||||
} else {
|
||||
x_and_width(&layout_line(
|
||||
align_to.row(),
|
||||
snapshot,
|
||||
&self.style,
|
||||
editor_width,
|
||||
is_row_soft_wrapped,
|
||||
window,
|
||||
cx,
|
||||
))
|
||||
};
|
||||
|
||||
let anchor_x = x_position.unwrap().0;
|
||||
|
||||
let selected = selections
|
||||
.binary_search_by(|selection| {
|
||||
|
@ -2746,17 +2755,43 @@ impl EditorElement {
|
|||
element.layout_as_root(size(available_width, quantized_height.into()), window, cx)
|
||||
};
|
||||
|
||||
let mut row = block_row_start;
|
||||
let mut x_offset = px(0.);
|
||||
let mut is_block = true;
|
||||
|
||||
if let BlockId::Custom(custom_block_id) = block_id {
|
||||
if block.height() > 0 {
|
||||
let element_height_in_lines =
|
||||
if block.has_height() {
|
||||
let mut element_height_in_lines =
|
||||
((final_size.height / line_height).ceil() as u32).max(1);
|
||||
|
||||
if block.place_near() && element_height_in_lines == 1 {
|
||||
if let Some((x_target, line_width)) = x_position {
|
||||
let margin = em_width * 2;
|
||||
if line_width + final_size.width + margin
|
||||
< editor_width + gutter_dimensions.full_width()
|
||||
&& !row_block_types.contains_key(&(row - 1))
|
||||
{
|
||||
x_offset = line_width + margin;
|
||||
row = row - 1;
|
||||
is_block = false;
|
||||
element_height_in_lines = 0;
|
||||
} else {
|
||||
let max_offset =
|
||||
editor_width + gutter_dimensions.full_width() - final_size.width;
|
||||
let min_offset = (x_target + em_width - final_size.width)
|
||||
.max(gutter_dimensions.full_width());
|
||||
x_offset = x_target.min(max_offset).max(min_offset);
|
||||
}
|
||||
}
|
||||
};
|
||||
if element_height_in_lines != block.height() {
|
||||
resized_blocks.insert(custom_block_id, element_height_in_lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
row_block_types.insert(row, is_block);
|
||||
|
||||
(element, final_size)
|
||||
(element, final_size, row, x_offset)
|
||||
}
|
||||
|
||||
fn render_buffer_header(
|
||||
|
@ -2962,14 +2997,14 @@ impl EditorElement {
|
|||
em_width: Pixels,
|
||||
text_x: Pixels,
|
||||
line_height: Pixels,
|
||||
line_layouts: &[LineWithInvisibles],
|
||||
line_layouts: &mut [LineWithInvisibles],
|
||||
selections: &[Selection<Point>],
|
||||
selected_buffer_ids: &Vec<BufferId>,
|
||||
is_row_soft_wrapped: impl Copy + Fn(usize) -> bool,
|
||||
sticky_header_excerpt_id: Option<ExcerptId>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Result<Vec<BlockLayout>, HashMap<CustomBlockId, u32>> {
|
||||
) -> Result<(Vec<BlockLayout>, HashMap<DisplayRow, bool>), HashMap<CustomBlockId, u32>> {
|
||||
let (fixed_blocks, non_fixed_blocks) = snapshot
|
||||
.blocks_in_range(rows.clone())
|
||||
.partition::<Vec<_>, _>(|(_, block)| block.style() == BlockStyle::Fixed);
|
||||
|
@ -2980,6 +3015,7 @@ impl EditorElement {
|
|||
let mut fixed_block_max_width = Pixels::ZERO;
|
||||
let mut blocks = Vec::new();
|
||||
let mut resized_blocks = HashMap::default();
|
||||
let mut row_block_types = HashMap::default();
|
||||
|
||||
for (row, block) in fixed_blocks {
|
||||
let block_id = block.id();
|
||||
|
@ -2988,7 +3024,7 @@ impl EditorElement {
|
|||
focused_block = None;
|
||||
}
|
||||
|
||||
let (element, element_size) = self.render_block(
|
||||
let (element, element_size, row, x_offset) = self.render_block(
|
||||
block,
|
||||
AvailableSpace::MinContent,
|
||||
block_id,
|
||||
|
@ -3004,6 +3040,7 @@ impl EditorElement {
|
|||
editor_width,
|
||||
scroll_width,
|
||||
&mut resized_blocks,
|
||||
&mut row_block_types,
|
||||
selections,
|
||||
selected_buffer_ids,
|
||||
is_row_soft_wrapped,
|
||||
|
@ -3011,27 +3048,32 @@ impl EditorElement {
|
|||
window,
|
||||
cx,
|
||||
);
|
||||
|
||||
fixed_block_max_width = fixed_block_max_width.max(element_size.width + em_width);
|
||||
blocks.push(BlockLayout {
|
||||
id: block_id,
|
||||
x_offset,
|
||||
row: Some(row),
|
||||
element,
|
||||
available_space: size(AvailableSpace::MinContent, element_size.height.into()),
|
||||
style: BlockStyle::Fixed,
|
||||
overlaps_gutter: true,
|
||||
is_buffer_header: block.is_buffer_header(),
|
||||
});
|
||||
}
|
||||
|
||||
for (row, block) in non_fixed_blocks {
|
||||
let style = block.style();
|
||||
let width = match style {
|
||||
BlockStyle::Sticky => hitbox.size.width,
|
||||
BlockStyle::Flex => hitbox
|
||||
let width = match (style, block.place_near()) {
|
||||
(_, true) => AvailableSpace::MinContent,
|
||||
(BlockStyle::Sticky, _) => hitbox.size.width.into(),
|
||||
(BlockStyle::Flex, _) => hitbox
|
||||
.size
|
||||
.width
|
||||
.max(fixed_block_max_width)
|
||||
.max(gutter_dimensions.width + *scroll_width),
|
||||
BlockStyle::Fixed => unreachable!(),
|
||||
.max(gutter_dimensions.width + *scroll_width)
|
||||
.into(),
|
||||
(BlockStyle::Fixed, _) => unreachable!(),
|
||||
};
|
||||
let block_id = block.id();
|
||||
|
||||
|
@ -3039,9 +3081,9 @@ impl EditorElement {
|
|||
focused_block = None;
|
||||
}
|
||||
|
||||
let (element, element_size) = self.render_block(
|
||||
let (element, element_size, row, x_offset) = self.render_block(
|
||||
block,
|
||||
width.into(),
|
||||
width,
|
||||
block_id,
|
||||
row,
|
||||
snapshot,
|
||||
|
@ -3055,6 +3097,7 @@ impl EditorElement {
|
|||
editor_width,
|
||||
scroll_width,
|
||||
&mut resized_blocks,
|
||||
&mut row_block_types,
|
||||
selections,
|
||||
selected_buffer_ids,
|
||||
is_row_soft_wrapped,
|
||||
|
@ -3065,10 +3108,12 @@ impl EditorElement {
|
|||
|
||||
blocks.push(BlockLayout {
|
||||
id: block_id,
|
||||
x_offset,
|
||||
row: Some(row),
|
||||
element,
|
||||
available_space: size(width.into(), element_size.height.into()),
|
||||
available_space: size(width, element_size.height.into()),
|
||||
style,
|
||||
overlaps_gutter: !block.place_near(),
|
||||
is_buffer_header: block.is_buffer_header(),
|
||||
});
|
||||
}
|
||||
|
@ -3090,7 +3135,7 @@ impl EditorElement {
|
|||
BlockStyle::Sticky => AvailableSpace::Definite(hitbox.size.width),
|
||||
};
|
||||
|
||||
let (element, element_size) = self.render_block(
|
||||
let (element, element_size, _, x_offset) = self.render_block(
|
||||
&block,
|
||||
width,
|
||||
focused_block.id,
|
||||
|
@ -3106,6 +3151,7 @@ impl EditorElement {
|
|||
editor_width,
|
||||
scroll_width,
|
||||
&mut resized_blocks,
|
||||
&mut row_block_types,
|
||||
selections,
|
||||
selected_buffer_ids,
|
||||
is_row_soft_wrapped,
|
||||
|
@ -3116,10 +3162,12 @@ impl EditorElement {
|
|||
|
||||
blocks.push(BlockLayout {
|
||||
id: block.id(),
|
||||
x_offset,
|
||||
row: None,
|
||||
element,
|
||||
available_space: size(width, element_size.height.into()),
|
||||
style,
|
||||
overlaps_gutter: true,
|
||||
is_buffer_header: block.is_buffer_header(),
|
||||
});
|
||||
}
|
||||
|
@ -3129,18 +3177,15 @@ impl EditorElement {
|
|||
|
||||
if resized_blocks.is_empty() {
|
||||
*scroll_width = (*scroll_width).max(fixed_block_max_width - gutter_dimensions.width);
|
||||
Ok(blocks)
|
||||
Ok((blocks, row_block_types))
|
||||
} else {
|
||||
Err(resized_blocks)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if any of the blocks changed size since the previous frame. This will trigger
|
||||
/// a restart of rendering for the editor based on the new sizes.
|
||||
fn layout_blocks(
|
||||
&self,
|
||||
blocks: &mut Vec<BlockLayout>,
|
||||
block_starts: &mut HashSet<DisplayRow>,
|
||||
hitbox: &Hitbox,
|
||||
line_height: Pixels,
|
||||
scroll_pixel_position: gpui::Point<Pixels>,
|
||||
|
@ -3149,10 +3194,9 @@ impl EditorElement {
|
|||
) {
|
||||
for block in blocks {
|
||||
let mut origin = if let Some(row) = block.row {
|
||||
block_starts.insert(row);
|
||||
hitbox.origin
|
||||
+ point(
|
||||
Pixels::ZERO,
|
||||
block.x_offset,
|
||||
row.as_f32() * line_height - scroll_pixel_position.y,
|
||||
)
|
||||
} else {
|
||||
|
@ -5322,7 +5366,15 @@ impl EditorElement {
|
|||
|
||||
fn paint_blocks(&mut self, layout: &mut EditorLayout, window: &mut Window, cx: &mut App) {
|
||||
for mut block in layout.blocks.drain(..) {
|
||||
block.element.paint(window, cx);
|
||||
if block.overlaps_gutter {
|
||||
block.element.paint(window, cx);
|
||||
} else {
|
||||
let mut bounds = layout.hitbox.bounds;
|
||||
bounds.origin.x += layout.gutter_hitbox.bounds.size.width;
|
||||
window.with_content_mask(Some(ContentMask { bounds }), |window| {
|
||||
block.element.paint(window, cx);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6955,7 +7007,7 @@ impl Element for EditorElement {
|
|||
em_width,
|
||||
gutter_dimensions.full_width(),
|
||||
line_height,
|
||||
&line_layouts,
|
||||
&mut line_layouts,
|
||||
&local_selections,
|
||||
&selected_buffer_ids,
|
||||
is_row_soft_wrapped,
|
||||
|
@ -6964,7 +7016,7 @@ impl Element for EditorElement {
|
|||
cx,
|
||||
)
|
||||
});
|
||||
let mut blocks = match blocks {
|
||||
let (mut blocks, row_block_types) = match blocks {
|
||||
Ok(blocks) => blocks,
|
||||
Err(resized_blocks) => {
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
|
@ -7078,6 +7130,7 @@ impl Element for EditorElement {
|
|||
let mut inline_diagnostics = self.layout_inline_diagnostics(
|
||||
&line_layouts,
|
||||
&crease_trailers,
|
||||
&row_block_types,
|
||||
content_origin,
|
||||
scroll_pixel_position,
|
||||
inline_completion_popover_origin,
|
||||
|
@ -7093,7 +7146,9 @@ impl Element for EditorElement {
|
|||
let mut inline_blame = None;
|
||||
if let Some(newest_selection_head) = newest_selection_head {
|
||||
let display_row = newest_selection_head.row();
|
||||
if (start_row..end_row).contains(&display_row) {
|
||||
if (start_row..end_row).contains(&display_row)
|
||||
&& !row_block_types.contains_key(&display_row)
|
||||
{
|
||||
let line_ix = display_row.minus(start_row) as usize;
|
||||
let row_info = &row_infos[line_ix];
|
||||
let line_layout = &line_layouts[line_ix];
|
||||
|
@ -7161,12 +7216,9 @@ impl Element for EditorElement {
|
|||
cx,
|
||||
);
|
||||
|
||||
let mut block_start_rows = HashSet::default();
|
||||
|
||||
window.with_element_namespace("blocks", |window| {
|
||||
self.layout_blocks(
|
||||
&mut blocks,
|
||||
&mut block_start_rows,
|
||||
&hitbox,
|
||||
line_height,
|
||||
scroll_pixel_position,
|
||||
|
@ -7184,7 +7236,7 @@ impl Element for EditorElement {
|
|||
let visible_cursors = self.layout_visible_cursors(
|
||||
&snapshot,
|
||||
&selections,
|
||||
&block_start_rows,
|
||||
&row_block_types,
|
||||
start_row..end_row,
|
||||
&line_layouts,
|
||||
&text_hitbox,
|
||||
|
@ -8028,10 +8080,12 @@ impl PositionMap {
|
|||
|
||||
struct BlockLayout {
|
||||
id: BlockId,
|
||||
x_offset: Pixels,
|
||||
row: Option<DisplayRow>,
|
||||
element: AnyElement,
|
||||
available_space: Size<AvailableSpace>,
|
||||
style: BlockStyle,
|
||||
overlaps_gutter: bool,
|
||||
is_buffer_header: bool,
|
||||
}
|
||||
|
||||
|
@ -8620,7 +8674,7 @@ mod tests {
|
|||
[BlockProperties {
|
||||
style: BlockStyle::Fixed,
|
||||
placement: BlockPlacement::Above(Anchor::min()),
|
||||
height: 3,
|
||||
height: Some(3),
|
||||
render: Arc::new(|cx| div().h(3. * cx.window.line_height()).into_any()),
|
||||
priority: 0,
|
||||
}],
|
||||
|
|
|
@ -57,6 +57,10 @@ impl Anchor {
|
|||
}
|
||||
|
||||
pub fn cmp(&self, other: &Anchor, snapshot: &MultiBufferSnapshot) -> Ordering {
|
||||
if self == other {
|
||||
return Ordering::Equal;
|
||||
}
|
||||
|
||||
let excerpt_id_cmp = self.excerpt_id.cmp(&other.excerpt_id, snapshot);
|
||||
if excerpt_id_cmp.is_ne() {
|
||||
return excerpt_id_cmp;
|
||||
|
|
|
@ -89,7 +89,7 @@ impl EditorBlock {
|
|||
let block = BlockProperties {
|
||||
placement: BlockPlacement::Below(code_range.end),
|
||||
// Take up at least one height for status, allow the editor to determine the real height based on the content from render
|
||||
height: 1,
|
||||
height: Some(1),
|
||||
style: BlockStyle::Sticky,
|
||||
render: Self::create_output_area_renderer(execution_view.clone(), on_close.clone()),
|
||||
priority: 0,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue