mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-27 12:54:42 +00:00
Start work on generalizing the BlockMap to allow arbitrary elements
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
e668ff8bcd
commit
0c714210ff
7 changed files with 579 additions and 897 deletions
|
@ -3,13 +3,12 @@ mod fold_map;
|
|||
mod tab_map;
|
||||
mod wrap_map;
|
||||
|
||||
pub use block_map::{BlockDisposition, BlockId, BlockProperties, BufferRows, Chunks};
|
||||
pub use block_map::{
|
||||
AlignedBlock, BlockContext, BlockDisposition, BlockId, BlockProperties, BufferRows, Chunks,
|
||||
};
|
||||
use block_map::{BlockMap, BlockPoint};
|
||||
use fold_map::{FoldMap, ToFoldPoint as _};
|
||||
use gpui::{
|
||||
fonts::{FontId, HighlightStyle},
|
||||
AppContext, Entity, ModelContext, ModelHandle,
|
||||
};
|
||||
use gpui::{fonts::FontId, ElementBox, Entity, ModelContext, ModelHandle};
|
||||
use language::{Anchor, Buffer, Point, Subscription as BufferSubscription, ToOffset, ToPoint};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
|
@ -17,8 +16,7 @@ use std::{
|
|||
};
|
||||
use sum_tree::Bias;
|
||||
use tab_map::TabMap;
|
||||
use text::Rope;
|
||||
use theme::{BlockStyle, SyntaxTheme};
|
||||
use theme::SyntaxTheme;
|
||||
use wrap_map::WrapMap;
|
||||
|
||||
pub trait ToDisplayPoint {
|
||||
|
@ -124,14 +122,13 @@ impl DisplayMap {
|
|||
self.block_map.read(snapshot, edits, cx);
|
||||
}
|
||||
|
||||
pub fn insert_blocks<P, T>(
|
||||
pub fn insert_blocks<P>(
|
||||
&mut self,
|
||||
blocks: impl IntoIterator<Item = BlockProperties<P, T>>,
|
||||
blocks: impl IntoIterator<Item = BlockProperties<P>>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Vec<BlockId>
|
||||
where
|
||||
P: ToOffset + Clone,
|
||||
T: Into<Rope> + Clone,
|
||||
{
|
||||
let snapshot = self.buffer.read(cx).snapshot();
|
||||
let edits = self.buffer_subscription.consume().into_inner();
|
||||
|
@ -144,12 +141,11 @@ impl DisplayMap {
|
|||
block_map.insert(blocks, cx)
|
||||
}
|
||||
|
||||
pub fn restyle_blocks<F1, F2>(&mut self, styles: HashMap<BlockId, (Option<F1>, Option<F2>)>)
|
||||
pub fn replace_blocks<F>(&mut self, styles: HashMap<BlockId, F>)
|
||||
where
|
||||
F1: 'static + Fn(&AppContext) -> Vec<(usize, HighlightStyle)>,
|
||||
F2: 'static + Fn(&AppContext) -> BlockStyle,
|
||||
F: 'static + Fn(&BlockContext) -> ElementBox,
|
||||
{
|
||||
self.block_map.restyle(styles);
|
||||
self.block_map.replace(styles);
|
||||
}
|
||||
|
||||
pub fn remove_blocks(&mut self, ids: HashSet<BlockId>, cx: &mut ModelContext<Self>) {
|
||||
|
@ -198,8 +194,8 @@ impl DisplayMapSnapshot {
|
|||
self.buffer_snapshot.len() == 0
|
||||
}
|
||||
|
||||
pub fn buffer_rows<'a>(&'a self, start_row: u32, cx: Option<&'a AppContext>) -> BufferRows<'a> {
|
||||
self.blocks_snapshot.buffer_rows(start_row, cx)
|
||||
pub fn buffer_rows<'a>(&'a self, start_row: u32) -> BufferRows<'a> {
|
||||
self.blocks_snapshot.buffer_rows(start_row)
|
||||
}
|
||||
|
||||
pub fn buffer_row_count(&self) -> u32 {
|
||||
|
@ -256,7 +252,7 @@ impl DisplayMapSnapshot {
|
|||
|
||||
pub fn text_chunks(&self, display_row: u32) -> impl Iterator<Item = &str> {
|
||||
self.blocks_snapshot
|
||||
.chunks(display_row..self.max_point().row() + 1, None, None)
|
||||
.chunks(display_row..self.max_point().row() + 1, None)
|
||||
.map(|h| h.text)
|
||||
}
|
||||
|
||||
|
@ -264,9 +260,8 @@ impl DisplayMapSnapshot {
|
|||
&'a self,
|
||||
display_rows: Range<u32>,
|
||||
theme: Option<&'a SyntaxTheme>,
|
||||
cx: &'a AppContext,
|
||||
) -> block_map::Chunks<'a> {
|
||||
self.blocks_snapshot.chunks(display_rows, theme, Some(cx))
|
||||
self.blocks_snapshot.chunks(display_rows, theme)
|
||||
}
|
||||
|
||||
pub fn chars_at<'a>(&'a self, point: DisplayPoint) -> impl Iterator<Item = char> + 'a {
|
||||
|
@ -322,6 +317,13 @@ impl DisplayMapSnapshot {
|
|||
self.folds_snapshot.folds_in_range(range)
|
||||
}
|
||||
|
||||
pub fn blocks_in_range<'a>(
|
||||
&'a self,
|
||||
rows: Range<u32>,
|
||||
) -> impl Iterator<Item = (u32, &'a AlignedBlock)> {
|
||||
self.blocks_snapshot.blocks_in_range(rows)
|
||||
}
|
||||
|
||||
pub fn intersects_fold<T: ToOffset>(&self, offset: T) -> bool {
|
||||
self.folds_snapshot.intersects_fold(offset)
|
||||
}
|
||||
|
@ -448,13 +450,6 @@ impl ToDisplayPoint for Anchor {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum DisplayRow {
|
||||
Buffer(u32),
|
||||
Block(BlockId, Option<BlockStyle>),
|
||||
Wrap,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -1065,7 +1060,7 @@ mod tests {
|
|||
) -> Vec<(String, Option<Color>)> {
|
||||
let snapshot = map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut chunks: Vec<(String, Option<Color>)> = Vec::new();
|
||||
for chunk in snapshot.chunks(rows, Some(theme), cx) {
|
||||
for chunk in snapshot.chunks(rows, Some(theme)) {
|
||||
let color = chunk.highlight_style.map(|s| s.color);
|
||||
if let Some((last_chunk, last_color)) = chunks.last_mut() {
|
||||
if color == *last_color {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,6 @@
|
|||
use super::{
|
||||
fold_map,
|
||||
tab_map::{self, Edit as TabEdit, Snapshot as TabSnapshot, TabPoint},
|
||||
DisplayRow,
|
||||
};
|
||||
use gpui::{
|
||||
fonts::FontId, text_layout::LineWrapper, Entity, ModelContext, ModelHandle, MutableAppContext,
|
||||
|
@ -607,13 +606,6 @@ impl Snapshot {
|
|||
len as u32
|
||||
}
|
||||
|
||||
pub fn line_char_count(&self, row: u32) -> u32 {
|
||||
self.text_chunks(row)
|
||||
.flat_map(|c| c.chars())
|
||||
.take_while(|c| *c != '\n')
|
||||
.count() as u32
|
||||
}
|
||||
|
||||
pub fn soft_wrap_indent(&self, row: u32) -> Option<u32> {
|
||||
let mut cursor = self.transforms.cursor::<WrapPoint>();
|
||||
cursor.seek(&WrapPoint::new(row + 1, 0), Bias::Right, &());
|
||||
|
@ -719,11 +711,7 @@ impl Snapshot {
|
|||
prev_tab_row = tab_point.row();
|
||||
soft_wrapped = false;
|
||||
}
|
||||
expected_buffer_rows.push(if soft_wrapped {
|
||||
DisplayRow::Wrap
|
||||
} else {
|
||||
DisplayRow::Buffer(buffer_row)
|
||||
});
|
||||
expected_buffer_rows.push(if soft_wrapped { None } else { Some(buffer_row) });
|
||||
}
|
||||
|
||||
for start_display_row in 0..expected_buffer_rows.len() {
|
||||
|
@ -803,7 +791,7 @@ impl<'a> Iterator for Chunks<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Iterator for BufferRows<'a> {
|
||||
type Item = DisplayRow;
|
||||
type Item = Option<u32>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.output_row > self.max_output_row {
|
||||
|
@ -823,11 +811,7 @@ impl<'a> Iterator for BufferRows<'a> {
|
|||
self.soft_wrapped = true;
|
||||
}
|
||||
|
||||
Some(if soft_wrapped {
|
||||
DisplayRow::Wrap
|
||||
} else {
|
||||
DisplayRow::Buffer(buffer_row)
|
||||
})
|
||||
Some(if soft_wrapped { None } else { Some(buffer_row) })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,11 +8,12 @@ mod test;
|
|||
|
||||
use aho_corasick::AhoCorasick;
|
||||
use clock::ReplicaId;
|
||||
pub use display_map::DisplayPoint;
|
||||
use display_map::*;
|
||||
pub use display_map::{DisplayPoint, DisplayRow};
|
||||
pub use element::*;
|
||||
use gpui::{
|
||||
action,
|
||||
elements::Text,
|
||||
geometry::vector::{vec2f, Vector2F},
|
||||
keymap::Binding,
|
||||
text_layout, AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle,
|
||||
|
@ -28,14 +29,14 @@ use std::{
|
|||
cmp,
|
||||
collections::HashMap,
|
||||
iter, mem,
|
||||
ops::{Range, RangeInclusive},
|
||||
ops::{Deref, Range, RangeInclusive},
|
||||
rc::Rc,
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
};
|
||||
use sum_tree::Bias;
|
||||
use text::rope::TextDimension;
|
||||
use theme::{DiagnosticStyle, EditorStyle, SyntaxTheme};
|
||||
use theme::{DiagnosticStyle, EditorStyle};
|
||||
use util::post_inc;
|
||||
use workspace::{EntryOpener, Workspace};
|
||||
|
||||
|
@ -2877,35 +2878,16 @@ impl Editor {
|
|||
active_diagnostics.is_valid = is_valid;
|
||||
let mut new_styles = HashMap::new();
|
||||
for (block_id, diagnostic) in &active_diagnostics.blocks {
|
||||
let severity = diagnostic.severity;
|
||||
let message_len = diagnostic.message.len();
|
||||
new_styles.insert(
|
||||
*block_id,
|
||||
(
|
||||
Some({
|
||||
let build_settings = self.build_settings.clone();
|
||||
move |cx: &AppContext| {
|
||||
let settings = build_settings.borrow()(cx);
|
||||
vec![(
|
||||
message_len,
|
||||
diagnostic_style(severity, is_valid, &settings.style)
|
||||
.text
|
||||
.into(),
|
||||
)]
|
||||
}
|
||||
}),
|
||||
Some({
|
||||
let build_settings = self.build_settings.clone();
|
||||
move |cx: &AppContext| {
|
||||
let settings = build_settings.borrow()(cx);
|
||||
diagnostic_style(severity, is_valid, &settings.style).block
|
||||
}
|
||||
}),
|
||||
),
|
||||
);
|
||||
let build_settings = self.build_settings.clone();
|
||||
let diagnostic = diagnostic.clone();
|
||||
new_styles.insert(*block_id, move |cx: &BlockContext| {
|
||||
let diagnostic = diagnostic.clone();
|
||||
let settings = build_settings.borrow()(cx.cx);
|
||||
render_diagnostic(diagnostic, &settings.style)
|
||||
});
|
||||
}
|
||||
self.display_map
|
||||
.update(cx, |display_map, _| display_map.restyle_blocks(new_styles));
|
||||
.update(cx, |display_map, _| display_map.replace_blocks(new_styles));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2940,30 +2922,17 @@ impl Editor {
|
|||
.insert_blocks(
|
||||
diagnostic_group.iter().map(|(range, diagnostic)| {
|
||||
let build_settings = self.build_settings.clone();
|
||||
let message_len = diagnostic.message.len();
|
||||
let severity = diagnostic.severity;
|
||||
let diagnostic = diagnostic.clone();
|
||||
let message_height = diagnostic.message.lines().count() as u8;
|
||||
|
||||
BlockProperties {
|
||||
position: range.start,
|
||||
text: diagnostic.message.as_str(),
|
||||
build_runs: Some(Arc::new({
|
||||
let build_settings = build_settings.clone();
|
||||
move |cx| {
|
||||
let settings = build_settings.borrow()(cx);
|
||||
vec![(
|
||||
message_len,
|
||||
diagnostic_style(severity, true, &settings.style)
|
||||
.text
|
||||
.into(),
|
||||
)]
|
||||
}
|
||||
})),
|
||||
build_style: Some(Arc::new({
|
||||
let build_settings = build_settings.clone();
|
||||
move |cx| {
|
||||
let settings = build_settings.borrow()(cx);
|
||||
diagnostic_style(severity, true, &settings.style).block
|
||||
}
|
||||
})),
|
||||
height: message_height,
|
||||
render: Arc::new(move |cx| {
|
||||
let settings = build_settings.borrow()(cx.cx);
|
||||
let diagnostic = diagnostic.clone();
|
||||
render_diagnostic(diagnostic, &settings.style)
|
||||
}),
|
||||
disposition: BlockDisposition::Below,
|
||||
}
|
||||
}),
|
||||
|
@ -3482,10 +3451,6 @@ impl Editor {
|
|||
}
|
||||
|
||||
impl Snapshot {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.display_snapshot.is_empty()
|
||||
}
|
||||
|
||||
pub fn is_focused(&self) -> bool {
|
||||
self.is_focused
|
||||
}
|
||||
|
@ -3494,23 +3459,6 @@ impl Snapshot {
|
|||
self.placeholder_text.as_ref()
|
||||
}
|
||||
|
||||
pub fn buffer_row_count(&self) -> u32 {
|
||||
self.display_snapshot.buffer_row_count()
|
||||
}
|
||||
|
||||
pub fn buffer_rows<'a>(&'a self, start_row: u32, cx: &'a AppContext) -> BufferRows<'a> {
|
||||
self.display_snapshot.buffer_rows(start_row, Some(cx))
|
||||
}
|
||||
|
||||
pub fn chunks<'a>(
|
||||
&'a self,
|
||||
display_rows: Range<u32>,
|
||||
theme: Option<&'a SyntaxTheme>,
|
||||
cx: &'a AppContext,
|
||||
) -> display_map::Chunks<'a> {
|
||||
self.display_snapshot.chunks(display_rows, theme, cx)
|
||||
}
|
||||
|
||||
pub fn scroll_position(&self) -> Vector2F {
|
||||
compute_scroll_position(
|
||||
&self.display_snapshot,
|
||||
|
@ -3518,29 +3466,13 @@ impl Snapshot {
|
|||
&self.scroll_top_anchor,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max_point(&self) -> DisplayPoint {
|
||||
self.display_snapshot.max_point()
|
||||
}
|
||||
impl Deref for Snapshot {
|
||||
type Target = DisplayMapSnapshot;
|
||||
|
||||
pub fn longest_row(&self) -> u32 {
|
||||
self.display_snapshot.longest_row()
|
||||
}
|
||||
|
||||
pub fn line_len(&self, display_row: u32) -> u32 {
|
||||
self.display_snapshot.line_len(display_row)
|
||||
}
|
||||
|
||||
pub fn line(&self, display_row: u32) -> String {
|
||||
self.display_snapshot.line(display_row)
|
||||
}
|
||||
|
||||
pub fn prev_row_boundary(&self, point: DisplayPoint) -> (DisplayPoint, Point) {
|
||||
self.display_snapshot.prev_row_boundary(point)
|
||||
}
|
||||
|
||||
pub fn next_row_boundary(&self, point: DisplayPoint) -> (DisplayPoint, Point) {
|
||||
self.display_snapshot.next_row_boundary(point)
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.display_snapshot
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3709,6 +3641,12 @@ impl SelectionExt for Selection<Point> {
|
|||
}
|
||||
}
|
||||
|
||||
fn render_diagnostic(diagnostic: Diagnostic, style: &EditorStyle) -> ElementBox {
|
||||
let mut text_style = style.text.clone();
|
||||
text_style.color = diagnostic_style(diagnostic.severity, true, &style).text;
|
||||
Text::new(diagnostic.message, text_style).boxed()
|
||||
}
|
||||
|
||||
pub fn diagnostic_style(
|
||||
severity: DiagnosticSeverity,
|
||||
valid: bool,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use crate::display_map::BlockContext;
|
||||
|
||||
use super::{
|
||||
DisplayPoint, DisplayRow, Editor, EditorMode, EditorSettings, EditorStyle, Input, Scroll,
|
||||
Select, SelectPhase, Snapshot, SoftWrap, MAX_LINE_LEN,
|
||||
DisplayPoint, Editor, EditorMode, EditorSettings, EditorStyle, Input, Scroll, Select,
|
||||
SelectPhase, Snapshot, SoftWrap, MAX_LINE_LEN,
|
||||
};
|
||||
use clock::ReplicaId;
|
||||
use gpui::{
|
||||
|
@ -13,7 +15,7 @@ use gpui::{
|
|||
json::{self, ToJson},
|
||||
keymap::Keystroke,
|
||||
text_layout::{self, RunStyle, TextLayoutCache},
|
||||
AppContext, Axis, Border, Element, Event, EventContext, FontCache, LayoutContext,
|
||||
AppContext, Axis, Border, Element, ElementBox, Event, EventContext, FontCache, LayoutContext,
|
||||
MutableAppContext, PaintContext, Quad, Scene, SizeConstraint, ViewContext, WeakViewHandle,
|
||||
};
|
||||
use json::json;
|
||||
|
@ -25,7 +27,6 @@ use std::{
|
|||
fmt::Write,
|
||||
ops::Range,
|
||||
};
|
||||
use theme::BlockStyle;
|
||||
|
||||
pub struct EditorElement {
|
||||
view: WeakViewHandle<Editor>,
|
||||
|
@ -278,51 +279,6 @@ impl EditorElement {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Draw block backgrounds
|
||||
for (ixs, block_style) in &layout.block_layouts {
|
||||
let row = start_row + ixs.start;
|
||||
let offset = vec2f(0., row as f32 * layout.line_height - scroll_top);
|
||||
let height = ixs.len() as f32 * layout.line_height;
|
||||
cx.scene.push_quad(Quad {
|
||||
bounds: RectF::new(
|
||||
text_bounds.origin() + offset,
|
||||
vec2f(text_bounds.width(), height),
|
||||
),
|
||||
background: block_style.background,
|
||||
border: block_style
|
||||
.border
|
||||
.map_or(Default::default(), |color| Border {
|
||||
width: 1.,
|
||||
color,
|
||||
overlay: true,
|
||||
top: true,
|
||||
right: false,
|
||||
bottom: true,
|
||||
left: false,
|
||||
}),
|
||||
corner_radius: 0.,
|
||||
});
|
||||
cx.scene.push_quad(Quad {
|
||||
bounds: RectF::new(
|
||||
gutter_bounds.origin() + offset,
|
||||
vec2f(gutter_bounds.width(), height),
|
||||
),
|
||||
background: block_style.gutter_background,
|
||||
border: block_style
|
||||
.gutter_border
|
||||
.map_or(Default::default(), |color| Border {
|
||||
width: 1.,
|
||||
color,
|
||||
overlay: true,
|
||||
top: true,
|
||||
right: false,
|
||||
bottom: true,
|
||||
left: false,
|
||||
}),
|
||||
corner_radius: 0.,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn paint_gutter(
|
||||
|
@ -461,6 +417,18 @@ impl EditorElement {
|
|||
cx.scene.pop_layer();
|
||||
}
|
||||
|
||||
fn paint_blocks(
|
||||
&mut self,
|
||||
bounds: RectF,
|
||||
visible_bounds: RectF,
|
||||
layout: &LayoutState,
|
||||
cx: &mut PaintContext,
|
||||
) {
|
||||
for (row_range, block) in &layout.blocks {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
fn max_line_number_width(&self, snapshot: &Snapshot, cx: &LayoutContext) -> f32 {
|
||||
let digit_count = (snapshot.buffer_row_count() as f32).log10().floor() as usize + 1;
|
||||
let style = &self.settings.style;
|
||||
|
@ -487,18 +455,13 @@ impl EditorElement {
|
|||
active_rows: &BTreeMap<u32, bool>,
|
||||
snapshot: &Snapshot,
|
||||
cx: &LayoutContext,
|
||||
) -> (
|
||||
Vec<Option<text_layout::Line>>,
|
||||
Vec<(Range<u32>, BlockStyle)>,
|
||||
) {
|
||||
) -> Vec<Option<text_layout::Line>> {
|
||||
let style = &self.settings.style;
|
||||
let include_line_numbers = snapshot.mode == EditorMode::Full;
|
||||
let mut last_block_id = None;
|
||||
let mut blocks = Vec::<(Range<u32>, BlockStyle)>::new();
|
||||
let mut line_number_layouts = Vec::with_capacity(rows.len());
|
||||
let mut line_number = String::new();
|
||||
for (ix, row) in snapshot
|
||||
.buffer_rows(rows.start, cx)
|
||||
.buffer_rows(rows.start)
|
||||
.take((rows.end - rows.start) as usize)
|
||||
.enumerate()
|
||||
{
|
||||
|
@ -508,46 +471,29 @@ impl EditorElement {
|
|||
} else {
|
||||
style.line_number
|
||||
};
|
||||
match row {
|
||||
DisplayRow::Buffer(buffer_row) => {
|
||||
if include_line_numbers {
|
||||
line_number.clear();
|
||||
write!(&mut line_number, "{}", buffer_row + 1).unwrap();
|
||||
line_number_layouts.push(Some(cx.text_layout_cache.layout_str(
|
||||
&line_number,
|
||||
style.text.font_size,
|
||||
&[(
|
||||
line_number.len(),
|
||||
RunStyle {
|
||||
font_id: style.text.font_id,
|
||||
color,
|
||||
underline: None,
|
||||
},
|
||||
)],
|
||||
)));
|
||||
}
|
||||
last_block_id = None;
|
||||
}
|
||||
DisplayRow::Block(block_id, style) => {
|
||||
let ix = ix as u32;
|
||||
if last_block_id == Some(block_id) {
|
||||
if let Some((row_range, _)) = blocks.last_mut() {
|
||||
row_range.end += 1;
|
||||
}
|
||||
} else if let Some(style) = style {
|
||||
blocks.push((ix..ix + 1, style));
|
||||
}
|
||||
line_number_layouts.push(None);
|
||||
last_block_id = Some(block_id);
|
||||
}
|
||||
DisplayRow::Wrap => {
|
||||
line_number_layouts.push(None);
|
||||
last_block_id = None;
|
||||
if let Some(buffer_row) = row {
|
||||
if include_line_numbers {
|
||||
line_number.clear();
|
||||
write!(&mut line_number, "{}", buffer_row + 1).unwrap();
|
||||
line_number_layouts.push(Some(cx.text_layout_cache.layout_str(
|
||||
&line_number,
|
||||
style.text.font_size,
|
||||
&[(
|
||||
line_number.len(),
|
||||
RunStyle {
|
||||
font_id: style.text.font_id,
|
||||
color,
|
||||
underline: None,
|
||||
},
|
||||
)],
|
||||
)));
|
||||
}
|
||||
} else {
|
||||
line_number_layouts.push(None);
|
||||
}
|
||||
}
|
||||
|
||||
(line_number_layouts, blocks)
|
||||
line_number_layouts
|
||||
}
|
||||
|
||||
fn layout_lines(
|
||||
|
@ -598,7 +544,7 @@ impl EditorElement {
|
|||
let mut styles = Vec::new();
|
||||
let mut row = rows.start;
|
||||
let mut line_exceeded_max_len = false;
|
||||
let chunks = snapshot.chunks(rows.clone(), Some(&style.syntax), cx);
|
||||
let chunks = snapshot.chunks(rows.clone(), Some(&style.syntax));
|
||||
|
||||
let newline_chunk = Chunk {
|
||||
text: "\n",
|
||||
|
@ -668,6 +614,27 @@ impl EditorElement {
|
|||
|
||||
layouts
|
||||
}
|
||||
|
||||
fn layout_blocks(
|
||||
&mut self,
|
||||
rows: Range<u32>,
|
||||
snapshot: &Snapshot,
|
||||
cx: &LayoutContext,
|
||||
) -> Vec<(Range<u32>, ElementBox)> {
|
||||
snapshot
|
||||
.blocks_in_range(rows)
|
||||
.map(|(start_row, block)| {
|
||||
(
|
||||
start_row..start_row + block.height(),
|
||||
block.render(&BlockContext {
|
||||
cx,
|
||||
gutter_width: 0.0,
|
||||
anchor_x: 0.0,
|
||||
}),
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl Element for EditorElement {
|
||||
|
@ -773,8 +740,7 @@ impl Element for EditorElement {
|
|||
}
|
||||
});
|
||||
|
||||
let (line_number_layouts, block_layouts) =
|
||||
self.layout_rows(start_row..end_row, &active_rows, &snapshot, cx);
|
||||
let line_number_layouts = self.layout_rows(start_row..end_row, &active_rows, &snapshot, cx);
|
||||
|
||||
let mut max_visible_line_width = 0.0;
|
||||
let line_layouts = self.layout_lines(start_row..end_row, &mut snapshot, cx);
|
||||
|
@ -784,6 +750,8 @@ impl Element for EditorElement {
|
|||
}
|
||||
}
|
||||
|
||||
let blocks = self.layout_blocks(start_row..end_row, &snapshot, cx);
|
||||
|
||||
let mut layout = LayoutState {
|
||||
size,
|
||||
gutter_size,
|
||||
|
@ -797,7 +765,7 @@ impl Element for EditorElement {
|
|||
highlighted_row,
|
||||
line_layouts,
|
||||
line_number_layouts,
|
||||
block_layouts,
|
||||
blocks,
|
||||
line_height,
|
||||
em_width,
|
||||
em_advance,
|
||||
|
@ -853,6 +821,7 @@ impl Element for EditorElement {
|
|||
self.paint_gutter(gutter_bounds, visible_bounds, layout, cx);
|
||||
}
|
||||
self.paint_text(text_bounds, visible_bounds, layout, cx);
|
||||
self.paint_blocks(text_bounds, visible_bounds, layout, cx);
|
||||
|
||||
cx.scene.pop_layer();
|
||||
|
||||
|
@ -927,7 +896,7 @@ pub struct LayoutState {
|
|||
highlighted_row: Option<u32>,
|
||||
line_layouts: Vec<text_layout::Line>,
|
||||
line_number_layouts: Vec<Option<text_layout::Line>>,
|
||||
block_layouts: Vec<(Range<u32>, BlockStyle)>,
|
||||
blocks: Vec<(Range<u32>, ElementBox)>,
|
||||
line_height: f32,
|
||||
em_width: f32,
|
||||
em_advance: f32,
|
||||
|
@ -1185,7 +1154,7 @@ mod tests {
|
|||
});
|
||||
let element = EditorElement::new(editor.downgrade(), settings);
|
||||
|
||||
let (layouts, _) = editor.update(cx, |editor, cx| {
|
||||
let layouts = editor.update(cx, |editor, cx| {
|
||||
let snapshot = editor.snapshot(cx);
|
||||
let mut presenter = cx.build_presenter(window_id, 30.);
|
||||
let mut layout_cx = presenter.build_layout_context(false, cx);
|
||||
|
|
|
@ -301,6 +301,10 @@ impl<T: Element> Default for Lifecycle<T> {
|
|||
}
|
||||
|
||||
impl ElementBox {
|
||||
pub fn name(&self) -> Option<&str> {
|
||||
self.0.name.as_deref()
|
||||
}
|
||||
|
||||
pub fn metadata<T: 'static>(&self) -> Option<&T> {
|
||||
let element = unsafe { &*self.0.element.as_ptr() };
|
||||
element.metadata().and_then(|m| m.downcast_ref())
|
||||
|
|
|
@ -253,8 +253,6 @@ pub struct EditorStyle {
|
|||
#[derive(Copy, Clone, Deserialize, Default)]
|
||||
pub struct DiagnosticStyle {
|
||||
pub text: Color,
|
||||
#[serde(flatten)]
|
||||
pub block: BlockStyle,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default, Deserialize)]
|
||||
|
@ -273,14 +271,6 @@ pub struct InputEditorStyle {
|
|||
pub selection: SelectionStyle,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Eq)]
|
||||
pub struct BlockStyle {
|
||||
pub background: Option<Color>,
|
||||
pub border: Option<Color>,
|
||||
pub gutter_background: Option<Color>,
|
||||
pub gutter_border: Option<Color>,
|
||||
}
|
||||
|
||||
impl EditorStyle {
|
||||
pub fn placeholder_text(&self) -> &TextStyle {
|
||||
self.placeholder_text.as_ref().unwrap_or(&self.text)
|
||||
|
|
Loading…
Reference in a new issue