Allow providing a background color in a TextRun
This commit is contained in:
@@ -196,7 +196,10 @@ impl TextSystem {
|
||||
let mut decoration_runs = SmallVec::<[DecorationRun; 32]>::new();
|
||||
for run in runs {
|
||||
if let Some(last_run) = decoration_runs.last_mut() {
|
||||
if last_run.color == run.color && last_run.underline == run.underline {
|
||||
if last_run.color == run.color
|
||||
&& last_run.underline == run.underline
|
||||
&& last_run.background_color == run.background_color
|
||||
{
|
||||
last_run.len += run.len as u32;
|
||||
continue;
|
||||
}
|
||||
@@ -204,6 +207,7 @@ impl TextSystem {
|
||||
decoration_runs.push(DecorationRun {
|
||||
len: run.len as u32,
|
||||
color: run.color,
|
||||
background_color: run.background_color,
|
||||
underline: run.underline.clone(),
|
||||
});
|
||||
}
|
||||
@@ -254,13 +258,16 @@ impl TextSystem {
|
||||
}
|
||||
|
||||
if decoration_runs.last().map_or(false, |last_run| {
|
||||
last_run.color == run.color && last_run.underline == run.underline
|
||||
last_run.color == run.color
|
||||
&& last_run.underline == run.underline
|
||||
&& last_run.background_color == run.background_color
|
||||
}) {
|
||||
decoration_runs.last_mut().unwrap().len += run_len_within_line as u32;
|
||||
} else {
|
||||
decoration_runs.push(DecorationRun {
|
||||
len: run_len_within_line as u32,
|
||||
color: run.color,
|
||||
background_color: run.background_color,
|
||||
underline: run.underline.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
black, point, px, BorrowWindow, Bounds, Hsla, LineLayout, Pixels, Point, Result, SharedString,
|
||||
UnderlineStyle, WindowContext, WrapBoundary, WrappedLineLayout,
|
||||
black, point, px, size, transparent_black, BorrowWindow, Bounds, Corners, Edges, Hsla,
|
||||
LineLayout, Pixels, Point, Result, SharedString, UnderlineStyle, WindowContext, WrapBoundary,
|
||||
WrappedLineLayout,
|
||||
};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use smallvec::SmallVec;
|
||||
@@ -10,6 +11,7 @@ use std::sync::Arc;
|
||||
pub struct DecorationRun {
|
||||
pub len: u32,
|
||||
pub color: Hsla,
|
||||
pub background_color: Option<Hsla>,
|
||||
pub underline: Option<UnderlineStyle>,
|
||||
}
|
||||
|
||||
@@ -97,6 +99,7 @@ fn paint_line(
|
||||
let mut run_end = 0;
|
||||
let mut color = black();
|
||||
let mut current_underline: Option<(Point<Pixels>, UnderlineStyle)> = None;
|
||||
let mut current_background: Option<(Point<Pixels>, Hsla)> = None;
|
||||
let text_system = cx.text_system().clone();
|
||||
let mut glyph_origin = origin;
|
||||
let mut prev_glyph_position = Point::default();
|
||||
@@ -110,12 +113,24 @@ fn paint_line(
|
||||
|
||||
if wraps.peek() == Some(&&WrapBoundary { run_ix, glyph_ix }) {
|
||||
wraps.next();
|
||||
if let Some((background_origin, background_color)) = current_background.take() {
|
||||
cx.paint_quad(
|
||||
Bounds {
|
||||
origin: background_origin,
|
||||
size: size(glyph_origin.x - background_origin.x, line_height),
|
||||
},
|
||||
Corners::default(),
|
||||
background_color,
|
||||
Edges::default(),
|
||||
transparent_black(),
|
||||
);
|
||||
}
|
||||
if let Some((underline_origin, underline_style)) = current_underline.take() {
|
||||
cx.paint_underline(
|
||||
underline_origin,
|
||||
glyph_origin.x - underline_origin.x,
|
||||
&underline_style,
|
||||
)?;
|
||||
);
|
||||
}
|
||||
|
||||
glyph_origin.x = origin.x;
|
||||
@@ -123,9 +138,20 @@ fn paint_line(
|
||||
}
|
||||
prev_glyph_position = glyph.position;
|
||||
|
||||
let mut finished_background: Option<(Point<Pixels>, Hsla)> = None;
|
||||
let mut finished_underline: Option<(Point<Pixels>, UnderlineStyle)> = None;
|
||||
if glyph.index >= run_end {
|
||||
if let Some(style_run) = decoration_runs.next() {
|
||||
if let Some((_, background_color)) = &mut current_background {
|
||||
if style_run.background_color.as_ref() != Some(background_color) {
|
||||
finished_background = current_background.take();
|
||||
}
|
||||
}
|
||||
if let Some(run_background) = style_run.background_color {
|
||||
current_background
|
||||
.get_or_insert((point(glyph_origin.x, origin.y), run_background));
|
||||
}
|
||||
|
||||
if let Some((_, underline_style)) = &mut current_underline {
|
||||
if style_run.underline.as_ref() != Some(underline_style) {
|
||||
finished_underline = current_underline.take();
|
||||
@@ -149,16 +175,30 @@ fn paint_line(
|
||||
color = style_run.color;
|
||||
} else {
|
||||
run_end = layout.len;
|
||||
finished_background = current_background.take();
|
||||
finished_underline = current_underline.take();
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((background_origin, background_color)) = finished_background {
|
||||
cx.paint_quad(
|
||||
Bounds {
|
||||
origin: background_origin,
|
||||
size: size(glyph_origin.x - background_origin.x, line_height),
|
||||
},
|
||||
Corners::default(),
|
||||
background_color,
|
||||
Edges::default(),
|
||||
transparent_black(),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some((underline_origin, underline_style)) = finished_underline {
|
||||
cx.paint_underline(
|
||||
underline_origin,
|
||||
glyph_origin.x - underline_origin.x,
|
||||
&underline_style,
|
||||
)?;
|
||||
);
|
||||
}
|
||||
|
||||
let max_glyph_bounds = Bounds {
|
||||
@@ -188,13 +228,27 @@ fn paint_line(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((background_origin, background_color)) = current_background.take() {
|
||||
let line_end_x = origin.x + wrap_width.unwrap_or(Pixels::MAX).min(layout.width);
|
||||
cx.paint_quad(
|
||||
Bounds {
|
||||
origin: background_origin,
|
||||
size: size(line_end_x - background_origin.x, line_height),
|
||||
},
|
||||
Corners::default(),
|
||||
background_color,
|
||||
Edges::default(),
|
||||
transparent_black(),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some((underline_start, underline_style)) = current_underline.take() {
|
||||
let line_end_x = origin.x + wrap_width.unwrap_or(Pixels::MAX).min(layout.width);
|
||||
cx.paint_underline(
|
||||
underline_start,
|
||||
line_end_x - underline_start.x,
|
||||
&underline_style,
|
||||
)?;
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -881,7 +881,7 @@ impl<'a> WindowContext<'a> {
|
||||
origin: Point<Pixels>,
|
||||
width: Pixels,
|
||||
style: &UnderlineStyle,
|
||||
) -> Result<()> {
|
||||
) {
|
||||
let scale_factor = self.scale_factor();
|
||||
let height = if style.wavy {
|
||||
style.thickness * 3.
|
||||
@@ -905,7 +905,6 @@ impl<'a> WindowContext<'a> {
|
||||
wavy: style.wavy,
|
||||
},
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Paint a monochrome (non-emoji) glyph into the scene for the current frame at the current z-index.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use gpui::{
|
||||
blue, div, red, white, Div, InteractiveText, ParentElement, Render, Styled, StyledText, View,
|
||||
VisualContext, WindowContext,
|
||||
blue, div, green, red, white, Div, InteractiveText, ParentElement, Render, Styled, StyledText,
|
||||
TextRun, View, VisualContext, WindowContext,
|
||||
};
|
||||
use ui::v_stack;
|
||||
|
||||
@@ -56,6 +56,21 @@ impl Render for TextStory {
|
||||
"flex-row. width 96. The quick brown fox jumps over the lazy dog. ",
|
||||
"Meanwhile, the lazy dog decided it was time for a change. ",
|
||||
"He started daily workout routines, ate healthier and became the fastest dog in town.",
|
||||
))).child(InteractiveText::new("interactive", StyledText::new("Hello world, how is it going?")).on_click(vec![2..4], |event, cx| {dbg!(event);}))
|
||||
))).child(
|
||||
InteractiveText::new(
|
||||
"interactive",
|
||||
StyledText::new("Hello world, how is it going?").with_runs(vec![
|
||||
cx.text_style().to_run(6),
|
||||
TextRun {
|
||||
background_color: Some(green()),
|
||||
..cx.text_style().to_run(5)
|
||||
},
|
||||
cx.text_style().to_run(18),
|
||||
]),
|
||||
)
|
||||
.on_click(vec![2..4, 1..3, 7..9], |range_ix, cx| {
|
||||
println!("Clicked range {range_ix}");
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user