From faa5d0c58d6174091253fd55820d286c23b80ab4 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 24 Jul 2024 10:12:33 +0200 Subject: Unify `Link` and `Message` generics in `text::Rich` --- examples/markdown/src/main.rs | 7 ++--- widget/src/helpers.rs | 6 ++-- widget/src/markdown.rs | 19 +++++------- widget/src/text/rich.rs | 69 +++++++++++-------------------------------- 4 files changed, 29 insertions(+), 72 deletions(-) diff --git a/examples/markdown/src/main.rs b/examples/markdown/src/main.rs index 44bf57c5..163dab66 100644 --- a/examples/markdown/src/main.rs +++ b/examples/markdown/src/main.rs @@ -64,11 +64,8 @@ impl Markdown { .padding(10) .font(Font::MONOSPACE); - let preview = markdown( - &self.items, - markdown::Settings::default(), - Message::LinkClicked, - ); + let preview = markdown(&self.items, markdown::Settings::default()) + .map(Message::LinkClicked); row![editor, scrollable(preview).spacing(10).height(Fill)] .spacing(10) diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index dcc668ca..0eb5f974 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -683,11 +683,11 @@ where /// Creates a new [`Rich`] text widget with the provided spans. /// /// [`Rich`]: text::Rich -pub fn rich_text<'a, Message, Link, Theme, Renderer>( +pub fn rich_text<'a, Link, Theme, Renderer>( spans: impl Into]>>, -) -> text::Rich<'a, Message, Link, Theme, Renderer> +) -> text::Rich<'a, Link, Theme, Renderer> where - Link: Clone, + Link: Clone + 'static, Theme: text::Catalog + 'a, Renderer: core::text::Renderer, { diff --git a/widget/src/markdown.rs b/widget/src/markdown.rs index f2b69244..0e47d35c 100644 --- a/widget/src/markdown.rs +++ b/widget/src/markdown.rs @@ -332,13 +332,11 @@ impl Default for Settings { /// Display a bunch of Markdown items. /// /// You can obtain the items with [`parse`]. -pub fn view<'a, Message, Renderer>( +pub fn view<'a, Renderer>( items: impl IntoIterator, settings: Settings, - on_link: impl Fn(Url) -> Message + Copy + 'a, -) -> Element<'a, Message, Theme, Renderer> +) -> Element<'a, Url, Theme, Renderer> where - Message: 'a, Renderer: core::text::Renderer + 'a, { let Settings { @@ -356,7 +354,7 @@ where let blocks = items.into_iter().enumerate().map(|(i, item)| match item { Item::Heading(level, heading) => { - container(rich_text(heading).on_link(on_link).size(match level { + container(rich_text(heading).size(match level { pulldown_cmark::HeadingLevel::H1 => h1_size, pulldown_cmark::HeadingLevel::H2 => h2_size, pulldown_cmark::HeadingLevel::H3 => h3_size, @@ -372,11 +370,11 @@ where .into() } Item::Paragraph(paragraph) => { - rich_text(paragraph).on_link(on_link).size(text_size).into() + rich_text(paragraph).size(text_size).into() } Item::List { start: None, items } => { column(items.iter().map(|items| { - row![text("•").size(text_size), view(items, settings, on_link)] + row![text("•").size(text_size), view(items, settings)] .spacing(spacing) .into() })) @@ -389,7 +387,7 @@ where } => column(items.iter().enumerate().map(|(i, items)| { row![ text!("{}.", i as u64 + *start).size(text_size), - view(items, settings, on_link) + view(items, settings) ] .spacing(spacing) .into() @@ -399,10 +397,7 @@ where Item::CodeBlock(code) => container( scrollable( container( - rich_text(code) - .font(Font::MONOSPACE) - .size(code_size) - .on_link(on_link), + rich_text(code).font(Font::MONOSPACE).size(code_size), ) .padding(spacing.0 / 2.0), ) diff --git a/widget/src/text/rich.rs b/widget/src/text/rich.rs index 05ad6576..9c0e2fac 100644 --- a/widget/src/text/rich.rs +++ b/widget/src/text/rich.rs @@ -17,13 +17,8 @@ use std::borrow::Cow; /// A bunch of [`Rich`] text. #[allow(missing_debug_implementations)] -pub struct Rich< - 'a, - Message, - Link = (), - Theme = crate::Theme, - Renderer = crate::Renderer, -> where +pub struct Rich<'a, Link, Theme = crate::Theme, Renderer = crate::Renderer> +where Link: Clone + 'static, Theme: Catalog, Renderer: core::text::Renderer, @@ -37,11 +32,9 @@ pub struct Rich< align_x: alignment::Horizontal, align_y: alignment::Vertical, class: Theme::Class<'a>, - on_link: Option Message + 'a>>, } -impl<'a, Message, Link, Theme, Renderer> - Rich<'a, Message, Link, Theme, Renderer> +impl<'a, Link, Theme, Renderer> Rich<'a, Link, Theme, Renderer> where Link: Clone + 'static, Theme: Catalog, @@ -59,7 +52,6 @@ where align_x: alignment::Horizontal::Left, align_y: alignment::Vertical::Top, class: Theme::default(), - on_link: None, } } @@ -155,21 +147,6 @@ where self.style(move |_theme| Style { color }) } - /// Sets the message handler for link clicks on the [`Rich`] text. - pub fn on_link(mut self, on_link: impl Fn(Link) -> Message + 'a) -> Self { - self.on_link = Some(Box::new(on_link)); - self - } - - /// Sets the message handler for link clicks on the [`Rich`] text. - pub fn on_link_maybe( - mut self, - on_link: Option Message + 'a>, - ) -> Self { - self.on_link = on_link.map(|on_link| Box::new(on_link) as _); - self - } - /// Sets the default style class of the [`Rich`] text. #[cfg(feature = "advanced")] #[must_use] @@ -188,10 +165,9 @@ where } } -impl<'a, Message, Link, Theme, Renderer> Default - for Rich<'a, Message, Link, Theme, Renderer> +impl<'a, Link, Theme, Renderer> Default for Rich<'a, Link, Theme, Renderer> where - Link: Clone + 'static, + Link: Clone + 'a, Theme: Catalog, Renderer: core::text::Renderer, { @@ -206,8 +182,8 @@ struct State { paragraph: P, } -impl<'a, Message, Link, Theme, Renderer> Widget - for Rich<'a, Message, Link, Theme, Renderer> +impl<'a, Link, Theme, Renderer> Widget + for Rich<'a, Link, Theme, Renderer> where Link: Clone + 'static, Theme: Catalog, @@ -288,13 +264,9 @@ where cursor: mouse::Cursor, _renderer: &Renderer, _clipboard: &mut dyn Clipboard, - shell: &mut Shell<'_, Message>, + shell: &mut Shell<'_, Link>, _viewport: &Rectangle, ) -> event::Status { - let Some(on_link_click) = self.on_link.as_ref() else { - return event::Status::Ignored; - }; - match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => { if let Some(position) = cursor.position_in(layout.bounds()) { @@ -326,7 +298,7 @@ where .get(span) .and_then(|span| span.link.clone()) { - shell.publish(on_link_click(link)); + shell.publish(link); } } _ => {} @@ -348,10 +320,6 @@ where _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { - if self.on_link.is_none() { - return mouse::Interaction::None; - } - if let Some(position) = cursor.position_in(layout.bounds()) { let state = tree .state @@ -436,11 +404,10 @@ where }) } -impl<'a, Message, Link, Theme, Renderer> - FromIterator> - for Rich<'a, Message, Link, Theme, Renderer> +impl<'a, Link, Theme, Renderer> FromIterator> + for Rich<'a, Link, Theme, Renderer> where - Link: Clone + 'static, + Link: Clone + 'a, Theme: Catalog, Renderer: core::text::Renderer, { @@ -454,18 +421,16 @@ where } } -impl<'a, Message, Link, Theme, Renderer> - From> - for Element<'a, Message, Theme, Renderer> +impl<'a, Link, Theme, Renderer> From> + for Element<'a, Link, Theme, Renderer> where - Message: 'a, - Link: Clone + 'static, + Link: Clone + 'a, Theme: Catalog + 'a, Renderer: core::text::Renderer + 'a, { fn from( - text: Rich<'a, Message, Link, Theme, Renderer>, - ) -> Element<'a, Message, Theme, Renderer> { + text: Rich<'a, Link, Theme, Renderer>, + ) -> Element<'a, Link, Theme, Renderer> { Element::new(text) } } -- cgit