matrix_gui/widgets/
plaintext.rs1use embedded_text::{
7 TextBox,
8 alignment::HorizontalAlignment,
9 style::{HeightMode, TextBoxStyleBuilder},
10};
11
12use crate::prelude::*;
13
14pub struct PlainText<'a, ID, COL: PixelColor> {
26 region: &'a Region<ID>,
28 text: &'a str,
30 font: OptionFont<'a>,
32 align: HorizontalAlign,
34 color: OptionColor<COL>,
36 paragraph_spacing: u8,
38 padding_inner: u8,
40 padding_outer: u8,
42 border_width: u8,
44}
45
46impl<'a, ID: WidgetId, COL: PixelColor> PlainText<'a, ID, COL> {
47 pub const fn new(region: &'a Region<ID>, text: &'a str) -> PlainText<'a, ID, COL> {
48 PlainText {
49 region,
50 text,
51 font: OptionFont::none(),
52 align: HorizontalAlign::Left,
53 color: OptionColor::none(),
54 paragraph_spacing: 0,
55 padding_inner: 0,
56 padding_outer: 0,
57 border_width: 0,
58 }
59 }
60
61 pub const fn with_font(mut self, font: UiFont<'a>) -> Self {
62 self.font.set_font(font);
63 self
64 }
65
66 pub const fn with_align(mut self, align: HorizontalAlign) -> Self {
67 self.align = align;
68 self
69 }
70
71 pub const fn with_color(mut self, color: COL) -> Self {
72 self.color.set_color(color);
73 self
74 }
75
76 pub const fn with_paragraph_spacing(mut self, paragraph_spacing: u8) -> Self {
77 self.paragraph_spacing = paragraph_spacing;
78 self
79 }
80
81 pub const fn with_padding(mut self, inner: u8, outer: u8) -> Self {
82 self.padding_inner = inner;
83 self.padding_outer = outer;
84 self
85 }
86
87 pub const fn with_border(mut self, border_width: u8) -> Self {
88 self.border_width = border_width;
89 self
90 }
91}
92
93impl<DRAW: DrawTarget<Color = COL>, ID: WidgetId, COL: PixelColor> Widget<DRAW, COL>
94 for PlainText<'_, ID, COL>
95{
96 fn draw(&mut self, ui: &mut Ui<DRAW, COL>) -> GuiResult<Response> {
97 let widget_state = ui.get_widget_state(self.region.id())?;
98 if widget_state.compare_set(RenderStatus::Rendered) {
99 return Ok(Response::Idle);
100 }
101
102 let mut area = self.region.rectangle();
103 if self.padding_outer > 0 {
104 area = area.offset(-(self.padding_outer as i32));
105 }
106 if self.border_width > 0 {
107 let rect_style = PrimitiveStyleBuilder::new()
108 .stroke_color(ui.style().border_color)
109 .stroke_width(self.border_width as u32)
110 .build();
111 ui.draw(&area.into_styled(rect_style)).ok();
112 }
113
114 area = matrix_utils::select(
115 self.padding_inner > 0,
116 area.offset(-(self.padding_inner as i32)),
117 area.offset(-(ui.style().default_padding.width as i32)),
118 );
119
120 let font = self.font.font(ui.style());
121 let color = self.color.text_color(ui.style());
122
123 let character_style = UiTextStyle::new(font, color);
124 let textbox_style = TextBoxStyleBuilder::new()
125 .height_mode(HeightMode::FitToText)
126 .alignment(self.align.into())
127 .paragraph_spacing(self.paragraph_spacing as u32)
128 .build();
129
130 let text_box = TextBox::with_textbox_style(self.text, area, character_style, textbox_style);
131
132 ui.clear_area(&area)?;
133 ui.draw(&text_box)?;
134
135 Ok(Response::Idle)
136 }
137}
138
139impl From<HorizontalAlign> for HorizontalAlignment {
140 fn from(value: HorizontalAlign) -> Self {
141 match value {
142 HorizontalAlign::Left => Self::Left,
143 HorizontalAlign::Center => Self::Center,
144 HorizontalAlign::Right => Self::Right,
145 HorizontalAlign::Justify => Self::Justified,
146 }
147 }
148}