mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-20 02:47:34 +03:00
Render path headers in editor element
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
f1e3d5285b
commit
8d95dbe3e6
@ -423,25 +423,16 @@ impl ProjectDiagnosticsEditor {
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
blocks_to_remove.extend(path_state.header);
|
||||
editor.remove_blocks(blocks_to_remove, cx);
|
||||
let header_block = first_excerpt_id.map(|excerpt_id| BlockProperties {
|
||||
position: excerpts_snapshot.anchor_in_excerpt(excerpt_id, language::Anchor::min()),
|
||||
height: 2,
|
||||
render: path_header_renderer(buffer, self.build_settings.clone()),
|
||||
disposition: BlockDisposition::Above,
|
||||
});
|
||||
let block_ids = editor.insert_blocks(
|
||||
blocks_to_add
|
||||
.into_iter()
|
||||
.map(|block| {
|
||||
let (excerpt_id, text_anchor) = block.position;
|
||||
BlockProperties {
|
||||
position: excerpts_snapshot.anchor_in_excerpt(excerpt_id, text_anchor),
|
||||
height: block.height,
|
||||
render: block.render,
|
||||
disposition: block.disposition,
|
||||
}
|
||||
})
|
||||
.chain(header_block.into_iter()),
|
||||
blocks_to_add.into_iter().map(|block| {
|
||||
let (excerpt_id, text_anchor) = block.position;
|
||||
BlockProperties {
|
||||
position: excerpts_snapshot.anchor_in_excerpt(excerpt_id, text_anchor),
|
||||
height: block.height,
|
||||
render: block.render,
|
||||
disposition: block.disposition,
|
||||
}
|
||||
}),
|
||||
cx,
|
||||
);
|
||||
|
||||
@ -660,51 +651,6 @@ impl workspace::ItemView for ProjectDiagnosticsEditor {
|
||||
}
|
||||
}
|
||||
|
||||
fn path_header_renderer(buffer: ModelHandle<Buffer>, build_settings: BuildSettings) -> RenderBlock {
|
||||
Arc::new(move |cx| {
|
||||
let settings = build_settings(cx);
|
||||
let style = settings.style.diagnostic_path_header;
|
||||
let font_size = (style.text_scale_factor * settings.style.text.font_size).round();
|
||||
|
||||
let mut filename = None;
|
||||
let mut path = None;
|
||||
if let Some(file) = buffer.read(&**cx).file() {
|
||||
filename = file
|
||||
.path()
|
||||
.file_name()
|
||||
.map(|f| f.to_string_lossy().to_string());
|
||||
path = file
|
||||
.path()
|
||||
.parent()
|
||||
.map(|p| p.to_string_lossy().to_string() + "/");
|
||||
}
|
||||
|
||||
Flex::row()
|
||||
.with_child(
|
||||
Label::new(
|
||||
filename.unwrap_or_else(|| "untitled".to_string()),
|
||||
style.filename.text.clone().with_font_size(font_size),
|
||||
)
|
||||
.contained()
|
||||
.with_style(style.filename.container)
|
||||
.boxed(),
|
||||
)
|
||||
.with_children(path.map(|path| {
|
||||
Label::new(path, style.path.text.clone().with_font_size(font_size))
|
||||
.contained()
|
||||
.with_style(style.path.container)
|
||||
.boxed()
|
||||
}))
|
||||
.aligned()
|
||||
.left()
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
.with_padding_left(cx.gutter_padding + cx.scroll_x * cx.em_width)
|
||||
.expanded()
|
||||
.named("path header block")
|
||||
})
|
||||
}
|
||||
|
||||
fn diagnostic_header_renderer(
|
||||
diagnostic: Diagnostic,
|
||||
build_settings: BuildSettings,
|
||||
@ -843,7 +789,10 @@ fn compare_diagnostics<L: language::ToOffset, R: language::ToOffset>(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use editor::{display_map::BlockContext, DisplayPoint, EditorSnapshot};
|
||||
use editor::{
|
||||
display_map::{BlockContext, TransformBlock},
|
||||
DisplayPoint, EditorSnapshot,
|
||||
};
|
||||
use gpui::TestAppContext;
|
||||
use language::{Diagnostic, DiagnosticEntry, DiagnosticSeverity, PointUtf16};
|
||||
use serde_json::json;
|
||||
@ -1259,18 +1208,23 @@ mod tests {
|
||||
editor
|
||||
.blocks_in_range(0..editor.max_point().row())
|
||||
.filter_map(|(row, block)| {
|
||||
block
|
||||
.render(&BlockContext {
|
||||
cx,
|
||||
anchor_x: 0.,
|
||||
scroll_x: 0.,
|
||||
gutter_padding: 0.,
|
||||
gutter_width: 0.,
|
||||
line_height: 0.,
|
||||
em_width: 0.,
|
||||
})
|
||||
.name()
|
||||
.map(|s| (row, s.to_string()))
|
||||
let name = match block {
|
||||
TransformBlock::Custom(block) => block
|
||||
.render(&BlockContext {
|
||||
cx,
|
||||
anchor_x: 0.,
|
||||
scroll_x: 0.,
|
||||
gutter_padding: 0.,
|
||||
gutter_width: 0.,
|
||||
line_height: 0.,
|
||||
em_width: 0.,
|
||||
})
|
||||
.name()?
|
||||
.to_string(),
|
||||
TransformBlock::ExcerptHeader { .. } => "path header block".to_string(),
|
||||
};
|
||||
|
||||
Some((row, name))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
@ -90,10 +90,7 @@ struct Transform {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum TransformBlock {
|
||||
Custom {
|
||||
block: Arc<Block>,
|
||||
column: u32,
|
||||
},
|
||||
Custom(Arc<Block>),
|
||||
ExcerptHeader {
|
||||
buffer: BufferSnapshot,
|
||||
range: Range<text::Anchor>,
|
||||
@ -104,14 +101,14 @@ pub enum TransformBlock {
|
||||
impl TransformBlock {
|
||||
fn disposition(&self) -> BlockDisposition {
|
||||
match self {
|
||||
TransformBlock::Custom { block, .. } => block.disposition,
|
||||
TransformBlock::Custom(block) => block.disposition,
|
||||
TransformBlock::ExcerptHeader { .. } => BlockDisposition::Above,
|
||||
}
|
||||
}
|
||||
|
||||
fn height(&self) -> u8 {
|
||||
pub fn height(&self) -> u8 {
|
||||
match self {
|
||||
TransformBlock::Custom { block, .. } => block.height,
|
||||
TransformBlock::Custom(block) => block.height,
|
||||
TransformBlock::ExcerptHeader { height, .. } => *height,
|
||||
}
|
||||
}
|
||||
@ -120,11 +117,7 @@ impl TransformBlock {
|
||||
impl Debug for TransformBlock {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Custom { block, column } => f
|
||||
.debug_struct("Custom")
|
||||
.field("block", block)
|
||||
.field("column", column)
|
||||
.finish(),
|
||||
Self::Custom(block) => f.debug_struct("Custom").field("block", block).finish(),
|
||||
Self::ExcerptHeader { buffer, .. } => f
|
||||
.debug_struct("ExcerptHeader")
|
||||
.field("path", &buffer.path())
|
||||
@ -319,7 +312,6 @@ impl BlockMap {
|
||||
.iter()
|
||||
.map(|block| {
|
||||
let mut position = block.position.to_point(&buffer);
|
||||
let column = wrap_snapshot.from_point(position, Bias::Left).column();
|
||||
match block.disposition {
|
||||
BlockDisposition::Above => position.column = 0,
|
||||
BlockDisposition::Below => {
|
||||
@ -327,13 +319,7 @@ impl BlockMap {
|
||||
}
|
||||
}
|
||||
let position = wrap_snapshot.from_point(position, Bias::Left);
|
||||
(
|
||||
position.row(),
|
||||
TransformBlock::Custom {
|
||||
block: block.clone(),
|
||||
column,
|
||||
},
|
||||
)
|
||||
(position.row(), TransformBlock::Custom(block.clone()))
|
||||
}),
|
||||
);
|
||||
blocks_in_edit.extend(
|
||||
@ -362,10 +348,7 @@ impl BlockMap {
|
||||
) => Ordering::Equal,
|
||||
(TransformBlock::ExcerptHeader { .. }, _) => Ordering::Less,
|
||||
(_, TransformBlock::ExcerptHeader { .. }) => Ordering::Greater,
|
||||
(
|
||||
TransformBlock::Custom { block: block_a, .. },
|
||||
TransformBlock::Custom { block: block_b, .. },
|
||||
) => block_a
|
||||
(TransformBlock::Custom(block_a), TransformBlock::Custom(block_b)) => block_a
|
||||
.disposition
|
||||
.cmp(&block_b.disposition)
|
||||
.then_with(|| block_a.id.cmp(&block_b.id)),
|
||||
@ -908,6 +891,10 @@ impl Block {
|
||||
pub fn render(&self, cx: &BlockContext) -> ElementBox {
|
||||
self.render.lock()(cx)
|
||||
}
|
||||
|
||||
pub fn position(&self) -> &Anchor {
|
||||
&self.position
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Block {
|
||||
@ -1008,10 +995,9 @@ mod tests {
|
||||
let blocks = snapshot
|
||||
.blocks_in_range(0..8)
|
||||
.map(|(start_row, block)| {
|
||||
let (block, column) = block.as_custom().unwrap();
|
||||
let block = block.as_custom().unwrap();
|
||||
(
|
||||
start_row..start_row + block.height as u32,
|
||||
column,
|
||||
block
|
||||
.render(&BlockContext {
|
||||
cx,
|
||||
@ -1033,9 +1019,9 @@ mod tests {
|
||||
assert_eq!(
|
||||
blocks,
|
||||
&[
|
||||
(1..3, 2, "block 2".to_string()),
|
||||
(3..4, 0, "block 1".to_string()),
|
||||
(7..10, 3, "block 3".to_string()),
|
||||
(1..2, "block 1".to_string()),
|
||||
(2..4, "block 2".to_string()),
|
||||
(7..10, "block 3".to_string()),
|
||||
]
|
||||
);
|
||||
|
||||
@ -1324,7 +1310,6 @@ mod tests {
|
||||
let mut expected_blocks = Vec::new();
|
||||
expected_blocks.extend(custom_blocks.iter().map(|(id, block)| {
|
||||
let mut position = block.position.to_point(&buffer_snapshot);
|
||||
let column = wraps_snapshot.from_point(position, Bias::Left).column();
|
||||
match block.disposition {
|
||||
BlockDisposition::Above => {
|
||||
position.column = 0;
|
||||
@ -1426,7 +1411,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
blocks_snapshot
|
||||
.blocks_in_range(0..(expected_row_count as u32))
|
||||
.map(|(row, block)| (row, block.as_custom().map(|(b, _)| b.id)))
|
||||
.map(|(row, block)| { (row, block.as_custom().map(|b| b.id)) })
|
||||
.collect::<Vec<_>>(),
|
||||
expected_block_positions
|
||||
);
|
||||
@ -1508,9 +1493,9 @@ mod tests {
|
||||
}
|
||||
|
||||
impl TransformBlock {
|
||||
fn as_custom(&self) -> Option<(&Block, u32)> {
|
||||
fn as_custom(&self) -> Option<&Block> {
|
||||
match self {
|
||||
TransformBlock::Custom { block, column } => Some((block, *column)),
|
||||
TransformBlock::Custom(block) => Some(block),
|
||||
TransformBlock::ExcerptHeader { .. } => None,
|
||||
}
|
||||
}
|
||||
|
@ -588,10 +588,6 @@ impl WrapSnapshot {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn text_summary(&self) -> TextSummary {
|
||||
self.transforms.summary().output
|
||||
}
|
||||
|
||||
pub fn max_point(&self) -> WrapPoint {
|
||||
WrapPoint(self.transforms.summary().output.lines)
|
||||
}
|
||||
@ -955,10 +951,6 @@ impl WrapPoint {
|
||||
&mut self.0.row
|
||||
}
|
||||
|
||||
pub fn column(&self) -> u32 {
|
||||
self.0.column
|
||||
}
|
||||
|
||||
pub fn column_mut(&mut self) -> &mut u32 {
|
||||
&mut self.0.column
|
||||
}
|
||||
|
@ -3,11 +3,12 @@ use super::{
|
||||
Anchor, DisplayPoint, Editor, EditorMode, EditorSettings, EditorSnapshot, EditorStyle, Input,
|
||||
Scroll, Select, SelectPhase, SoftWrap, ToPoint, MAX_LINE_LEN,
|
||||
};
|
||||
use crate::display_map::TransformBlock;
|
||||
use clock::ReplicaId;
|
||||
use collections::{BTreeMap, HashMap};
|
||||
use gpui::{
|
||||
color::Color,
|
||||
elements::layout_highlighted_chunks,
|
||||
elements::*,
|
||||
fonts::{HighlightStyle, Underline},
|
||||
geometry::{
|
||||
rect::RectF,
|
||||
@ -649,44 +650,84 @@ impl EditorElement {
|
||||
line_layouts: &[text_layout::Line],
|
||||
cx: &mut LayoutContext,
|
||||
) -> Vec<(u32, ElementBox)> {
|
||||
Default::default()
|
||||
// snapshot
|
||||
// .blocks_in_range(rows.clone())
|
||||
// .map(|(start_row, block)| {
|
||||
// let anchor_row = block
|
||||
// .position()
|
||||
// .to_point(&snapshot.buffer_snapshot)
|
||||
// .to_display_point(snapshot)
|
||||
// .row();
|
||||
let scroll_x = snapshot.scroll_position.x();
|
||||
snapshot
|
||||
.blocks_in_range(rows.clone())
|
||||
.map(|(block_row, block)| {
|
||||
let mut element = match block {
|
||||
TransformBlock::Custom(block) => {
|
||||
let align_to = block
|
||||
.position()
|
||||
.to_point(&snapshot.buffer_snapshot)
|
||||
.to_display_point(snapshot);
|
||||
let anchor_x = text_x
|
||||
+ if rows.contains(&align_to.row()) {
|
||||
line_layouts[(align_to.row() - rows.start) as usize]
|
||||
.x_for_index(align_to.column() as usize)
|
||||
} else {
|
||||
layout_line(align_to.row(), snapshot, style, cx.text_layout_cache)
|
||||
.x_for_index(align_to.column() as usize)
|
||||
};
|
||||
|
||||
// let anchor_x = text_x
|
||||
// + if rows.contains(&anchor_row) {
|
||||
// line_layouts[(anchor_row - rows.start) as usize]
|
||||
// .x_for_index(block.column() as usize)
|
||||
// } else {
|
||||
// layout_line(anchor_row, snapshot, style, cx.text_layout_cache)
|
||||
// .x_for_index(block.column() as usize)
|
||||
// };
|
||||
block.render(&BlockContext {
|
||||
cx,
|
||||
anchor_x,
|
||||
gutter_padding,
|
||||
line_height,
|
||||
scroll_x,
|
||||
gutter_width,
|
||||
em_width,
|
||||
})
|
||||
}
|
||||
TransformBlock::ExcerptHeader { buffer, .. } => {
|
||||
let style = &self.settings.style.diagnostic_path_header;
|
||||
let font_size =
|
||||
(style.text_scale_factor * self.settings.style.text.font_size).round();
|
||||
|
||||
// let mut element = block.render(&BlockContext {
|
||||
// cx,
|
||||
// anchor_x,
|
||||
// gutter_padding,
|
||||
// line_height,
|
||||
// scroll_x: snapshot.scroll_position.x(),
|
||||
// gutter_width,
|
||||
// em_width,
|
||||
// });
|
||||
// element.layout(
|
||||
// SizeConstraint {
|
||||
// min: Vector2F::zero(),
|
||||
// max: vec2f(width, block.height() as f32 * line_height),
|
||||
// },
|
||||
// cx,
|
||||
// );
|
||||
// (start_row, element)
|
||||
// })
|
||||
// .collect()
|
||||
let mut filename = None;
|
||||
let mut parent_path = None;
|
||||
if let Some(path) = buffer.path() {
|
||||
filename = path.file_name().map(|f| f.to_string_lossy().to_string());
|
||||
parent_path =
|
||||
path.parent().map(|p| p.to_string_lossy().to_string() + "/");
|
||||
}
|
||||
|
||||
Flex::row()
|
||||
.with_child(
|
||||
Label::new(
|
||||
filename.unwrap_or_else(|| "untitled".to_string()),
|
||||
style.filename.text.clone().with_font_size(font_size),
|
||||
)
|
||||
.contained()
|
||||
.with_style(style.filename.container)
|
||||
.boxed(),
|
||||
)
|
||||
.with_children(parent_path.map(|path| {
|
||||
Label::new(path, style.path.text.clone().with_font_size(font_size))
|
||||
.contained()
|
||||
.with_style(style.path.container)
|
||||
.boxed()
|
||||
}))
|
||||
.aligned()
|
||||
.left()
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
.with_padding_left(gutter_padding + scroll_x * em_width)
|
||||
.expanded()
|
||||
.named("path header block")
|
||||
}
|
||||
};
|
||||
|
||||
element.layout(
|
||||
SizeConstraint {
|
||||
min: Vector2F::zero(),
|
||||
max: vec2f(width, block.height() as f32 * line_height),
|
||||
},
|
||||
cx,
|
||||
);
|
||||
(block_row, element)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user