Skip to main content

vizia_core/modifiers/
text.rs

1use super::internal;
2use crate::prelude::*;
3use std::{cell::RefCell, rc::Rc};
4
5/// Modifiers for changing the text properties of a view.
6pub trait TextModifiers: internal::Modifiable {
7    /// Sets the text content of the view.
8    fn text<T: ToStringLocalized, R: Res<T> + 'static>(mut self, value: R) -> Self {
9        let entity = self.entity();
10        let current = self.current();
11        self.context().with_current(current, |cx| {
12            let value_store = Rc::new(RefCell::new(None::<R>));
13            let value_store_for_binding = value_store.clone();
14
15            value.set_or_bind(cx, move |cx, val| {
16                *value_store_for_binding.borrow_mut() = Some(val);
17                let cx: &mut EventContext<'_> = &mut EventContext::new_with_current(cx, entity);
18                let text_data = value_store_for_binding
19                    .borrow()
20                    .as_ref()
21                    .map(|value| value.get_value(cx).to_string_local(cx));
22
23                let Some(text_data) = text_data else {
24                    return;
25                };
26
27                // cx.text_context.set_text(entity, &text_data);
28                cx.style.text.insert(entity, text_data);
29
30                cx.style.needs_text_update(entity);
31                cx.needs_relayout();
32                cx.needs_redraw();
33            });
34
35            let value_store_for_locale = value_store;
36            let locale = cx.environment().locale;
37            locale.set_or_bind(cx, move |cx, _| {
38                let cx: &mut EventContext<'_> = &mut EventContext::new_with_current(cx, entity);
39                let text_data = value_store_for_locale
40                    .borrow()
41                    .as_ref()
42                    .map(|value| value.get_value(cx).to_string_local(cx));
43
44                let Some(text_data) = text_data else {
45                    return;
46                };
47
48                // cx.text_context.set_text(entity, &text_data);
49                cx.style.text.insert(entity, text_data);
50
51                cx.style.needs_text_update(entity);
52                cx.needs_relayout();
53                cx.needs_redraw();
54            });
55        });
56
57        self
58    }
59
60    modifier!(
61        /// Sets the font that should be used by the view.
62        ///
63        /// The font name refers to the name assigned when the font is added to context.
64        font_family,
65        Vec<FamilyOwned>,
66        SystemFlags::REFLOW
67    );
68
69    modifier!(
70        /// Sets the font weight that should be used by the view.
71        font_weight,
72        FontWeight,
73        SystemFlags::REFLOW
74    );
75
76    modifier!(
77        /// Sets the font style that should be used by the view.
78        font_slant,
79        FontSlant,
80        SystemFlags::REFLOW
81    );
82
83    modifier!(
84        /// Sets the font stretch that should be used by the view if the font supports it.
85        font_width,
86        FontWidth,
87        SystemFlags::REFLOW
88    );
89
90    modifier!(
91        /// Sets the font variation settings that should be used by the view.
92        font_variation_settings,
93        Vec<FontVariation>,
94        SystemFlags::REFLOW
95    );
96
97    /// Sets the text color of the view.
98    fn color<U: Clone + Into<Color>>(mut self, value: impl Res<U>) -> Self {
99        let entity = self.entity();
100        let current = self.current();
101        self.context().with_current(current, move |cx| {
102            value.set_or_bind(cx, move |cx, v| {
103                cx.style.font_color.insert(entity, v.get_value(cx).into());
104                cx.style.needs_text_update(entity);
105                cx.needs_redraw(entity);
106            });
107        });
108        self
109    }
110
111    /// Sets the font size of the view.
112    fn font_size<U: Into<FontSize>>(mut self, value: impl Res<U>) -> Self {
113        let entity = self.entity();
114        let current = self.current();
115        self.context().with_current(current, move |cx| {
116            value.set_or_bind(cx, move |cx, v| {
117                cx.style.font_size.insert(entity, v.get_value(cx).into());
118                cx.style.needs_text_update(entity);
119            });
120        });
121        self
122    }
123
124    /// Sets the letter spacing of the view text.
125    fn letter_spacing<U: Into<LetterSpacing>>(mut self, value: impl Res<U>) -> Self {
126        let entity = self.entity();
127        let current = self.current();
128        self.context().with_current(current, move |cx| {
129            value.set_or_bind(cx, move |cx, v| {
130                cx.style.letter_spacing.insert(entity, v.get_value(cx).into());
131                cx.style.needs_text_update(entity);
132            });
133        });
134        self
135    }
136
137    modifier!(
138        /// Sets the ext caret color of the view.
139        caret_color,
140        Color,
141        SystemFlags::REDRAW
142    );
143
144    modifier!(
145        /// Sets the color used to highlight selected text within the view.
146        selection_color,
147        Color,
148        SystemFlags::REDRAW
149    );
150
151    modifier!(
152        /// Sets whether the text of the view should be allowed to wrap.
153        text_wrap,
154        bool,
155        SystemFlags::REFLOW
156    );
157
158    modifier!(
159        /// Sets the horizontal alignment of text within the view.
160        text_align,
161        TextAlign,
162        SystemFlags::REFLOW
163    );
164
165    modifier!(
166        /// Sets the text overflow.
167        text_overflow,
168        TextOverflow,
169        SystemFlags::REFLOW
170    );
171
172    modifier!(
173        /// Sets the line height of the view text.
174        line_height,
175        LineHeight,
176        SystemFlags::REFLOW
177    );
178
179    modifier!(
180        /// Sets the max number of .
181        line_clamp,
182        LineClamp,
183        SystemFlags::REFLOW
184    );
185
186    modifier!(
187        /// Sets the max number of .
188        text_decoration_line,
189        TextDecorationLine,
190        SystemFlags::REFLOW
191    );
192
193    modifier!(
194        /// Sets the width of the text stroke.
195        /// This sets Skia's [`skia_safe::textlayout::TextStyle`]'s foreground [`skia_safe::Paint`] to
196        /// draw a stroke on the text.
197        ///
198        /// See also [`Self::text_stroke_style`].
199        text_stroke_width,
200        Length,
201        SystemFlags::REFLOW
202    );
203
204    modifier!(
205        /// Sets the paint style of the text stroke.
206        /// You can either draw text with a stroke, or just the stroke outline.
207        ///
208        /// If you desire to paint the text stroke in a separate colour to the
209        /// fill property, Skia does not seem to support this (see the
210        /// [discussion on the PR to add text stroke](https://github.com/vizia/vizia/pull/528)).
211        ///
212        /// A workaround would involve a [`ZStack`] to overlay two copies of the
213        /// same text, one with a stroke and one without. These can have two
214        /// different colours. See also the [Flutter documentation](
215        /// https://api.flutter.dev/flutter/painting/TextStyle-class.html#painting.TextStyle.6)
216        /// on achieving this.
217        text_stroke_style,
218        TextStrokeStyle,
219        SystemFlags::REFLOW
220    );
221}
222
223impl<V> TextModifiers for Handle<'_, V> {}