summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-07-28 17:45:11 +0200
committerLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-07-28 17:45:11 +0200
commitca8ebb16a67095260e4e94109f82d3ac1603e927 (patch)
tree0abbc20c913a1c002dbcb6af4e9291ead567a17c
parentebc6c0eba86608dbd9912ab180f48ca603f20c19 (diff)
downloadiced-ca8ebb16a67095260e4e94109f82d3ac1603e927.tar.gz
iced-ca8ebb16a67095260e4e94109f82d3ac1603e927.tar.bz2
iced-ca8ebb16a67095260e4e94109f82d3ac1603e927.zip
Implement `strikethrough` support for `rich_text` spans
-rw-r--r--core/src/text.rs10
-rw-r--r--widget/src/markdown.rs23
-rw-r--r--widget/src/text/rich.rs68
3 files changed, 73 insertions, 28 deletions
diff --git a/core/src/text.rs b/core/src/text.rs
index 68c586f1..436fee9a 100644
--- a/core/src/text.rs
+++ b/core/src/text.rs
@@ -247,6 +247,8 @@ pub struct Span<'a, Link = (), Font = crate::Font> {
pub padding: Padding,
/// Whether the [`Span`] should be underlined or not.
pub underline: bool,
+ /// Whether the [`Span`] should be struck through or not.
+ pub strikethrough: bool,
}
/// A text highlight.
@@ -271,6 +273,7 @@ impl<'a, Link, Font> Span<'a, Link, Font> {
link: None,
padding: Padding::ZERO,
underline: false,
+ strikethrough: false,
}
}
@@ -395,6 +398,12 @@ impl<'a, Link, Font> Span<'a, Link, Font> {
self
}
+ /// Sets whether the [`Span`] shoud be struck through or not.
+ pub fn strikethrough(mut self, strikethrough: bool) -> Self {
+ self.strikethrough = strikethrough;
+ self
+ }
+
/// Turns the [`Span`] into a static one.
pub fn to_static(self) -> Span<'static, Link, Font> {
Span {
@@ -407,6 +416,7 @@ impl<'a, Link, Font> Span<'a, Link, Font> {
highlight: self.highlight,
padding: self.padding,
underline: self.underline,
+ strikethrough: self.strikethrough,
}
}
}
diff --git a/widget/src/markdown.rs b/widget/src/markdown.rs
index 9cd4a62f..23e36435 100644
--- a/widget/src/markdown.rs
+++ b/widget/src/markdown.rs
@@ -47,6 +47,7 @@ pub fn parse(
let mut spans = Vec::new();
let mut strong = false;
let mut emphasis = false;
+ let mut strikethrough = false;
let mut metadata = false;
let mut table = false;
let mut link = None;
@@ -59,7 +60,8 @@ pub fn parse(
markdown,
pulldown_cmark::Options::ENABLE_YAML_STYLE_METADATA_BLOCKS
| pulldown_cmark::Options::ENABLE_PLUSES_DELIMITED_METADATA_BLOCKS
- | pulldown_cmark::Options::ENABLE_TABLES,
+ | pulldown_cmark::Options::ENABLE_TABLES
+ | pulldown_cmark::Options::ENABLE_STRIKETHROUGH,
);
let produce = |lists: &mut Vec<List>, item| {
@@ -90,6 +92,10 @@ pub fn parse(
emphasis = true;
None
}
+ pulldown_cmark::Tag::Strikethrough if !metadata && !table => {
+ strikethrough = true;
+ None
+ }
pulldown_cmark::Tag::Link { dest_url, .. }
if !metadata && !table =>
{
@@ -155,12 +161,16 @@ pub fn parse(
Item::Heading(level, spans.drain(..).collect()),
)
}
+ pulldown_cmark::TagEnd::Strong if !metadata && !table => {
+ strong = false;
+ None
+ }
pulldown_cmark::TagEnd::Emphasis if !metadata && !table => {
emphasis = false;
None
}
- pulldown_cmark::TagEnd::Strong if !metadata && !table => {
- strong = false;
+ pulldown_cmark::TagEnd::Strikethrough if !metadata && !table => {
+ strikethrough = false;
None
}
pulldown_cmark::TagEnd::Link if !metadata && !table => {
@@ -227,7 +237,7 @@ pub fn parse(
return None;
}
- let span = span(text.into_string());
+ let span = span(text.into_string()).strikethrough(strikethrough);
let span = if strong || emphasis {
span.font(Font {
@@ -263,7 +273,8 @@ pub fn parse(
.color(Color::WHITE)
.background(color!(0x111111))
.border(border::rounded(2))
- .padding(padding::left(2).right(2));
+ .padding(padding::left(2).right(2))
+ .strikethrough(strikethrough);
let span = if let Some(link) = link.as_ref() {
span.color(palette.primary).link(link.clone())
@@ -275,7 +286,7 @@ pub fn parse(
None
}
pulldown_cmark::Event::SoftBreak if !metadata && !table => {
- spans.push(span(" "));
+ spans.push(span(" ").strikethrough(strikethrough));
None
}
pulldown_cmark::Event::HardBreak if !metadata && !table => {
diff --git a/widget/src/text/rich.rs b/widget/src/text/rich.rs
index 096056d4..c6aa1e14 100644
--- a/widget/src/text/rich.rs
+++ b/widget/src/text/rich.rs
@@ -254,7 +254,11 @@ where
let is_hovered_link =
span.link.is_some() && Some(index) == hovered_span;
- if span.highlight.is_some() || span.underline || is_hovered_link {
+ if span.highlight.is_some()
+ || span.underline
+ || span.strikethrough
+ || is_hovered_link
+ {
let translation = layout.position() - Point::ORIGIN;
let regions = state.paragraph.span_bounds(index);
@@ -284,7 +288,7 @@ where
}
}
- if span.underline || is_hovered_link {
+ if span.underline || span.strikethrough || is_hovered_link {
let size = span
.size
.or(self.size)
@@ -295,27 +299,47 @@ where
.unwrap_or(self.line_height)
.to_absolute(size);
- for bounds in regions {
- renderer.fill_quad(
- renderer::Quad {
- bounds: Rectangle::new(
- bounds.position()
- + translation
- + Vector::new(
- 0.0,
- size.0
- + (line_height.0 - size.0)
- / 2.0
- - size.0 * 0.08,
- ),
- Size::new(bounds.width, 1.0),
- ),
- ..Default::default()
- },
- span.color
- .or(style.color)
- .unwrap_or(defaults.text_color),
+ let color = span
+ .color
+ .or(style.color)
+ .unwrap_or(defaults.text_color);
+
+ let baseline = translation
+ + Vector::new(
+ 0.0,
+ size.0 + (line_height.0 - size.0) / 2.0,
);
+
+ if span.underline || is_hovered_link {
+ for bounds in &regions {
+ renderer.fill_quad(
+ renderer::Quad {
+ bounds: Rectangle::new(
+ bounds.position() + baseline
+ - Vector::new(0.0, size.0 * 0.08),
+ Size::new(bounds.width, 1.0),
+ ),
+ ..Default::default()
+ },
+ color,
+ );
+ }
+ }
+
+ if span.strikethrough {
+ for bounds in &regions {
+ renderer.fill_quad(
+ renderer::Quad {
+ bounds: Rectangle::new(
+ bounds.position() + baseline
+ - Vector::new(0.0, size.0 / 2.0),
+ Size::new(bounds.width, 1.0),
+ ),
+ ..Default::default()
+ },
+ color,
+ );
+ }
}
}
}