Unify Link and Message generics in text::Rich
This commit is contained in:
parent
a8c772eb8a
commit
faa5d0c58d
4 changed files with 29 additions and 72 deletions
|
|
@ -64,11 +64,8 @@ impl Markdown {
|
||||||
.padding(10)
|
.padding(10)
|
||||||
.font(Font::MONOSPACE);
|
.font(Font::MONOSPACE);
|
||||||
|
|
||||||
let preview = markdown(
|
let preview = markdown(&self.items, markdown::Settings::default())
|
||||||
&self.items,
|
.map(Message::LinkClicked);
|
||||||
markdown::Settings::default(),
|
|
||||||
Message::LinkClicked,
|
|
||||||
);
|
|
||||||
|
|
||||||
row![editor, scrollable(preview).spacing(10).height(Fill)]
|
row![editor, scrollable(preview).spacing(10).height(Fill)]
|
||||||
.spacing(10)
|
.spacing(10)
|
||||||
|
|
|
||||||
|
|
@ -683,11 +683,11 @@ where
|
||||||
/// Creates a new [`Rich`] text widget with the provided spans.
|
/// Creates a new [`Rich`] text widget with the provided spans.
|
||||||
///
|
///
|
||||||
/// [`Rich`]: text::Rich
|
/// [`Rich`]: text::Rich
|
||||||
pub fn rich_text<'a, Message, Link, Theme, Renderer>(
|
pub fn rich_text<'a, Link, Theme, Renderer>(
|
||||||
spans: impl Into<Cow<'a, [text::Span<'a, Link, Renderer::Font>]>>,
|
spans: impl Into<Cow<'a, [text::Span<'a, Link, Renderer::Font>]>>,
|
||||||
) -> text::Rich<'a, Message, Link, Theme, Renderer>
|
) -> text::Rich<'a, Link, Theme, Renderer>
|
||||||
where
|
where
|
||||||
Link: Clone,
|
Link: Clone + 'static,
|
||||||
Theme: text::Catalog + 'a,
|
Theme: text::Catalog + 'a,
|
||||||
Renderer: core::text::Renderer,
|
Renderer: core::text::Renderer,
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -332,13 +332,11 @@ impl Default for Settings {
|
||||||
/// Display a bunch of Markdown items.
|
/// Display a bunch of Markdown items.
|
||||||
///
|
///
|
||||||
/// You can obtain the items with [`parse`].
|
/// You can obtain the items with [`parse`].
|
||||||
pub fn view<'a, Message, Renderer>(
|
pub fn view<'a, Renderer>(
|
||||||
items: impl IntoIterator<Item = &'a Item>,
|
items: impl IntoIterator<Item = &'a Item>,
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
on_link: impl Fn(Url) -> Message + Copy + 'a,
|
) -> Element<'a, Url, Theme, Renderer>
|
||||||
) -> Element<'a, Message, Theme, Renderer>
|
|
||||||
where
|
where
|
||||||
Message: 'a,
|
|
||||||
Renderer: core::text::Renderer<Font = Font> + 'a,
|
Renderer: core::text::Renderer<Font = Font> + 'a,
|
||||||
{
|
{
|
||||||
let Settings {
|
let Settings {
|
||||||
|
|
@ -356,7 +354,7 @@ where
|
||||||
|
|
||||||
let blocks = items.into_iter().enumerate().map(|(i, item)| match item {
|
let blocks = items.into_iter().enumerate().map(|(i, item)| match item {
|
||||||
Item::Heading(level, heading) => {
|
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::H1 => h1_size,
|
||||||
pulldown_cmark::HeadingLevel::H2 => h2_size,
|
pulldown_cmark::HeadingLevel::H2 => h2_size,
|
||||||
pulldown_cmark::HeadingLevel::H3 => h3_size,
|
pulldown_cmark::HeadingLevel::H3 => h3_size,
|
||||||
|
|
@ -372,11 +370,11 @@ where
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
Item::Paragraph(paragraph) => {
|
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 } => {
|
Item::List { start: None, items } => {
|
||||||
column(items.iter().map(|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)
|
.spacing(spacing)
|
||||||
.into()
|
.into()
|
||||||
}))
|
}))
|
||||||
|
|
@ -389,7 +387,7 @@ where
|
||||||
} => column(items.iter().enumerate().map(|(i, items)| {
|
} => column(items.iter().enumerate().map(|(i, items)| {
|
||||||
row![
|
row![
|
||||||
text!("{}.", i as u64 + *start).size(text_size),
|
text!("{}.", i as u64 + *start).size(text_size),
|
||||||
view(items, settings, on_link)
|
view(items, settings)
|
||||||
]
|
]
|
||||||
.spacing(spacing)
|
.spacing(spacing)
|
||||||
.into()
|
.into()
|
||||||
|
|
@ -399,10 +397,7 @@ where
|
||||||
Item::CodeBlock(code) => container(
|
Item::CodeBlock(code) => container(
|
||||||
scrollable(
|
scrollable(
|
||||||
container(
|
container(
|
||||||
rich_text(code)
|
rich_text(code).font(Font::MONOSPACE).size(code_size),
|
||||||
.font(Font::MONOSPACE)
|
|
||||||
.size(code_size)
|
|
||||||
.on_link(on_link),
|
|
||||||
)
|
)
|
||||||
.padding(spacing.0 / 2.0),
|
.padding(spacing.0 / 2.0),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,8 @@ use std::borrow::Cow;
|
||||||
|
|
||||||
/// A bunch of [`Rich`] text.
|
/// A bunch of [`Rich`] text.
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct Rich<
|
pub struct Rich<'a, Link, Theme = crate::Theme, Renderer = crate::Renderer>
|
||||||
'a,
|
where
|
||||||
Message,
|
|
||||||
Link = (),
|
|
||||||
Theme = crate::Theme,
|
|
||||||
Renderer = crate::Renderer,
|
|
||||||
> where
|
|
||||||
Link: Clone + 'static,
|
Link: Clone + 'static,
|
||||||
Theme: Catalog,
|
Theme: Catalog,
|
||||||
Renderer: core::text::Renderer,
|
Renderer: core::text::Renderer,
|
||||||
|
|
@ -37,11 +32,9 @@ pub struct Rich<
|
||||||
align_x: alignment::Horizontal,
|
align_x: alignment::Horizontal,
|
||||||
align_y: alignment::Vertical,
|
align_y: alignment::Vertical,
|
||||||
class: Theme::Class<'a>,
|
class: Theme::Class<'a>,
|
||||||
on_link: Option<Box<dyn Fn(Link) -> Message + 'a>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Message, Link, Theme, Renderer>
|
impl<'a, Link, Theme, Renderer> Rich<'a, Link, Theme, Renderer>
|
||||||
Rich<'a, Message, Link, Theme, Renderer>
|
|
||||||
where
|
where
|
||||||
Link: Clone + 'static,
|
Link: Clone + 'static,
|
||||||
Theme: Catalog,
|
Theme: Catalog,
|
||||||
|
|
@ -59,7 +52,6 @@ where
|
||||||
align_x: alignment::Horizontal::Left,
|
align_x: alignment::Horizontal::Left,
|
||||||
align_y: alignment::Vertical::Top,
|
align_y: alignment::Vertical::Top,
|
||||||
class: Theme::default(),
|
class: Theme::default(),
|
||||||
on_link: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,21 +147,6 @@ where
|
||||||
self.style(move |_theme| Style { color })
|
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<impl Fn(Link) -> 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.
|
/// Sets the default style class of the [`Rich`] text.
|
||||||
#[cfg(feature = "advanced")]
|
#[cfg(feature = "advanced")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
|
@ -188,10 +165,9 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Message, Link, Theme, Renderer> Default
|
impl<'a, Link, Theme, Renderer> Default for Rich<'a, Link, Theme, Renderer>
|
||||||
for Rich<'a, Message, Link, Theme, Renderer>
|
|
||||||
where
|
where
|
||||||
Link: Clone + 'static,
|
Link: Clone + 'a,
|
||||||
Theme: Catalog,
|
Theme: Catalog,
|
||||||
Renderer: core::text::Renderer,
|
Renderer: core::text::Renderer,
|
||||||
{
|
{
|
||||||
|
|
@ -206,8 +182,8 @@ struct State<Link, P: Paragraph> {
|
||||||
paragraph: P,
|
paragraph: P,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Message, Link, Theme, Renderer> Widget<Message, Theme, Renderer>
|
impl<'a, Link, Theme, Renderer> Widget<Link, Theme, Renderer>
|
||||||
for Rich<'a, Message, Link, Theme, Renderer>
|
for Rich<'a, Link, Theme, Renderer>
|
||||||
where
|
where
|
||||||
Link: Clone + 'static,
|
Link: Clone + 'static,
|
||||||
Theme: Catalog,
|
Theme: Catalog,
|
||||||
|
|
@ -288,13 +264,9 @@ where
|
||||||
cursor: mouse::Cursor,
|
cursor: mouse::Cursor,
|
||||||
_renderer: &Renderer,
|
_renderer: &Renderer,
|
||||||
_clipboard: &mut dyn Clipboard,
|
_clipboard: &mut dyn Clipboard,
|
||||||
shell: &mut Shell<'_, Message>,
|
shell: &mut Shell<'_, Link>,
|
||||||
_viewport: &Rectangle,
|
_viewport: &Rectangle,
|
||||||
) -> event::Status {
|
) -> event::Status {
|
||||||
let Some(on_link_click) = self.on_link.as_ref() else {
|
|
||||||
return event::Status::Ignored;
|
|
||||||
};
|
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => {
|
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => {
|
||||||
if let Some(position) = cursor.position_in(layout.bounds()) {
|
if let Some(position) = cursor.position_in(layout.bounds()) {
|
||||||
|
|
@ -326,7 +298,7 @@ where
|
||||||
.get(span)
|
.get(span)
|
||||||
.and_then(|span| span.link.clone())
|
.and_then(|span| span.link.clone())
|
||||||
{
|
{
|
||||||
shell.publish(on_link_click(link));
|
shell.publish(link);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
@ -348,10 +320,6 @@ where
|
||||||
_viewport: &Rectangle,
|
_viewport: &Rectangle,
|
||||||
_renderer: &Renderer,
|
_renderer: &Renderer,
|
||||||
) -> mouse::Interaction {
|
) -> mouse::Interaction {
|
||||||
if self.on_link.is_none() {
|
|
||||||
return mouse::Interaction::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(position) = cursor.position_in(layout.bounds()) {
|
if let Some(position) = cursor.position_in(layout.bounds()) {
|
||||||
let state = tree
|
let state = tree
|
||||||
.state
|
.state
|
||||||
|
|
@ -436,11 +404,10 @@ where
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Message, Link, Theme, Renderer>
|
impl<'a, Link, Theme, Renderer> FromIterator<Span<'a, Link, Renderer::Font>>
|
||||||
FromIterator<Span<'a, Link, Renderer::Font>>
|
for Rich<'a, Link, Theme, Renderer>
|
||||||
for Rich<'a, Message, Link, Theme, Renderer>
|
|
||||||
where
|
where
|
||||||
Link: Clone + 'static,
|
Link: Clone + 'a,
|
||||||
Theme: Catalog,
|
Theme: Catalog,
|
||||||
Renderer: core::text::Renderer,
|
Renderer: core::text::Renderer,
|
||||||
{
|
{
|
||||||
|
|
@ -454,18 +421,16 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Message, Link, Theme, Renderer>
|
impl<'a, Link, Theme, Renderer> From<Rich<'a, Link, Theme, Renderer>>
|
||||||
From<Rich<'a, Message, Link, Theme, Renderer>>
|
for Element<'a, Link, Theme, Renderer>
|
||||||
for Element<'a, Message, Theme, Renderer>
|
|
||||||
where
|
where
|
||||||
Message: 'a,
|
Link: Clone + 'a,
|
||||||
Link: Clone + 'static,
|
|
||||||
Theme: Catalog + 'a,
|
Theme: Catalog + 'a,
|
||||||
Renderer: core::text::Renderer + 'a,
|
Renderer: core::text::Renderer + 'a,
|
||||||
{
|
{
|
||||||
fn from(
|
fn from(
|
||||||
text: Rich<'a, Message, Link, Theme, Renderer>,
|
text: Rich<'a, Link, Theme, Renderer>,
|
||||||
) -> Element<'a, Message, Theme, Renderer> {
|
) -> Element<'a, Link, Theme, Renderer> {
|
||||||
Element::new(text)
|
Element::new(text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue