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    modifier!(
125        /// Sets the ext caret color of the view.
126        caret_color,
127        Color,
128        SystemFlags::REDRAW
129    );
130
131    modifier!(
132        /// Sets the color used to highlight selected text within the view.
133        selection_color,
134        Color,
135        SystemFlags::REDRAW
136    );
137
138    modifier!(
139        /// Sets whether the text of the view should be allowed to wrap.
140        text_wrap,
141        bool,
142        SystemFlags::REFLOW
143    );
144
145    modifier!(
146        /// Sets the horizontal alignment of text within the view.
147        text_align,
148        TextAlign,
149        SystemFlags::REFLOW
150    );
151
152    modifier!(
153        /// Sets the text overflow.
154        text_overflow,
155        TextOverflow,
156        SystemFlags::REFLOW
157    );
158
159    modifier!(
160        /// Sets the max number of .
161        line_clamp,
162        LineClamp,
163        SystemFlags::REFLOW
164    );
165
166    modifier!(
167        /// Sets the max number of .
168        text_decoration_line,
169        TextDecorationLine,
170        SystemFlags::REFLOW
171    );
172
173    modifier!(
174        /// Sets the width of the text stroke.
175        /// This sets Skia's [`skia_safe::textlayout::TextStyle`]'s foreground [`skia_safe::Paint`] to
176        /// draw a stroke on the text.
177        ///
178        /// See also [`Self::text_stroke_style`].
179        text_stroke_width,
180        Length,
181        SystemFlags::REFLOW
182    );
183
184    modifier!(
185        /// Sets the paint style of the text stroke.
186        /// You can either draw text with a stroke, or just the stroke outline.
187        ///
188        /// If you desire to paint the text stroke in a separate colour to the
189        /// fill property, Skia does not seem to support this (see the
190        /// [discussion on the PR to add text stroke](https://github.com/vizia/vizia/pull/528)).
191        ///
192        /// A workaround would involve a [`ZStack`] to overlay two copies of the
193        /// same text, one with a stroke and one without. These can have two
194        /// different colours. See also the [Flutter documentation](
195        /// https://api.flutter.dev/flutter/painting/TextStyle-class.html#painting.TextStyle.6)
196        /// on achieving this.
197        text_stroke_style,
198        TextStrokeStyle,
199        SystemFlags::REFLOW
200    );
201}
202
203impl<V> TextModifiers for Handle<'_, V> {}