use std::borrow::Borrow; use iced::{font, widget::container, Font}; use crate::{impl_focusable, style::*}; #[derive(Clone, Debug, PartialEq)] pub struct Text { pub content: String, align: Alignment, colour: Option, font_style: font::Style, overflow_strategy: OverflowStrategy, size: Option, strength: Option, width: iced::Length, is_focused: bool, } #[derive(Clone, Debug, PartialEq)] enum Alignment { Left, Right, } #[derive(Clone, Debug, PartialEq)] enum Colour { Danger, Primary, Highlight, } #[derive(Clone, Debug, PartialEq)] enum OverflowStrategy { Grow, Clip, } #[derive(Clone, Debug, PartialEq)] enum Strength { Base, Weak, } #[derive(Clone, Debug, PartialEq)] enum Size { VSmall, Small, Base, } impl Text { pub fn default(content: &str) -> Self { Self { align: Alignment::Left, content: String::from(content), colour: Some(Colour::Primary), font_style: font::Style::Normal, overflow_strategy: OverflowStrategy::Grow, size: Some(Size::Base), strength: Some(Strength::Base), is_focused: false, width: iced::Length::Shrink, } } pub fn new(content: &str) -> Self { Self { align: Alignment::Left, content: String::from(content), colour: None, font_style: font::Style::Normal, overflow_strategy: OverflowStrategy::Grow, size: None, strength: None, width: iced::Length::Shrink, is_focused: false, } } pub fn currency(amount: i32) -> Self { let formatted_string = if amount < 0 { format!("({} · {})", -amount / 100, -amount % 100) } else { format!(" {} · {} ", amount / 100, amount % 100) }; Self::default(&formatted_string) } pub fn as_element<'a, Message>(self) -> iced::Element<'a, Message> where Message: 'a, { >>::into(self) } pub fn v_small(&self) -> Self { Self { size: Some(Size::VSmall), ..self.clone() } } pub fn small(&self) -> Self { Self { size: Some(Size::Small), ..self.clone() } } pub fn danger(&self) -> Self { Self { colour: Some(Colour::Danger), ..self.clone() } } pub fn weak(&self) -> Self { Self { strength: Some(Strength::Weak), ..self.clone() } } pub fn highlight_maybe(&self, do_highlight: bool) -> Self { if do_highlight { Self { colour: Some(Colour::Highlight), ..self.clone() } } else { self.clone() } } pub fn align_right(&self) -> Self { Self { align: Alignment::Right, ..self.clone() } } pub fn width(&self, width: iced::Length) -> Self { Self { width, ..self.clone() } } pub fn clip(&self) -> Self { Self { overflow_strategy: OverflowStrategy::Clip, ..self.clone() } } pub fn italic(&self) -> Self { Self { font_style: font::Style::Italic, ..self.clone() } } } impl<'a, Message> From for iced::Element<'a, Message> where Message: 'a, { fn from(text: Text) -> Self { text_as_element(text) } } impl<'a, Message> From<&'a Text> for iced::Element<'a, Message> where Message: 'a, { fn from(text: &'a Text) -> Self { text_as_element(text) } } fn text_as_element<'a, T, Message>(text: T) -> iced::Element<'a, Message> where T: Borrow + 'a, Message: 'a, { let overflow_strategy = &text.borrow().overflow_strategy.clone(); let text_elem: iced::widget::Text = iced::widget::text(text.borrow().content.clone()) .font(Font { style: text.borrow().font_style, ..Default::default() }) .size(match text.borrow().size { Some(Size::VSmall) => u32::from(TEXT_SIZE_V_SM), Some(Size::Small) => u32::from(TEXT_SIZE_SM), Some(Size::Base) | None => u32::from(TEXT_SIZE_BASE), }) .align_x(match &text.borrow().align { Alignment::Left => iced::alignment::Horizontal::Left, Alignment::Right => iced::alignment::Horizontal::Right, }) .wrapping(match overflow_strategy { OverflowStrategy::Grow => iced::widget::text::Wrapping::default(), OverflowStrategy::Clip => iced::widget::text::Wrapping::None, }) .width(text.borrow().width) .style(move |theme: &iced::Theme| iced::widget::text::Style { color: match (&text.borrow().colour, &text.borrow().strength) { (Some(Colour::Danger), Some(Strength::Base) | None) => { Some(theme.extended_palette().danger.base.text) } (Some(Colour::Danger), Some(Strength::Weak)) => { Some(theme.extended_palette().danger.weak.text) } (Some(Colour::Primary), Some(Strength::Base) | None) => { Some(theme.extended_palette().primary.base.text) } (Some(Colour::Primary), Some(Strength::Weak)) => { Some(theme.extended_palette().primary.weak.text) } (Some(Colour::Highlight), Some(Strength::Base) | None) => { Some(theme.extended_palette().primary.base.color) } (Some(Colour::Highlight), Some(Strength::Weak)) => { Some(theme.extended_palette().primary.weak.color) } (None, _) => None, }, }); match overflow_strategy { OverflowStrategy::Grow => text_elem.into(), OverflowStrategy::Clip => container::<'a, Message, _, _>(text_elem) .height(iced::Length::Shrink) .clip(true) .into(), } } impl_focusable!(Text);