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