Make RichText generic over data structure

... and decouple `markdown::parse` from theming
This commit is contained in:
Héctor Ramón Jiménez 2024-08-22 02:24:06 +02:00
parent 55764b923e
commit 4c883f12b4
No known key found for this signature in database
GPG key ID: 4C07CEC81AFA161F
7 changed files with 223 additions and 94 deletions

View file

@ -13,8 +13,6 @@ use crate::core::{
Rectangle, Shell, Size, Vector, Widget,
};
use std::borrow::Cow;
/// A bunch of [`Rich`] text.
#[allow(missing_debug_implementations)]
pub struct Rich<'a, Link, Theme = crate::Theme, Renderer = crate::Renderer>
@ -23,7 +21,7 @@ where
Theme: Catalog,
Renderer: core::text::Renderer,
{
spans: Cow<'a, [Span<'a, Link, Renderer::Font>]>,
spans: Box<dyn AsRef<[Span<'a, Link, Renderer::Font>]> + 'a>,
size: Option<Pixels>,
line_height: LineHeight,
width: Length,
@ -39,11 +37,12 @@ where
Link: Clone + 'static,
Theme: Catalog,
Renderer: core::text::Renderer,
Renderer::Font: 'a,
{
/// Creates a new empty [`Rich`] text.
pub fn new() -> Self {
Self {
spans: Cow::default(),
spans: Box::new([]),
size: None,
line_height: LineHeight::default(),
width: Length::Shrink,
@ -57,10 +56,10 @@ where
/// Creates a new [`Rich`] text with the given text spans.
pub fn with_spans(
spans: impl Into<Cow<'a, [Span<'a, Link, Renderer::Font>]>>,
spans: impl AsRef<[Span<'a, Link, Renderer::Font>]> + 'a,
) -> Self {
Self {
spans: spans.into(),
spans: Box::new(spans),
..Self::new()
}
}
@ -154,15 +153,6 @@ where
self.class = class.into();
self
}
/// Adds a new text [`Span`] to the [`Rich`] text.
pub fn push(
mut self,
span: impl Into<Span<'a, Link, Renderer::Font>>,
) -> Self {
self.spans.to_mut().push(span.into());
self
}
}
impl<'a, Link, Theme, Renderer> Default for Rich<'a, Link, Theme, Renderer>
@ -170,6 +160,7 @@ where
Link: Clone + 'a,
Theme: Catalog,
Renderer: core::text::Renderer,
Renderer::Font: 'a,
{
fn default() -> Self {
Self::new()
@ -221,7 +212,7 @@ where
limits,
self.width,
self.height,
self.spans.as_ref(),
self.spans.as_ref().as_ref(),
self.line_height,
self.size,
self.font,
@ -250,7 +241,7 @@ where
.position_in(layout.bounds())
.and_then(|position| state.paragraph.hit_span(position));
for (index, span) in self.spans.iter().enumerate() {
for (index, span) in self.spans.as_ref().as_ref().iter().enumerate() {
let is_hovered_link =
span.link.is_some() && Some(index) == hovered_span;
@ -394,6 +385,8 @@ where
Some(span) if span == span_pressed => {
if let Some(link) = self
.spans
.as_ref()
.as_ref()
.get(span)
.and_then(|span| span.link.clone())
{
@ -427,7 +420,7 @@ where
if let Some(span) = state
.paragraph
.hit_span(position)
.and_then(|span| self.spans.get(span))
.and_then(|span| self.spans.as_ref().as_ref().get(span))
{
if span.link.is_some() {
return mouse::Interaction::Pointer;
@ -509,14 +502,12 @@ where
Link: Clone + 'a,
Theme: Catalog,
Renderer: core::text::Renderer,
Renderer::Font: 'a,
{
fn from_iter<T: IntoIterator<Item = Span<'a, Link, Renderer::Font>>>(
spans: T,
) -> Self {
Self {
spans: spans.into_iter().collect(),
..Self::new()
}
Self::with_spans(spans.into_iter().collect::<Vec<_>>())
}
}