summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-07-28 15:09:54 +0200
committerLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-07-28 15:09:54 +0200
commitbf16d1ddcdcac21a4f4ad5ba79caba857067ee56 (patch)
treeddec17362b3815016aecf5b8eff68d1d06834686
parentc47a6ed7b639cf76086554fe2b65a8acecb61ea2 (diff)
downloadiced-bf16d1ddcdcac21a4f4ad5ba79caba857067ee56.tar.gz
iced-bf16d1ddcdcac21a4f4ad5ba79caba857067ee56.tar.bz2
iced-bf16d1ddcdcac21a4f4ad5ba79caba857067ee56.zip
Implement `underline` support for `rich_text` spans
-rw-r--r--core/src/text.rs10
-rw-r--r--widget/src/markdown.rs4
-rw-r--r--widget/src/text/rich.rs79
3 files changed, 71 insertions, 22 deletions
diff --git a/core/src/text.rs b/core/src/text.rs
index 2f085bd8..68c586f1 100644
--- a/core/src/text.rs
+++ b/core/src/text.rs
@@ -245,6 +245,8 @@ pub struct Span<'a, Link = (), Font = crate::Font> {
///
/// Currently, it only affects the bounds of the [`Highlight`].
pub padding: Padding,
+ /// Whether the [`Span`] should be underlined or not.
+ pub underline: bool,
}
/// A text highlight.
@@ -268,6 +270,7 @@ impl<'a, Link, Font> Span<'a, Link, Font> {
highlight: None,
link: None,
padding: Padding::ZERO,
+ underline: false,
}
}
@@ -386,6 +389,12 @@ impl<'a, Link, Font> Span<'a, Link, Font> {
self
}
+ /// Sets whether the [`Span`] shoud be underlined or not.
+ pub fn underline(mut self, underline: bool) -> Self {
+ self.underline = underline;
+ self
+ }
+
/// Turns the [`Span`] into a static one.
pub fn to_static(self) -> Span<'static, Link, Font> {
Span {
@@ -397,6 +406,7 @@ impl<'a, Link, Font> Span<'a, Link, Font> {
link: self.link,
highlight: self.highlight,
padding: self.padding,
+ underline: self.underline,
}
}
}
diff --git a/widget/src/markdown.rs b/widget/src/markdown.rs
index 9cd4a62f..dbdb6e42 100644
--- a/widget/src/markdown.rs
+++ b/widget/src/markdown.rs
@@ -248,7 +248,9 @@ pub fn parse(
};
let span = if let Some(link) = link.as_ref() {
- span.color(palette.primary).link(link.clone())
+ span.color(palette.primary)
+ .link(link.clone())
+ .underline(true)
} else {
span
};
diff --git a/widget/src/text/rich.rs b/widget/src/text/rich.rs
index 9935e6c5..8e4b0b7e 100644
--- a/widget/src/text/rich.rs
+++ b/widget/src/text/rich.rs
@@ -237,7 +237,7 @@ where
theme: &Theme,
defaults: &renderer::Style,
layout: Layout<'_>,
- _cursor_position: mouse::Cursor,
+ _cursor: mouse::Cursor,
viewport: &Rectangle,
) {
let state = tree
@@ -247,28 +247,65 @@ where
let style = theme.style(&self.class);
for (index, span) in self.spans.iter().enumerate() {
- if let Some(highlight) = span.highlight {
+ if span.highlight.is_some() || span.underline {
let translation = layout.position() - Point::ORIGIN;
+ let regions = state.paragraph.span_bounds(index);
+
+ if let Some(highlight) = span.highlight {
+ for bounds in &regions {
+ let bounds = Rectangle::new(
+ bounds.position()
+ - Vector::new(
+ span.padding.left,
+ span.padding.top,
+ ),
+ bounds.size()
+ + Size::new(
+ span.padding.horizontal(),
+ span.padding.vertical(),
+ ),
+ );
+
+ renderer.fill_quad(
+ renderer::Quad {
+ bounds: bounds + translation,
+ border: highlight.border,
+ ..Default::default()
+ },
+ highlight.background,
+ );
+ }
+ }
- for bounds in state.paragraph.span_bounds(index) {
- let bounds = Rectangle::new(
- bounds.position()
- - Vector::new(span.padding.left, span.padding.top),
- bounds.size()
- + Size::new(
- span.padding.horizontal(),
- span.padding.vertical(),
- ),
- );
-
- renderer.fill_quad(
- renderer::Quad {
- bounds: bounds + translation,
- border: highlight.border,
- ..Default::default()
- },
- highlight.background,
- );
+ if span.underline {
+ let line_height = span
+ .line_height
+ .unwrap_or(self.line_height)
+ .to_absolute(
+ span.size
+ .or(self.size)
+ .unwrap_or(renderer.default_size()),
+ );
+
+ for bounds in regions {
+ renderer.fill_quad(
+ renderer::Quad {
+ bounds: Rectangle::new(
+ bounds.position()
+ + translation
+ + Vector::new(
+ 0.0,
+ line_height.0 * 0.8 + 1.0,
+ ),
+ Size::new(bounds.width, 1.0),
+ ),
+ ..Default::default()
+ },
+ span.color
+ .or(style.color)
+ .unwrap_or(defaults.text_color),
+ );
+ }
}
}
}