Skip to main content

ferroui_controls/documents/
text_element.rs

1use super::IInlineHost;
2use crate::{Border, Control};
3use ferroui_base::media::{
4    Brushes, FontFamily, FontFeatureCollection, FontStretch, FontStyle, FontWeight, IBrush,
5};
6use ferroui_base::{
7    ferro_class, ferro_property, AttachedProperty, FerroObjectImpl, FerroObjectImplExt, FerroProperty,
8    FerroPropertyChangedEventArgs, StyledElement, StyledElementImpl, StyledProperty, StyledPropertyOptions,
9};
10use std::cell::RefCell;
11use std::rc::Rc;
12
13/// `TextElement` is the base class for content in text based controls.
14/// It also defines the inherited font and foreground attached properties
15/// used by every control that displays text.
16///
17/// This class is abstract.
18#[repr(C)]
19pub struct TextElement {
20    base: StyledElement,
21    inline_host: RefCell<Option<Rc<dyn IInlineHost>>>,
22}
23
24ferro_class! {
25    TextElement: StyledElement, virtuals TextElementImpl: StyledElementImpl {
26        /// Called when the host of the element changes.
27        #[doc(hidden)]
28        fn on_inline_host_changed(this, old_value: Option<&Rc<dyn IInlineHost>>, new_value: Option<&Rc<dyn IInlineHost>>);
29    }
30}
31
32ferroui_base::ferro_impl_classes!(TextElement: StyledElementImpl);
33
34impl FerroObjectImpl for TextElement {
35    fn on_property_changed(this: &Self, change: &FerroPropertyChangedEventArgs<'_>) {
36        Self::parent_on_property_changed(this, change);
37
38        match change.property().name() {
39            "Background" | "FontFamily" | "FontSize" | "FontStyle" | "FontWeight" | "FontStretch"
40            | "Foreground" => {
41                if let Some(host) = this.inline_host() {
42                    host.invalidate();
43                }
44            }
45            _ => {}
46        }
47    }
48}
49
50impl TextElementImpl for TextElement {
51    fn on_inline_host_changed(
52        _this: &Self,
53        _old_value: Option<&Rc<dyn IInlineHost>>,
54        _new_value: Option<&Rc<dyn IInlineHost>>,
55    ) {
56    }
57}
58
59ferroui_base::ferro_properties! { impl TextElement {
60    ferro_property!(
61        /// Defines the `Background` property.
62        pub fn background_property() -> StyledProperty<Option<Rc<dyn IBrush>>> {
63            Border::background_property().add_owner::<TextElement>()
64        }
65    );
66
67    ferro_property!(
68        /// Defines the `FontFamily` property.
69        pub fn font_family_property() -> AttachedProperty<FontFamily> {
70            FerroProperty::register_attached_with::<TextElement, TextElement, _>(
71                "FontFamily",
72                StyledPropertyOptions::new(FontFamily::default_family()).inherits(true),
73            )
74        }
75    );
76
77    ferro_property!(
78        /// Defines the `FontFeatures` property.
79        pub fn font_features_property() -> AttachedProperty<Option<FontFeatureCollection>> {
80            FerroProperty::register_attached_with::<TextElement, TextElement, _>(
81                "FontFeatures",
82                StyledPropertyOptions::new(None).inherits(true),
83            )
84        }
85    );
86
87    ferro_property!(
88        /// Defines the `FontSize` property.
89        pub fn font_size_property() -> AttachedProperty<f64> {
90            FerroProperty::register_attached_with::<TextElement, TextElement, _>(
91                "FontSize",
92                StyledPropertyOptions::new(12.0)
93                    .inherits(true)
94                    .validate(|font_size: &f64| *font_size > 0.0 && !font_size.is_nan() && !font_size.is_infinite()),
95            )
96        }
97    );
98
99    ferro_property!(
100        /// Defines the `FontStyle` property.
101        pub fn font_style_property() -> AttachedProperty<FontStyle> {
102            FerroProperty::register_attached_with::<TextElement, TextElement, _>(
103                "FontStyle",
104                StyledPropertyOptions::new(FontStyle::default()).inherits(true),
105            )
106        }
107    );
108
109    ferro_property!(
110        /// Defines the `FontWeight` property.
111        pub fn font_weight_property() -> AttachedProperty<FontWeight> {
112            FerroProperty::register_attached_with::<TextElement, TextElement, _>(
113                "FontWeight",
114                StyledPropertyOptions::new(FontWeight::Normal).inherits(true),
115            )
116        }
117    );
118
119    ferro_property!(
120        /// Defines the `FontStretch` property.
121        pub fn font_stretch_property() -> AttachedProperty<FontStretch> {
122            FerroProperty::register_attached_with::<TextElement, TextElement, _>(
123                "FontStretch",
124                StyledPropertyOptions::new(FontStretch::Normal).inherits(true),
125            )
126        }
127    );
128
129    ferro_property!(
130        /// Defines the `Foreground` property.
131        pub fn foreground_property() -> AttachedProperty<Option<Rc<dyn IBrush>>> {
132            FerroProperty::register_attached_with::<TextElement, TextElement, _>(
133                "Foreground",
134                StyledPropertyOptions::new(Some(Brushes::black() as Rc<dyn IBrush>)).inherits(true),
135            )
136        }
137    );
138
139    ferro_property!(
140        /// Defines the `LetterSpacing` property.
141        pub fn letter_spacing_property() -> AttachedProperty<f64> {
142            FerroProperty::register_attached_with::<TextElement, Control, _>(
143                "LetterSpacing",
144                StyledPropertyOptions::new(0.0).inherits(true),
145            )
146        }
147    );
148} }
149
150impl TextElement {
151    /// Creates the class data; see [`ferroui_base::FerroObject::construct`].
152    pub fn construct() -> Self {
153        Self { base: StyledElement::construct(), inline_host: RefCell::new(None) }
154    }
155
156    /// A brush used to paint the control's background.
157    pub fn background(&self) -> Option<Rc<dyn IBrush>> {
158        self.get_value(Self::background_property())
159    }
160
161    pub fn set_background(&self, value: Option<Rc<dyn IBrush>>) {
162        self.set_value(Self::background_property(), value)
163    }
164
165    /// The font family.
166    pub fn font_family(&self) -> FontFamily {
167        self.get_value(Self::font_family_property())
168    }
169
170    pub fn set_font_family(&self, value: FontFamily) {
171        self.set_value(Self::font_family_property(), value)
172    }
173
174    /// The font features.
175    pub fn font_features(&self) -> Option<FontFeatureCollection> {
176        self.get_value(Self::font_features_property())
177    }
178
179    pub fn set_font_features(&self, value: Option<FontFeatureCollection>) {
180        self.set_value(Self::font_features_property(), value)
181    }
182
183    /// The font size.
184    pub fn font_size(&self) -> f64 {
185        self.get_value(Self::font_size_property())
186    }
187
188    pub fn set_font_size(&self, value: f64) {
189        self.set_value(Self::font_size_property(), value)
190    }
191
192    /// The font style.
193    pub fn font_style(&self) -> FontStyle {
194        self.get_value(Self::font_style_property())
195    }
196
197    pub fn set_font_style(&self, value: FontStyle) {
198        self.set_value(Self::font_style_property(), value)
199    }
200
201    /// The font weight.
202    pub fn font_weight(&self) -> FontWeight {
203        self.get_value(Self::font_weight_property())
204    }
205
206    pub fn set_font_weight(&self, value: FontWeight) {
207        self.set_value(Self::font_weight_property(), value)
208    }
209
210    /// The font stretch.
211    pub fn font_stretch(&self) -> FontStretch {
212        self.get_value(Self::font_stretch_property())
213    }
214
215    pub fn set_font_stretch(&self, value: FontStretch) {
216        self.set_value(Self::font_stretch_property(), value)
217    }
218
219    /// A brush used to paint the text.
220    pub fn foreground(&self) -> Option<Rc<dyn IBrush>> {
221        self.get_value(Self::foreground_property())
222    }
223
224    pub fn set_foreground(&self, value: Option<Rc<dyn IBrush>>) {
225        self.set_value(Self::foreground_property(), value)
226    }
227
228    /// The letter spacing.
229    pub fn letter_spacing(&self) -> f64 {
230        self.get_value(Self::letter_spacing_property())
231    }
232
233    pub fn set_letter_spacing(&self, value: f64) {
234        self.set_value(Self::letter_spacing_property(), value)
235    }
236
237    /// Gets the value of the attached `FontFamily` property on a control.
238    pub fn get_font_family(control: &Control) -> FontFamily {
239        control.get_value(Self::font_family_property())
240    }
241
242    /// Sets the value of the attached `FontFamily` property on a control.
243    pub fn set_font_family_on(control: &Control, value: FontFamily) {
244        control.set_value(Self::font_family_property(), value)
245    }
246
247    /// Gets the value of the attached `FontFeatures` property on a control.
248    pub fn get_font_features(control: &Control) -> Option<FontFeatureCollection> {
249        control.get_value(Self::font_features_property())
250    }
251
252    /// Sets the value of the attached `FontFeatures` property on a control.
253    pub fn set_font_features_on(control: &Control, value: Option<FontFeatureCollection>) {
254        control.set_value(Self::font_features_property(), value)
255    }
256
257    /// Gets the value of the attached `LetterSpacing` property on a control.
258    pub fn get_letter_spacing(control: &Control) -> f64 {
259        control.get_value(Self::letter_spacing_property())
260    }
261
262    /// Sets the value of the attached `LetterSpacing` property on a control.
263    pub fn set_letter_spacing_on(control: &Control, value: f64) {
264        control.set_value(Self::letter_spacing_property(), value)
265    }
266
267    /// Gets the value of the attached `FontSize` property on a control.
268    pub fn get_font_size(control: &Control) -> f64 {
269        control.get_value(Self::font_size_property())
270    }
271
272    /// Sets the value of the attached `FontSize` property on a control.
273    pub fn set_font_size_on(control: &Control, value: f64) {
274        control.set_value(Self::font_size_property(), value)
275    }
276
277    /// Gets the value of the attached `FontStyle` property on a control.
278    pub fn get_font_style(control: &Control) -> FontStyle {
279        control.get_value(Self::font_style_property())
280    }
281
282    /// Sets the value of the attached `FontStyle` property on a control.
283    pub fn set_font_style_on(control: &Control, value: FontStyle) {
284        control.set_value(Self::font_style_property(), value)
285    }
286
287    /// Gets the value of the attached `FontWeight` property on a control.
288    pub fn get_font_weight(control: &Control) -> FontWeight {
289        control.get_value(Self::font_weight_property())
290    }
291
292    /// Sets the value of the attached `FontWeight` property on a control.
293    pub fn set_font_weight_on(control: &Control, value: FontWeight) {
294        control.set_value(Self::font_weight_property(), value)
295    }
296
297    /// Gets the value of the attached `FontStretch` property on a control.
298    pub fn get_font_stretch(control: &Control) -> FontStretch {
299        control.get_value(Self::font_stretch_property())
300    }
301
302    /// Sets the value of the attached `FontStretch` property on a control.
303    pub fn set_font_stretch_on(control: &Control, value: FontStretch) {
304        control.set_value(Self::font_stretch_property(), value)
305    }
306
307    /// Gets the value of the attached `Foreground` property on a control.
308    pub fn get_foreground(control: &Control) -> Option<Rc<dyn IBrush>> {
309        control.get_value(Self::foreground_property())
310    }
311
312    /// Sets the value of the attached `Foreground` property on a control.
313    pub fn set_foreground_on(control: &Control, value: Option<Rc<dyn IBrush>>) {
314        control.set_value(Self::foreground_property(), value)
315    }
316
317    /// The host of the element.
318    pub(crate) fn inline_host(&self) -> Option<Rc<dyn IInlineHost>> {
319        self.inline_host.borrow().clone()
320    }
321
322    pub(crate) fn set_inline_host(&self, value: Option<Rc<dyn IInlineHost>>) {
323        let old_value = self.inline_host.replace(value.clone());
324        self.on_inline_host_changed(old_value.as_ref(), value.as_ref());
325    }
326}