Specialize widget::text helper with custom IntoContent trait

This commit is contained in:
Héctor Ramón Jiménez 2024-04-01 21:36:08 +02:00
parent c30b4b0a1c
commit 1d83e59e8a
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
5 changed files with 78 additions and 10 deletions

View file

@ -21,7 +21,7 @@ where
Theme: Catalog,
Renderer: text::Renderer,
{
content: Cow<'a, str>,
content: Content<'a>,
size: Option<Pixels>,
line_height: LineHeight,
width: Length,
@ -39,9 +39,9 @@ where
Renderer: text::Renderer,
{
/// Create a new fragment of [`Text`] with the given contents.
pub fn new(content: impl Into<Cow<'a, str>>) -> Self {
pub fn new(content: impl IntoContent<'a>) -> Self {
Text {
content: content.into(),
content: content.into_content(),
size: None,
line_height: LineHeight::default(),
font: None,
@ -366,3 +366,67 @@ impl Catalog for Theme {
class(self)
}
}
/// The content of a [`Text`] widget.
///
/// This is just an alias to a string that may be either
/// borrowed or owned.
pub type Content<'a> = Cow<'a, str>;
/// A trait for converting a value to some text [`Content`].
pub trait IntoContent<'a> {
/// Converts the value to some text [`Content`].
fn into_content(self) -> Content<'a>;
}
impl<'a> IntoContent<'a> for &'a str {
fn into_content(self) -> Content<'a> {
Content::Borrowed(self)
}
}
impl<'a> IntoContent<'a> for &'a String {
fn into_content(self) -> Content<'a> {
Content::Borrowed(self.as_str())
}
}
impl<'a> IntoContent<'a> for String {
fn into_content(self) -> Content<'a> {
Content::Owned(self)
}
}
macro_rules! into_content {
($type:ty) => {
impl<'a> IntoContent<'a> for $type {
fn into_content(self) -> Content<'a> {
Content::Owned(self.to_string())
}
}
impl<'a> IntoContent<'a> for &$type {
fn into_content(self) -> Content<'a> {
Content::Owned(self.to_string())
}
}
};
}
into_content!(char);
into_content!(bool);
into_content!(u8);
into_content!(u16);
into_content!(u32);
into_content!(u64);
into_content!(u128);
into_content!(i8);
into_content!(i16);
into_content!(i32);
into_content!(i64);
into_content!(i128);
into_content!(f32);
into_content!(f64);

View file

@ -173,7 +173,7 @@ impl App {
.style(button::danger);
row![
text(&item.name).color(item.color),
text(item.name.clone()).color(item.color),
horizontal_space(),
pick_list(Color::ALL, Some(item.color), move |color| {
Message::ItemColorChanged(item.clone(), color)

View file

@ -357,7 +357,7 @@ impl<'a> Step {
.into()
}
fn container(title: &str) -> Column<'a, StepMessage> {
fn container(title: &str) -> Column<'_, StepMessage> {
column![text(title).size(50)].spacing(20)
}
@ -589,7 +589,7 @@ impl<'a> Step {
value: &str,
is_secure: bool,
is_showing_icon: bool,
) -> Column<'a, StepMessage> {
) -> Column<'_, StepMessage> {
let mut text_input = text_input("Type something to continue...", value)
.on_input(StepMessage::InputChanged)
.padding(10)
@ -674,7 +674,7 @@ fn ferris<'a>(
.center_x()
}
fn padded_button<'a, Message: Clone>(label: &str) -> Button<'a, Message> {
fn padded_button<Message: Clone>(label: &str) -> Button<'_, Message> {
button(text(label)).padding([12, 24])
}

View file

@ -97,7 +97,11 @@ impl WebSocket {
} else {
scrollable(
column(
self.messages.iter().cloned().map(text).map(Element::from),
self.messages
.iter()
.map(ToString::to_string)
.map(text)
.map(Element::from),
)
.spacing(10),
)

View file

@ -145,13 +145,13 @@ where
///
/// [`Text`]: core::widget::Text
pub fn text<'a, Theme, Renderer>(
text: impl ToString,
text: impl text::IntoContent<'a>,
) -> Text<'a, Theme, Renderer>
where
Theme: text::Catalog + 'a,
Renderer: core::text::Renderer,
{
Text::new(text.to_string())
Text::new(text)
}
/// Creates a new [`Checkbox`].