Label

Struct Label 

Source
pub struct Label<T> { /* private fields */ }
Expand description

A label that displays static or dynamic text.

This type manages an inner RawLabel, updating its text based on the current Data and Env as required.

If your Data is already text, you may use a RawLabel directly. As a convenience, you can create a RawLabel with the Label::raw constructor method.

A label is the easiest way to display text in Druid. A label is instantiated with some LabelText type, such as an ArcStr or a LocalizedString, and also has methods for setting the default font, font-size, text color, and other attributes.

In addition to being a Widget, Label is also regularly used as a component in other widgets that wish to display text; to facilitate this it has a draw_at method that allows the caller to easily draw the label’s text at the desired position on screen.

§Examples

Make a label to say something very important:


let font = FontDescriptor::new(FontFamily::SYSTEM_UI)
    .with_weight(FontWeight::BOLD)
    .with_size(48.0);

let important_label = Label::new("WATCH OUT!")
    .with_font(font)
    .with_text_color(Color::rgb(1.0, 0.2, 0.2));

Implementations§

Source§

impl<T: TextStorage> Label<T>

Source

pub fn raw() -> RawLabel<T>

Create a new RawLabel.

This can display text Data directly.

Source§

impl<T: Data> Label<T>

Source

pub fn new(text: impl Into<LabelText<T>>) -> Self

Construct a new Label widget.

use druid::LocalizedString;
use druid::widget::Label;

// Construct a new Label using static string.
let _: Label<u32> = Label::new("Hello world");

// Construct a new Label using localized string.
let text = LocalizedString::new("hello-counter").with_arg("count", |data: &u32, _env| (*data).into());
let _: Label<u32> = Label::new(text);

// Construct a new dynamic Label. Text will be updated when data changes.
let _: Label<u32> = Label::new(|data: &u32, _env: &_| format!("Hello world: {}", data));
Examples found in repository?
examples/disabled.rs (line 39)
37fn named_child(name: &str, widget: impl Widget<AppData> + 'static) -> impl Widget<AppData> {
38    Flex::row()
39        .with_child(Label::new(name))
40        .with_default_spacer()
41        .with_child(widget)
42}
More examples
Hide additional examples
examples/tabs.rs (line 107)
103    fn group<T: Data, W: Widget<T> + 'static>(text: &str, w: W) -> impl Widget<T> {
104        Flex::column()
105            .cross_axis_alignment(CrossAxisAlignment::Start)
106            .with_child(
107                Label::new(text)
108                    .background(theme::PLACEHOLDER_COLOR)
109                    .expand_width(),
110            )
111            .with_default_spacer()
112            .with_child(w)
113            .with_default_spacer()
114            .border(Color::WHITE, 0.5)
115    }
116
117    let axis_picker = group(
118        "Tab bar axis",
119        RadioGroup::column(vec![
120            ("Horizontal", Axis::Horizontal),
121            ("Vertical", Axis::Vertical),
122        ])
123        .lens(TabConfig::axis),
124    );
125
126    let cross_picker = group(
127        "Tab bar edge",
128        RadioGroup::column(vec![
129            ("Leading", TabsEdge::Leading),
130            ("Trailing", TabsEdge::Trailing),
131        ])
132        .lens(TabConfig::edge),
133    );
134
135    let transit_picker = group(
136        "Transition",
137        RadioGroup::column(vec![
138            ("Instant", TabsTransition::Instant),
139            (
140                "Slide",
141                TabsTransition::Slide(Duration::from_millis(250).as_nanos() as u64),
142            ),
143        ])
144        .lens(TabConfig::transition),
145    );
146
147    let sidebar = Flex::column()
148        .main_axis_alignment(MainAxisAlignment::Start)
149        .cross_axis_alignment(CrossAxisAlignment::Start)
150        .with_child(axis_picker)
151        .with_default_spacer()
152        .with_child(cross_picker)
153        .with_default_spacer()
154        .with_child(transit_picker)
155        .with_flex_spacer(1.)
156        .fix_width(200.0)
157        .lens(AppState::tab_config);
158
159    let vs = ViewSwitcher::new(
160        |app_s: &AppState, _| app_s.tab_config.clone(),
161        |tc: &TabConfig, _, _| Box::new(build_tab_widget(tc)),
162    );
163    Flex::row().with_child(sidebar).with_flex_child(vs, 1.0)
164}
165
166#[derive(Clone, Data)]
167struct NumberedTabs;
168
169impl TabsPolicy for NumberedTabs {
170    type Key = usize;
171    type Build = ();
172    type Input = DynamicTabData;
173    type LabelWidget = Label<DynamicTabData>;
174    type BodyWidget = Label<DynamicTabData>;
175
176    fn tabs_changed(&self, old_data: &DynamicTabData, data: &DynamicTabData) -> bool {
177        old_data.tabs_key() != data.tabs_key()
178    }
179
180    fn tabs(&self, data: &DynamicTabData) -> Vec<Self::Key> {
181        data.tab_labels.iter().copied().collect()
182    }
183
184    fn tab_info(&self, key: Self::Key, _data: &DynamicTabData) -> TabInfo<DynamicTabData> {
185        TabInfo::new(format!("Tab {key:?}"), true)
186    }
187
188    fn tab_body(&self, key: Self::Key, _data: &DynamicTabData) -> Label<DynamicTabData> {
189        Label::new(format!("Dynamic tab body {key:?}"))
190    }
191
192    fn close_tab(&self, key: Self::Key, data: &mut DynamicTabData) {
193        if let Some(idx) = data.tab_labels.index_of(&key) {
194            data.remove_tab(idx)
195        }
196    }
197
198    fn tab_label(
199        &self,
200        _key: Self::Key,
201        info: TabInfo<Self::Input>,
202        _data: &Self::Input,
203    ) -> Self::LabelWidget {
204        Self::default_make_label(info)
205    }
206}
207
208fn build_tab_widget(tab_config: &TabConfig) -> impl Widget<AppState> {
209    let dyn_tabs = Tabs::for_policy(NumberedTabs)
210        .with_axis(tab_config.axis)
211        .with_edge(tab_config.edge)
212        .with_transition(tab_config.transition)
213        .lens(AppState::advanced);
214
215    let control_dynamic = Flex::column()
216        .cross_axis_alignment(CrossAxisAlignment::Start)
217        .with_child(Label::new("Control dynamic tabs"))
218        .with_child(Button::new("Add a tab").on_click(|_c, d: &mut DynamicTabData, _e| d.add_tab()))
219        .with_child(Label::new(|adv: &DynamicTabData, _e: &Env| {
220            format!("Highest tab number is {}", adv.highest_tab)
221        }))
222        .with_spacer(20.)
223        .lens(AppState::advanced);
224
225    let first_static_tab = Flex::row()
226        .with_child(Label::new("Rename tab:"))
227        .with_child(TextBox::new().lens(AppState::first_tab_name));
228
229    let main_tabs = Tabs::new()
230        .with_axis(tab_config.axis)
231        .with_edge(tab_config.edge)
232        .with_transition(tab_config.transition)
233        .with_tab(
234            |app_state: &AppState, _: &Env| app_state.first_tab_name.to_string(),
235            first_static_tab,
236        )
237        .with_tab("Dynamic", control_dynamic)
238        .with_tab("Page 3", Label::new("Page 3 content"))
239        .with_tab("Page 4", Label::new("Page 4 content"))
240        .with_tab("Page 5", Label::new("Page 5 content"))
241        .with_tab("Page 6", Label::new("Page 6 content"))
242        .with_tab_index(1);
243
244    Split::rows(main_tabs, dyn_tabs).draggable(true)
245}
examples/calc.rs (line 136)
121fn op_button_label(op: char, label: String) -> impl Widget<CalcState> {
122    let painter = Painter::new(|ctx, _, env| {
123        let bounds = ctx.size().to_rect();
124
125        ctx.fill(bounds, &env.get(theme::PRIMARY_DARK));
126
127        if ctx.is_hot() {
128            ctx.stroke(bounds.inset(-0.5), &Color::WHITE, 1.0);
129        }
130
131        if ctx.is_active() {
132            ctx.fill(bounds, &env.get(theme::PRIMARY_LIGHT));
133        }
134    });
135
136    Label::new(label)
137        .with_text_size(24.)
138        .center()
139        .background(painter)
140        .expand()
141        .on_click(move |_ctx, data: &mut CalcState, _env| data.op(op))
142}
143
144fn op_button(op: char) -> impl Widget<CalcState> {
145    op_button_label(op, op.to_string())
146}
147
148fn digit_button(digit: u8) -> impl Widget<CalcState> {
149    let painter = Painter::new(|ctx, _, env| {
150        let bounds = ctx.size().to_rect();
151
152        ctx.fill(bounds, &env.get(theme::BACKGROUND_LIGHT));
153
154        if ctx.is_hot() {
155            ctx.stroke(bounds.inset(-0.5), &Color::WHITE, 1.0);
156        }
157
158        if ctx.is_active() {
159            ctx.fill(bounds, &Color::rgb8(0x71, 0x71, 0x71));
160        }
161    });
162
163    Label::new(format!("{digit}"))
164        .with_text_size(24.)
165        .center()
166        .background(painter)
167        .expand()
168        .on_click(move |_ctx, data: &mut CalcState, _env| data.digit(digit))
169}
170
171fn flex_row<T: Data>(
172    w1: impl Widget<T> + 'static,
173    w2: impl Widget<T> + 'static,
174    w3: impl Widget<T> + 'static,
175    w4: impl Widget<T> + 'static,
176) -> impl Widget<T> {
177    Flex::row()
178        .with_flex_child(w1, 1.0)
179        .with_spacer(1.0)
180        .with_flex_child(w2, 1.0)
181        .with_spacer(1.0)
182        .with_flex_child(w3, 1.0)
183        .with_spacer(1.0)
184        .with_flex_child(w4, 1.0)
185}
186
187fn build_calc() -> impl Widget<CalcState> {
188    let display = Label::new(|data: &String, _env: &_| data.clone())
189        .with_text_size(32.0)
190        .lens(CalcState::value)
191        .padding(5.0);
192    Flex::column()
193        .with_flex_spacer(0.2)
194        .with_child(display)
195        .with_flex_spacer(0.2)
196        .cross_axis_alignment(CrossAxisAlignment::End)
197        .with_flex_child(
198            flex_row(
199                op_button_label('c', "CE".to_string()),
200                op_button('C'),
201                op_button('⌫'),
202                op_button('÷'),
203            ),
204            1.0,
205        )
206        .with_spacer(1.0)
207        .with_flex_child(
208            flex_row(
209                digit_button(7),
210                digit_button(8),
211                digit_button(9),
212                op_button('×'),
213            ),
214            1.0,
215        )
216        .with_spacer(1.0)
217        .with_flex_child(
218            flex_row(
219                digit_button(4),
220                digit_button(5),
221                digit_button(6),
222                op_button('−'),
223            ),
224            1.0,
225        )
226        .with_spacer(1.0)
227        .with_flex_child(
228            flex_row(
229                digit_button(1),
230                digit_button(2),
231                digit_button(3),
232                op_button('+'),
233            ),
234            1.0,
235        )
236        .with_spacer(1.0)
237        .with_flex_child(
238            flex_row(
239                op_button('±'),
240                digit_button(0),
241                op_button('.'),
242                op_button('='),
243            ),
244            1.0,
245        )
246}
examples/either.rs (line 45)
32fn ui_builder() -> impl Widget<AppState> {
33    // Our UI consists of a column with a button and an `Either` widget
34    let button = Checkbox::new("Toggle slider")
35        .lens(AppState::which)
36        .padding(5.0);
37
38    // The `Either` widget has two children, only one of which is visible at a time.
39    // To determine which child is visible, you pass it a closure that takes the
40    // `Data` and the `Env` and returns a bool; if it returns `true`, the first
41    // widget will be visible, and if `false`, the second.
42    let either = Either::new(
43        |data, _env| data.which,
44        Slider::new().lens(AppState::value).padding(5.0),
45        Label::new("Click to reveal slider").padding(5.0),
46    );
47    Flex::column().with_child(button).with_child(either)
48}
examples/textbox.rs (line 68)
67fn build_root_widget() -> impl Widget<AppState> {
68    let blurb = Label::new(EXPLAINER)
69        .with_line_break_mode(druid::widget::LineBreaking::WordWrap)
70        .padding(8.0)
71        .border(Color::grey(0.6), 2.0)
72        .rounded(5.0);
73
74    Flex::column()
75        .cross_axis_alignment(druid::widget::CrossAxisAlignment::Start)
76        .with_child(blurb)
77        .with_spacer(24.0)
78        .with_child(
79            TextBox::new()
80                .with_placeholder("Single")
81                .lens(AppState::single),
82        )
83        .with_default_spacer()
84        .with_flex_child(
85            TextBox::multiline()
86                .with_placeholder("Multi")
87                .lens(AppState::multi)
88                .expand_width(),
89            1.0,
90        )
91        .padding(8.0)
92}
examples/hello.rs (lines 53-59)
51fn build_root_widget() -> impl Widget<HelloState> {
52    // a label that will determine its text based on the current app data.
53    let label = Label::new(|data: &HelloState, _env: &Env| {
54        if data.name.is_empty() {
55            "Hello anybody!?".to_string()
56        } else {
57            format!("Hello {}!", data.name)
58        }
59    })
60    .with_text_size(32.0);
61
62    // a textbox that modifies `name`.
63    let textbox = TextBox::new()
64        .with_placeholder("Who are we greeting?")
65        .with_text_size(18.0)
66        .fix_width(TEXT_BOX_WIDTH)
67        .lens(HelloState::name);
68
69    // arrange the two widgets vertically, with some padding
70    Flex::column()
71        .with_child(label)
72        .with_spacer(VERTICAL_WIDGET_SPACING)
73        .with_child(textbox)
74        .align_vertical(UnitPoint::CENTER)
75}
Source

pub fn dynamic(text: impl Fn(&T, &Env) -> String + 'static) -> Self

Construct a new dynamic label.

The contents of this label are generated from the data using a closure.

This is provided as a convenience; a closure can also be passed to new, but due to limitations of the implementation of that method, the types in the closure need to be annotated, which is not true for this method.

§Examples

The following are equivalent.

use druid::Env;
use druid::widget::Label;
let label1: Label<u32> = Label::new(|data: &u32, _: &Env| format!("total is {}", data));
let label2: Label<u32> = Label::dynamic(|data, _| format!("total is {}", data));
Examples found in repository?
examples/z_stack.rs (lines 47-52)
45fn build_root_widget() -> impl Widget<State> {
46    ZStack::new(
47        Button::from_label(Label::dynamic(|state: &State, _| {
48            format!(
49                "Very large button with text! Count up (currently {})",
50                state.counter
51            )
52        }))
53        .on_click(|_, state: &mut State, _| state.counter += 1),
54    )
55    .with_child(
56        Button::new("Reset").on_click(|_, state: &mut State, _| state.counter = 0),
57        Vec2::new(1.0, 1.0),
58        Vec2::ZERO,
59        UnitPoint::LEFT,
60        Vec2::new(10.0, 0.0),
61    )
62}
More examples
Hide additional examples
examples/event_viewer.rs (line 306)
304fn make_list_item() -> impl Widget<LoggedEvent> {
305    Flex::row()
306        .with_child(Label::dynamic(|d: &LoggedEvent, _| d.number()).fix_width(PROPERTIES[0].1))
307        .with_default_spacer()
308        .with_child(Label::dynamic(|d: &LoggedEvent, _| d.name()).fix_width(PROPERTIES[1].1))
309        .with_default_spacer()
310        .with_child(Label::dynamic(|d: &LoggedEvent, _| d.mouse_pos()).fix_width(PROPERTIES[2].1))
311        .with_default_spacer()
312        .with_child(Label::dynamic(|d: &LoggedEvent, _| d.wheel_delta()).fix_width(PROPERTIES[3].1))
313        .with_default_spacer()
314        .with_child(
315            Label::dynamic(|d: &LoggedEvent, _| d.mouse_button()).fix_width(PROPERTIES[4].1),
316        )
317        .with_default_spacer()
318        .with_child(Label::dynamic(|d: &LoggedEvent, _| d.click_count()).fix_width(PROPERTIES[5].1))
319        .with_default_spacer()
320        .with_child(Label::dynamic(|d: &LoggedEvent, _| d.is_repeat()).fix_width(PROPERTIES[6].1))
321        .with_default_spacer()
322        .with_child(Label::dynamic(|d: &LoggedEvent, _| d.key()).fix_width(PROPERTIES[7].1))
323        .with_default_spacer()
324        .with_child(Label::dynamic(|d: &LoggedEvent, _| d.code()).fix_width(PROPERTIES[8].1))
325        .with_default_spacer()
326        .with_child(Label::dynamic(|d: &LoggedEvent, _| d.modifiers()).fix_width(PROPERTIES[9].1))
327        .with_default_spacer()
328        .with_child(Label::dynamic(|d: &LoggedEvent, _| d.location()).fix_width(PROPERTIES[10].1))
329}
examples/slider.rs (lines 57-59)
55fn build_root_widget() -> impl Widget<AppState> {
56    let range = Flex::row()
57        .with_child(Label::dynamic(|value: &(f64, f64), _| {
58            format!("Value Range: {value:?}")
59        }))
60        .with_default_spacer()
61        .with_child(
62            RangeSlider::new()
63                .with_range(0.0, 20.0)
64                .with_step(1.0)
65                .track_color(KeyOrValue::Concrete(Color::RED))
66                .fix_width(250.0),
67        )
68        .lens(AppState::range);
69
70    let value = Flex::row()
71        .with_child(Label::dynamic(|value: &AppState, _| {
72            format!("Value: {:?}", value.value)
73        }))
74        .with_default_spacer()
75        .with_child(ViewSwitcher::new(
76            |data: &AppState, _| data.range,
77            |range, _, _| {
78                Slider::new()
79                    .with_range(range.0, range.1)
80                    .track_color(KeyOrValue::Concrete(Color::RED))
81                    .knob_style(KnobStyle::Wedge)
82                    .axis(Axis::Vertical)
83                    .with_step(0.25)
84                    .annotated(1.0, 0.25)
85                    .fix_height(250.0)
86                    .lens(AppState::value)
87                    .boxed()
88            },
89        ));
90
91    // arrange the two widgets vertically, with some padding
92    Flex::column()
93        .with_child(range)
94        .with_spacer(VERTICAL_WIDGET_SPACING)
95        .with_child(value)
96        .cross_axis_alignment(CrossAxisAlignment::End)
97        .align_vertical(UnitPoint::RIGHT)
98        .padding(20.0)
99}
examples/identity.rs (line 73)
62fn make_ui() -> impl Widget<OurData> {
63    // We can also generate these dynamically whenever we need it.
64    let id_two = WidgetId::next();
65    // We have a column with 2 labels and 2 buttons.
66    // Each of the 2 labels only has access to its own counter and is given a `WidgetId`.
67    // Both labels have a controller, this handles commands send to children.
68    // The 2 buttons send a command when clicked. Both send the exact same command.
69    // The key diference is that they both give a different `WidgetId` as target.
70    // This means that only the corresponding controller gets the command, and increments their counter.
71    Flex::column()
72        .with_child(
73            Label::dynamic(|data, _| format!("One: {data}"))
74                .controller(LabelControler)
75                .with_id(ID_ONE)
76                .lens(OurData::counter_one)
77                .padding(2.0),
78        )
79        .with_child(
80            Label::dynamic(|data, _| format!("Two: {data}"))
81                .controller(LabelControler)
82                .with_id(id_two)
83                .lens(OurData::counter_two)
84                .padding(2.0),
85        )
86        .with_child(
87            Button::<OurData>::new("Increment one")
88                .on_click(|ctx, _data, _env| ctx.submit_command(INCREMENT.to(ID_ONE)))
89                .padding(2.0),
90        )
91        .with_child(
92            Button::<OurData>::new("Increment two")
93                .on_click(move |ctx, _data, _env| ctx.submit_command(INCREMENT.to(id_two)))
94                .padding(2.0),
95        )
96        .padding(10.0)
97}
examples/disabled.rs (line 101)
44fn main_widget() -> impl Widget<AppData> {
45    Flex::column()
46        .with_child(named_child("text:", TextBox::new().lens(AppData::text)))
47        .with_default_spacer()
48        .with_child(
49            named_child("text (disabled):", TextBox::new().lens(AppData::text))
50                .disabled_if(|data, _| data.disabled),
51        )
52        .with_default_spacer()
53        .with_child(named_child("text:", TextBox::new().lens(AppData::text)))
54        .with_default_spacer()
55        .with_child(
56            named_child("text (disabled):", TextBox::new().lens(AppData::text))
57                .disabled_if(|data, _| data.disabled),
58        )
59        .with_default_spacer()
60        .with_default_spacer()
61        .with_child(
62            named_child(
63                "value (disabled):",
64                Slider::new().with_range(0.0, 10.0).lens(AppData::value),
65            )
66            .disabled_if(|data, _| data.disabled),
67        )
68        .with_default_spacer()
69        .with_child(
70            named_child(
71                "value (disabled):",
72                Stepper::new()
73                    .with_range(0.0, 10.0)
74                    .with_step(0.5)
75                    .lens(AppData::value),
76            )
77            .disabled_if(|data, _| data.disabled),
78        )
79        .with_default_spacer()
80        .with_child(
81            named_child(
82                "option (disabled):",
83                Checkbox::new("option").lens(AppData::option),
84            )
85            .disabled_if(|data, _| data.disabled),
86        )
87        .with_default_spacer()
88        .with_child(
89            named_child("option (disabled):", Switch::new().lens(AppData::option))
90                .disabled_if(|data, _| data.disabled),
91        )
92        .with_default_spacer()
93        .with_child(
94            Flex::row()
95                .with_child(
96                    Button::new("-")
97                        .on_click(|_, data: &mut f64, _| *data -= 1.0)
98                        .disabled_if(|data, _| *data < 1.0),
99                )
100                .with_default_spacer()
101                .with_child(Label::dynamic(|data: &f64, _| data.to_string()))
102                .with_default_spacer()
103                .with_child(
104                    Button::new("+")
105                        .on_click(|_, data: &mut f64, _| *data += 1.0)
106                        .disabled_if(|data, _| *data > 9.0),
107                )
108                .lens(AppData::value)
109                .disabled_if(|data: &AppData, _| data.disabled),
110        )
111        .with_default_spacer()
112        .with_default_spacer()
113        .with_default_spacer()
114        .with_child(Checkbox::new("disabled").lens(AppData::disabled))
115        .with_default_spacer()
116        .cross_axis_alignment(CrossAxisAlignment::End)
117        .align_horizontal(UnitPoint::CENTER)
118}
Source

pub fn text(&self) -> ArcStr

Return the current value of the label’s text.

Source

pub fn set_text(&mut self, text: impl Into<LabelText<T>>)

Set the label’s text.

§Note

If you change this property, at runtime, you must ensure that update is called in order to correctly recompute the text. If you are unsure, call request_update explicitly.

Source

pub fn with_text_color(self, color: impl Into<KeyOrValue<Color>>) -> Self

Builder-style method for setting the text color.

The argument can be either a Color or a Key<Color>.

Examples found in repository?
examples/transparency.rs (line 97)
62fn build_root_widget() -> impl Widget<HelloState> {
63    // Draw red circle, and two semi-transparent rectangles
64    let circle_and_rects = Painter::new(|ctx, _data, _env| {
65        let boundaries = ctx.size().to_rect();
66        let center = (boundaries.width() / 2., boundaries.height() / 2.);
67        let circle = Circle::new(center, center.0.min(center.1));
68        ctx.fill(circle, &Color::RED);
69
70        let rect1 = Rect::new(0., 0., boundaries.width() / 2., boundaries.height() / 2.);
71        ctx.fill(rect1, &Color::rgba8(0x0, 0xff, 0, 125));
72
73        let rect2 = Rect::new(
74            boundaries.width() / 2.,
75            boundaries.height() / 2.,
76            boundaries.width(),
77            boundaries.height(),
78        );
79        ctx.fill(rect2, &Color::rgba8(0x0, 0x0, 0xff, 125));
80    });
81
82    // This textbox modifies the label, idea here is to test that the background
83    // invalidation works when you type to the textbox
84    let textbox = TextBox::new()
85        .with_placeholder("Type to test clearing")
86        .with_text_size(18.0)
87        .lens(HelloState::name)
88        .fix_width(250.);
89
90    let label = Label::new(|data: &HelloState, _env: &Env| {
91        if data.name.is_empty() {
92            "Text: ".to_string()
93        } else {
94            format!("Text: {}!", data.name)
95        }
96    })
97    .with_text_color(Color::RED)
98    .with_text_size(32.0);
99
100    Flex::column()
101        .with_flex_child(circle_and_rects.expand().controller(DragController), 10.0)
102        .with_spacer(4.0)
103        .with_child(textbox)
104        .with_spacer(4.0)
105        .with_child(label)
106}
More examples
Hide additional examples
examples/layout.rs (line 66)
24fn build_app() -> impl Widget<u32> {
25    // Usually we put all the widgets in one big tree using builder-style
26    // methods. Sometimes we split them up in declarations to increase
27    // readability. In this case we also have some recurring elements,
28    // we add those in a loop later on.
29    let mut col = Flex::column().with_child(
30        // The `Flex`'s first child is another Flex! In this case it is
31        // a row.
32        Flex::row()
33            // The row has its own children.
34            .with_child(
35                Label::new("One")
36                    .fix_width(60.0)
37                    .background(Color::rgb8(0x77, 0x77, 0))
38                    .border(Color::WHITE, 3.0)
39                    .center(),
40            )
41            // Spacing element that will fill all available space in
42            // between label and a button. Notice that weight is non-zero.
43            // We could have achieved a similar result with expanding the
44            // width and setting the main-axis-allignment to SpaceBetween.
45            .with_flex_spacer(1.0)
46            .with_child(Button::new("Two").padding(20.))
47            // After we added all the children, we can set some more
48            // values using builder-style methods. Since these methods
49            // dont return the original `Flex` but a SizedBox and Container
50            // respectively, we have to put these at the end.
51            .fix_height(100.0)
52            //turquoise
53            .background(Color::rgb8(0, 0x77, 0x88)),
54    );
55
56    for i in 0..5 {
57        // Give a larger weight to one of the buttons for it to
58        // occupy more space.
59        let weight = if i == 2 { 3.0 } else { 1.0 };
60        // call `expand_height` to force the buttons to use all their provided flex
61        col.add_flex_child(Button::new(format!("Button #{i}")).expand_height(), weight);
62    }
63
64    // aspect ratio box
65    let aspect_ratio_label = Label::new("This is an aspect-ratio box. Notice how the text will overflow if the box becomes too small.")
66        .with_text_color(Color::BLACK)
67        .with_line_break_mode(LineBreaking::WordWrap)
68        .center();
69    let aspect_ratio_box = AspectRatioBox::new(aspect_ratio_label, 4.0)
70        .border(Color::BLACK, 1.0)
71        .background(Color::WHITE);
72    col.add_flex_child(aspect_ratio_box.center(), 1.0);
73
74    // This method asks Druid to draw colored rectangles around our widgets,
75    // so we can visually inspect their layout rectangles.
76    col.debug_paint_layout()
77}
examples/styled_text.rs (line 99)
72fn ui_builder() -> impl Widget<AppData> {
73    let my_painter = Painter::new(|ctx, _, _| {
74        let bounds = ctx.size().to_rect();
75        if ctx.is_hot() {
76            ctx.fill(bounds, &Color::rgba8(0, 0, 0, 128));
77        }
78
79        if ctx.is_active() {
80            ctx.stroke(bounds, &Color::WHITE, 2.0);
81        }
82    });
83
84    // This is Druid's default text style.
85    // It's set by theme::LABEL_COLOR and theme::UI_FONT
86    let label =
87        Label::new(|data: &String, _env: &_| format!("Default: {data}")).lens(AppData::text);
88
89    // The text_color, text_size, and font builder methods can override the
90    // defaults provided by the theme by passing in a Key or a concrete value.
91    //
92    // In this example, text_color receives a Key from the theme, text_size
93    // gets a custom key which we set with the env_scope wrapper, and the
94    // default font key (theme::FONT_NAME) is overridden in the env_scope
95    // wrapper. (Like text_color and text_size, the font can be set using the
96    // with_font builder method, but overriding here makes it easy to fall back
97    // to the default font)
98    let styled_label = Label::new(|data: &AppData, _env: &_| format!("{data}"))
99        .with_text_color(theme::PRIMARY_LIGHT)
100        .with_font(MY_CUSTOM_FONT)
101        .background(my_painter)
102        .on_click(|_, data, _| {
103            data.size *= 1.1;
104        })
105        .env_scope(|env: &mut druid::Env, data: &AppData| {
106            let new_font = if data.mono {
107                FontDescriptor::new(FontFamily::MONOSPACE)
108            } else {
109                FontDescriptor::new(FontFamily::SYSTEM_UI)
110            }
111            .with_size(data.size);
112            env.set(MY_CUSTOM_FONT, new_font);
113        });
114
115    let labels = Scroll::new(
116        Flex::column()
117            .cross_axis_alignment(CrossAxisAlignment::Start)
118            .with_child(label)
119            .with_default_spacer()
120            .with_child(styled_label),
121    )
122    .expand_height()
123    .fix_width(COLUMN_WIDTH);
124
125    let stepper = Stepper::new()
126        .with_range(0.0, 100.0)
127        .with_step(1.0)
128        .with_wraparound(false)
129        .lens(AppData::size);
130
131    // TODO: Replace Parse usage with TextBox::with_formatter
132    #[allow(deprecated)]
133    let stepper_textbox = LensWrap::new(
134        Parse::new(TextBox::new()),
135        AppData::size.map(|x| Some(*x), |x, y| *x = y.unwrap_or(24.0)),
136    );
137
138    let mono_checkbox = Checkbox::new("Monospace").lens(AppData::mono);
139    let stepper_row = Flex::row()
140        .with_child(stepper_textbox)
141        .with_child(stepper)
142        .with_default_spacer()
143        .with_child(mono_checkbox);
144
145    let input = TextBox::multiline()
146        .with_placeholder("Your sample text here :)")
147        .fix_width(COLUMN_WIDTH)
148        .fix_height(140.0)
149        .lens(AppData::text);
150
151    Flex::column()
152        .main_axis_alignment(MainAxisAlignment::Center)
153        .with_default_spacer()
154        .with_flex_child(labels, 1.0)
155        .with_default_spacer()
156        .with_child(input)
157        .with_default_spacer()
158        .with_child(stepper_row)
159        .with_default_spacer()
160}
Source

pub fn with_text_size(self, size: impl Into<KeyOrValue<f64>>) -> Self

Builder-style method for setting the text size.

The argument can be either an f64 or a Key<f64>.

Examples found in repository?
examples/calc.rs (line 137)
121fn op_button_label(op: char, label: String) -> impl Widget<CalcState> {
122    let painter = Painter::new(|ctx, _, env| {
123        let bounds = ctx.size().to_rect();
124
125        ctx.fill(bounds, &env.get(theme::PRIMARY_DARK));
126
127        if ctx.is_hot() {
128            ctx.stroke(bounds.inset(-0.5), &Color::WHITE, 1.0);
129        }
130
131        if ctx.is_active() {
132            ctx.fill(bounds, &env.get(theme::PRIMARY_LIGHT));
133        }
134    });
135
136    Label::new(label)
137        .with_text_size(24.)
138        .center()
139        .background(painter)
140        .expand()
141        .on_click(move |_ctx, data: &mut CalcState, _env| data.op(op))
142}
143
144fn op_button(op: char) -> impl Widget<CalcState> {
145    op_button_label(op, op.to_string())
146}
147
148fn digit_button(digit: u8) -> impl Widget<CalcState> {
149    let painter = Painter::new(|ctx, _, env| {
150        let bounds = ctx.size().to_rect();
151
152        ctx.fill(bounds, &env.get(theme::BACKGROUND_LIGHT));
153
154        if ctx.is_hot() {
155            ctx.stroke(bounds.inset(-0.5), &Color::WHITE, 1.0);
156        }
157
158        if ctx.is_active() {
159            ctx.fill(bounds, &Color::rgb8(0x71, 0x71, 0x71));
160        }
161    });
162
163    Label::new(format!("{digit}"))
164        .with_text_size(24.)
165        .center()
166        .background(painter)
167        .expand()
168        .on_click(move |_ctx, data: &mut CalcState, _env| data.digit(digit))
169}
170
171fn flex_row<T: Data>(
172    w1: impl Widget<T> + 'static,
173    w2: impl Widget<T> + 'static,
174    w3: impl Widget<T> + 'static,
175    w4: impl Widget<T> + 'static,
176) -> impl Widget<T> {
177    Flex::row()
178        .with_flex_child(w1, 1.0)
179        .with_spacer(1.0)
180        .with_flex_child(w2, 1.0)
181        .with_spacer(1.0)
182        .with_flex_child(w3, 1.0)
183        .with_spacer(1.0)
184        .with_flex_child(w4, 1.0)
185}
186
187fn build_calc() -> impl Widget<CalcState> {
188    let display = Label::new(|data: &String, _env: &_| data.clone())
189        .with_text_size(32.0)
190        .lens(CalcState::value)
191        .padding(5.0);
192    Flex::column()
193        .with_flex_spacer(0.2)
194        .with_child(display)
195        .with_flex_spacer(0.2)
196        .cross_axis_alignment(CrossAxisAlignment::End)
197        .with_flex_child(
198            flex_row(
199                op_button_label('c', "CE".to_string()),
200                op_button('C'),
201                op_button('⌫'),
202                op_button('÷'),
203            ),
204            1.0,
205        )
206        .with_spacer(1.0)
207        .with_flex_child(
208            flex_row(
209                digit_button(7),
210                digit_button(8),
211                digit_button(9),
212                op_button('×'),
213            ),
214            1.0,
215        )
216        .with_spacer(1.0)
217        .with_flex_child(
218            flex_row(
219                digit_button(4),
220                digit_button(5),
221                digit_button(6),
222                op_button('−'),
223            ),
224            1.0,
225        )
226        .with_spacer(1.0)
227        .with_flex_child(
228            flex_row(
229                digit_button(1),
230                digit_button(2),
231                digit_button(3),
232                op_button('+'),
233            ),
234            1.0,
235        )
236        .with_spacer(1.0)
237        .with_flex_child(
238            flex_row(
239                op_button('±'),
240                digit_button(0),
241                op_button('.'),
242                op_button('='),
243            ),
244            1.0,
245        )
246}
More examples
Hide additional examples
examples/hello.rs (line 60)
51fn build_root_widget() -> impl Widget<HelloState> {
52    // a label that will determine its text based on the current app data.
53    let label = Label::new(|data: &HelloState, _env: &Env| {
54        if data.name.is_empty() {
55            "Hello anybody!?".to_string()
56        } else {
57            format!("Hello {}!", data.name)
58        }
59    })
60    .with_text_size(32.0);
61
62    // a textbox that modifies `name`.
63    let textbox = TextBox::new()
64        .with_placeholder("Who are we greeting?")
65        .with_text_size(18.0)
66        .fix_width(TEXT_BOX_WIDTH)
67        .lens(HelloState::name);
68
69    // arrange the two widgets vertically, with some padding
70    Flex::column()
71        .with_child(label)
72        .with_spacer(VERTICAL_WIDGET_SPACING)
73        .with_child(textbox)
74        .align_vertical(UnitPoint::CENTER)
75}
examples/transparency.rs (line 98)
62fn build_root_widget() -> impl Widget<HelloState> {
63    // Draw red circle, and two semi-transparent rectangles
64    let circle_and_rects = Painter::new(|ctx, _data, _env| {
65        let boundaries = ctx.size().to_rect();
66        let center = (boundaries.width() / 2., boundaries.height() / 2.);
67        let circle = Circle::new(center, center.0.min(center.1));
68        ctx.fill(circle, &Color::RED);
69
70        let rect1 = Rect::new(0., 0., boundaries.width() / 2., boundaries.height() / 2.);
71        ctx.fill(rect1, &Color::rgba8(0x0, 0xff, 0, 125));
72
73        let rect2 = Rect::new(
74            boundaries.width() / 2.,
75            boundaries.height() / 2.,
76            boundaries.width(),
77            boundaries.height(),
78        );
79        ctx.fill(rect2, &Color::rgba8(0x0, 0x0, 0xff, 125));
80    });
81
82    // This textbox modifies the label, idea here is to test that the background
83    // invalidation works when you type to the textbox
84    let textbox = TextBox::new()
85        .with_placeholder("Type to test clearing")
86        .with_text_size(18.0)
87        .lens(HelloState::name)
88        .fix_width(250.);
89
90    let label = Label::new(|data: &HelloState, _env: &Env| {
91        if data.name.is_empty() {
92            "Text: ".to_string()
93        } else {
94            format!("Text: {}!", data.name)
95        }
96    })
97    .with_text_color(Color::RED)
98    .with_text_size(32.0);
99
100    Flex::column()
101        .with_flex_child(circle_and_rects.expand().controller(DragController), 10.0)
102        .with_spacer(4.0)
103        .with_child(textbox)
104        .with_spacer(4.0)
105        .with_child(label)
106}
examples/flex.rs (line 268)
241fn build_widget(state: &Params) -> Box<dyn Widget<AppState>> {
242    let mut flex = match state.axis {
243        FlexType::Column => Flex::column(),
244        FlexType::Row => Flex::row(),
245    }
246    .cross_axis_alignment(state.cross_alignment)
247    .main_axis_alignment(state.main_alignment)
248    .must_fill_main_axis(state.fill_major_axis);
249
250    flex.add_child(
251        TextBox::new()
252            .with_placeholder("Sample text")
253            .lens(DemoState::input_text),
254    );
255    space_if_needed(&mut flex, state);
256
257    flex.add_child(
258        Button::new("Clear").on_click(|_ctx, data: &mut DemoState, _env| {
259            data.input_text.clear();
260            data.enabled = false;
261            data.volume = 0.0;
262        }),
263    );
264
265    space_if_needed(&mut flex, state);
266
267    flex.add_child(
268        Label::new(|data: &DemoState, _: &Env| data.input_text.clone()).with_text_size(32.0),
269    );
270    space_if_needed(&mut flex, state);
271    flex.add_child(Checkbox::new("Demo").lens(DemoState::enabled));
272    space_if_needed(&mut flex, state);
273    flex.add_child(Switch::new().lens(DemoState::enabled));
274    space_if_needed(&mut flex, state);
275    flex.add_child(Slider::new().lens(DemoState::volume));
276    space_if_needed(&mut flex, state);
277    flex.add_child(ProgressBar::new().lens(DemoState::volume));
278    space_if_needed(&mut flex, state);
279    flex.add_child(
280        Stepper::new()
281            .with_range(0.0, 1.0)
282            .with_step(0.1)
283            .with_wraparound(true)
284            .lens(DemoState::volume),
285    );
286
287    let mut flex = SizedBox::new(flex);
288    if state.fix_minor_axis {
289        match state.axis {
290            FlexType::Row => flex = flex.height(200.),
291            FlexType::Column => flex = flex.width(200.),
292        }
293    }
294    if state.fix_major_axis {
295        match state.axis {
296            FlexType::Row => flex = flex.width(600.),
297            FlexType::Column => flex = flex.height(300.),
298        }
299    }
300
301    let flex = flex
302        .padding(8.0)
303        .border(Color::grey(0.6), 2.0)
304        .rounded(5.0)
305        .lens(AppState::demo_state);
306
307    if state.debug_layout {
308        flex.debug_paint_layout().boxed()
309    } else {
310        flex.boxed()
311    }
312}
Source

pub fn with_font(self, font: impl Into<KeyOrValue<FontDescriptor>>) -> Self

Builder-style method for setting the font.

The argument can be a FontDescriptor or a Key<FontDescriptor> that refers to a font defined in the Env.

Examples found in repository?
examples/styled_text.rs (line 100)
72fn ui_builder() -> impl Widget<AppData> {
73    let my_painter = Painter::new(|ctx, _, _| {
74        let bounds = ctx.size().to_rect();
75        if ctx.is_hot() {
76            ctx.fill(bounds, &Color::rgba8(0, 0, 0, 128));
77        }
78
79        if ctx.is_active() {
80            ctx.stroke(bounds, &Color::WHITE, 2.0);
81        }
82    });
83
84    // This is Druid's default text style.
85    // It's set by theme::LABEL_COLOR and theme::UI_FONT
86    let label =
87        Label::new(|data: &String, _env: &_| format!("Default: {data}")).lens(AppData::text);
88
89    // The text_color, text_size, and font builder methods can override the
90    // defaults provided by the theme by passing in a Key or a concrete value.
91    //
92    // In this example, text_color receives a Key from the theme, text_size
93    // gets a custom key which we set with the env_scope wrapper, and the
94    // default font key (theme::FONT_NAME) is overridden in the env_scope
95    // wrapper. (Like text_color and text_size, the font can be set using the
96    // with_font builder method, but overriding here makes it easy to fall back
97    // to the default font)
98    let styled_label = Label::new(|data: &AppData, _env: &_| format!("{data}"))
99        .with_text_color(theme::PRIMARY_LIGHT)
100        .with_font(MY_CUSTOM_FONT)
101        .background(my_painter)
102        .on_click(|_, data, _| {
103            data.size *= 1.1;
104        })
105        .env_scope(|env: &mut druid::Env, data: &AppData| {
106            let new_font = if data.mono {
107                FontDescriptor::new(FontFamily::MONOSPACE)
108            } else {
109                FontDescriptor::new(FontFamily::SYSTEM_UI)
110            }
111            .with_size(data.size);
112            env.set(MY_CUSTOM_FONT, new_font);
113        });
114
115    let labels = Scroll::new(
116        Flex::column()
117            .cross_axis_alignment(CrossAxisAlignment::Start)
118            .with_child(label)
119            .with_default_spacer()
120            .with_child(styled_label),
121    )
122    .expand_height()
123    .fix_width(COLUMN_WIDTH);
124
125    let stepper = Stepper::new()
126        .with_range(0.0, 100.0)
127        .with_step(1.0)
128        .with_wraparound(false)
129        .lens(AppData::size);
130
131    // TODO: Replace Parse usage with TextBox::with_formatter
132    #[allow(deprecated)]
133    let stepper_textbox = LensWrap::new(
134        Parse::new(TextBox::new()),
135        AppData::size.map(|x| Some(*x), |x, y| *x = y.unwrap_or(24.0)),
136    );
137
138    let mono_checkbox = Checkbox::new("Monospace").lens(AppData::mono);
139    let stepper_row = Flex::row()
140        .with_child(stepper_textbox)
141        .with_child(stepper)
142        .with_default_spacer()
143        .with_child(mono_checkbox);
144
145    let input = TextBox::multiline()
146        .with_placeholder("Your sample text here :)")
147        .fix_width(COLUMN_WIDTH)
148        .fix_height(140.0)
149        .lens(AppData::text);
150
151    Flex::column()
152        .main_axis_alignment(MainAxisAlignment::Center)
153        .with_default_spacer()
154        .with_flex_child(labels, 1.0)
155        .with_default_spacer()
156        .with_child(input)
157        .with_default_spacer()
158        .with_child(stepper_row)
159        .with_default_spacer()
160}
Source

pub fn with_line_break_mode(self, mode: LineBreaking) -> Self

Builder-style method to set the LineBreaking behaviour.

Examples found in repository?
examples/textbox.rs (line 69)
67fn build_root_widget() -> impl Widget<AppState> {
68    let blurb = Label::new(EXPLAINER)
69        .with_line_break_mode(druid::widget::LineBreaking::WordWrap)
70        .padding(8.0)
71        .border(Color::grey(0.6), 2.0)
72        .rounded(5.0);
73
74    Flex::column()
75        .cross_axis_alignment(druid::widget::CrossAxisAlignment::Start)
76        .with_child(blurb)
77        .with_spacer(24.0)
78        .with_child(
79            TextBox::new()
80                .with_placeholder("Single")
81                .lens(AppState::single),
82        )
83        .with_default_spacer()
84        .with_flex_child(
85            TextBox::multiline()
86                .with_placeholder("Multi")
87                .lens(AppState::multi)
88                .expand_width(),
89            1.0,
90        )
91        .padding(8.0)
92}
More examples
Hide additional examples
examples/input_region.rs (line 50)
48    pub fn new() -> Self {
49        let info_label = Label::new(INFO_TEXT)
50            .with_line_break_mode(LineBreaking::WordWrap)
51            .padding(20.0)
52            .background(Color::rgba(0.2, 0.2, 0.2, 1.0));
53        let toggle_input_region = Button::new("Toggle Input Region")
54            .on_click(|ctx, data: &mut bool, _: &Env| {
55                *data = !*data;
56                tracing::debug!("Setting input region toggle to: {}", *data);
57                ctx.request_layout();
58            })
59            .lens(AppState::limit_input_region);
60        let toggle_titlebar = Button::new("Toggle TitleBar")
61            .on_click(|ctx, data: &mut bool, _: &Env| {
62                *data = !*data;
63                tracing::debug!("Setting titlebar visibility to: {}", *data);
64                ctx.window().show_titlebar(*data);
65                ctx.request_layout();
66            })
67            .lens(AppState::show_titlebar);
68        let toggle_always_on_top = Button::new("Toggle Always On Top")
69            .on_click(|ctx, data: &mut bool, _: &Env| {
70                *data = !*data;
71                tracing::debug!("Setting always on top to: {}", *data);
72                ctx.window().set_always_on_top(*data);
73            })
74            .lens(AppState::always_on_top);
75        let controls_flex = Flex::row()
76            .with_child(toggle_input_region)
77            .with_child(toggle_titlebar)
78            .with_child(toggle_always_on_top);
79        Self {
80            info_label: WidgetPod::new(info_label),
81            controls: WidgetPod::new(controls_flex),
82        }
83    }
examples/layout.rs (line 67)
24fn build_app() -> impl Widget<u32> {
25    // Usually we put all the widgets in one big tree using builder-style
26    // methods. Sometimes we split them up in declarations to increase
27    // readability. In this case we also have some recurring elements,
28    // we add those in a loop later on.
29    let mut col = Flex::column().with_child(
30        // The `Flex`'s first child is another Flex! In this case it is
31        // a row.
32        Flex::row()
33            // The row has its own children.
34            .with_child(
35                Label::new("One")
36                    .fix_width(60.0)
37                    .background(Color::rgb8(0x77, 0x77, 0))
38                    .border(Color::WHITE, 3.0)
39                    .center(),
40            )
41            // Spacing element that will fill all available space in
42            // between label and a button. Notice that weight is non-zero.
43            // We could have achieved a similar result with expanding the
44            // width and setting the main-axis-allignment to SpaceBetween.
45            .with_flex_spacer(1.0)
46            .with_child(Button::new("Two").padding(20.))
47            // After we added all the children, we can set some more
48            // values using builder-style methods. Since these methods
49            // dont return the original `Flex` but a SizedBox and Container
50            // respectively, we have to put these at the end.
51            .fix_height(100.0)
52            //turquoise
53            .background(Color::rgb8(0, 0x77, 0x88)),
54    );
55
56    for i in 0..5 {
57        // Give a larger weight to one of the buttons for it to
58        // occupy more space.
59        let weight = if i == 2 { 3.0 } else { 1.0 };
60        // call `expand_height` to force the buttons to use all their provided flex
61        col.add_flex_child(Button::new(format!("Button #{i}")).expand_height(), weight);
62    }
63
64    // aspect ratio box
65    let aspect_ratio_label = Label::new("This is an aspect-ratio box. Notice how the text will overflow if the box becomes too small.")
66        .with_text_color(Color::BLACK)
67        .with_line_break_mode(LineBreaking::WordWrap)
68        .center();
69    let aspect_ratio_box = AspectRatioBox::new(aspect_ratio_label, 4.0)
70        .border(Color::BLACK, 1.0)
71        .background(Color::WHITE);
72    col.add_flex_child(aspect_ratio_box.center(), 1.0);
73
74    // This method asks Druid to draw colored rectangles around our widgets,
75    // so we can visually inspect their layout rectangles.
76    col.debug_paint_layout()
77}
Source

pub fn with_text_alignment(self, alignment: TextAlignment) -> Self

Builder-style method to set the TextAlignment.

Source

pub fn draw_at(&self, ctx: &mut PaintCtx<'_, '_, '_>, origin: impl Into<Point>)

Draw this label’s text at the provided Point, without internal padding.

This is a convenience for widgets that want to use Label as a way of managing a dynamic or localized string, but want finer control over where the text is drawn.

Methods from Deref<Target = RawLabel<ArcStr>>§

Source

pub fn set_text_color(&mut self, color: impl Into<KeyOrValue<Color>>)

Set the text color.

The argument can be either a Color or a Key<Color>.

If you change this property, you are responsible for calling request_layout to ensure the label is updated.

Source

pub fn set_text_size(&mut self, size: impl Into<KeyOrValue<f64>>)

Set the text size.

The argument can be either an f64 or a Key<f64>.

If you change this property, you are responsible for calling request_layout to ensure the label is updated.

Source

pub fn set_font(&mut self, font: impl Into<KeyOrValue<FontDescriptor>>)

Set the font.

The argument can be a FontDescriptor or a Key<FontDescriptor> that refers to a font defined in the Env.

If you change this property, you are responsible for calling request_layout to ensure the label is updated.

Source

pub fn set_line_break_mode(&mut self, mode: LineBreaking)

Set the LineBreaking behaviour.

If you change this property, you are responsible for calling request_layout to ensure the label is updated.

Examples found in repository?
examples/text.rs (line 72)
63    fn update(
64        &mut self,
65        child: &mut RawLabel<AppState>,
66        ctx: &mut UpdateCtx,
67        old_data: &AppState,
68        data: &AppState,
69        env: &Env,
70    ) {
71        if old_data.line_break_mode != data.line_break_mode {
72            child.set_line_break_mode(data.line_break_mode);
73            ctx.request_layout();
74        }
75        if old_data.alignment != data.alignment {
76            child.set_text_alignment(data.alignment);
77            ctx.request_layout();
78        }
79        child.update(ctx, old_data, data, env);
80    }
Source

pub fn set_text_alignment(&mut self, alignment: TextAlignment)

Set the TextAlignment for this layout.

Examples found in repository?
examples/text.rs (line 76)
63    fn update(
64        &mut self,
65        child: &mut RawLabel<AppState>,
66        ctx: &mut UpdateCtx,
67        old_data: &AppState,
68        data: &AppState,
69        env: &Env,
70    ) {
71        if old_data.line_break_mode != data.line_break_mode {
72            child.set_line_break_mode(data.line_break_mode);
73            ctx.request_layout();
74        }
75        if old_data.alignment != data.alignment {
76            child.set_text_alignment(data.alignment);
77            ctx.request_layout();
78        }
79        child.update(ctx, old_data, data, env);
80    }
Source

pub fn draw_at(&self, ctx: &mut PaintCtx<'_, '_, '_>, origin: impl Into<Point>)

Draw this label’s text at the provided Point, without internal padding.

This is a convenience for widgets that want to use Label as a way of managing a dynamic or localized string, but want finer control over where the text is drawn.

Source

pub fn baseline_offset(&self) -> f64

Return the offset of the first baseline relative to the bottom of the widget.

Trait Implementations§

Source§

impl<T> Deref for Label<T>

Source§

type Target = RawLabel<Arc<str>>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl<T> DerefMut for Label<T>

Source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
Source§

impl<T: Data> Widget<T> for Label<T>

Source§

fn event( &mut self, _ctx: &mut EventCtx<'_, '_>, _event: &Event, _data: &mut T, _env: &Env, )

Handle an event. Read more
Source§

fn lifecycle( &mut self, ctx: &mut LifeCycleCtx<'_, '_>, event: &LifeCycle, data: &T, env: &Env, )

Handle a life cycle notification. Read more
Source§

fn update( &mut self, ctx: &mut UpdateCtx<'_, '_>, _old_data: &T, data: &T, env: &Env, )

Update the widget’s appearance in response to a change in the app’s Data or Env. Read more
Source§

fn layout( &mut self, ctx: &mut LayoutCtx<'_, '_>, bc: &BoxConstraints, _data: &T, env: &Env, ) -> Size

Compute layout. Read more
Source§

fn paint(&mut self, ctx: &mut PaintCtx<'_, '_, '_>, _data: &T, env: &Env)

Paint the widget appearance. Read more
Source§

fn compute_max_intrinsic( &mut self, axis: Axis, ctx: &mut LayoutCtx<'_, '_>, bc: &BoxConstraints, _data: &T, env: &Env, ) -> f64

Computes max intrinsic/preferred dimension of a widget on the provided axis. Read more

Auto Trait Implementations§

§

impl<T> !Freeze for Label<T>

§

impl<T> !RefUnwindSafe for Label<T>

§

impl<T> !Send for Label<T>

§

impl<T> !Sync for Label<T>

§

impl<T> Unpin for Label<T>

§

impl<T> !UnwindSafe for Label<T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> RoundFrom<T> for T

Source§

fn round_from(x: T) -> T

Performs the conversion.
Source§

impl<T, U> RoundInto<U> for T
where U: RoundFrom<T>,

Source§

fn round_into(self) -> U

Performs the conversion.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, W> TestWidgetExt<T> for W
where T: Data, W: Widget<T> + 'static,

Source§

fn record(self, recording: &Recording) -> Recorder<Self>

Available on non-WebAssembly only.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T, W> WidgetExt<T> for W
where T: Data, W: Widget<T> + 'static,

Source§

fn padding(self, insets: impl Into<KeyOrValue<Insets>>) -> Padding<T, Self>

Wrap this widget in a Padding widget with the given Insets. Read more
Source§

fn center(self) -> Align<T>

Wrap this widget in an Align widget, configured to center it.
Source§

fn align_left(self) -> Align<T>

Wrap this widget in an Align widget, configured to align left.
Source§

fn align_right(self) -> Align<T>

Wrap this widget in an Align widget, configured to align right.
Source§

fn align_vertical(self, align: UnitPoint) -> Align<T>

Wrap this widget in an Align widget, configured to align vertically.
Source§

fn align_horizontal(self, align: UnitPoint) -> Align<T>

Wrap this widget in an Align widget, configured to align horizontally.
Source§

fn fix_width(self, width: impl Into<KeyOrValue<f64>>) -> SizedBox<T>

Wrap this widget in a SizedBox with an explicit width.
Source§

fn fix_height(self, height: impl Into<KeyOrValue<f64>>) -> SizedBox<T>

Wrap this widget in a SizedBox with an explicit height.
Source§

fn fix_size( self, width: impl Into<KeyOrValue<f64>>, height: impl Into<KeyOrValue<f64>>, ) -> SizedBox<T>

Wrap this widget in an SizedBox with an explicit width and height
Source§

fn expand(self) -> SizedBox<T>

Wrap this widget in a SizedBox with an infinite width and height. Read more
Source§

fn expand_width(self) -> SizedBox<T>

Wrap this widget in a SizedBox with an infinite width. Read more
Source§

fn expand_height(self) -> SizedBox<T>

Wrap this widget in a SizedBox with an infinite width. Read more
Source§

fn background(self, brush: impl Into<BackgroundBrush<T>>) -> Container<T>

Wrap this widget in a Container with the provided background brush. Read more
Source§

fn foreground(self, brush: impl Into<BackgroundBrush<T>>) -> Container<T>

Wrap this widget in a Container with the provided foreground brush. Read more
Source§

fn border( self, color: impl Into<KeyOrValue<Color>>, width: impl Into<KeyOrValue<f64>>, ) -> Container<T>

Wrap this widget in a Container with the given border. Read more
Source§

fn env_scope(self, f: impl Fn(&mut Env, &T) + 'static) -> EnvScope<T, Self>

Wrap this widget in a EnvScope widget, modifying the parent Env with the provided closure.
Source§

fn controller<C: Controller<T, Self>>( self, controller: C, ) -> ControllerHost<Self, C>

Wrap this widget with the provided Controller.
Source§

fn on_added( self, f: impl Fn(&mut Self, &mut LifeCycleCtx<'_, '_>, &T, &Env) + 'static, ) -> ControllerHost<Self, Added<T, Self>>

Provide a closure that will be called when this widget is added to the widget tree. Read more
Source§

fn on_click( self, f: impl Fn(&mut EventCtx<'_, '_>, &mut T, &Env) + 'static, ) -> ControllerHost<Self, Click<T>>

Control the events of this widget with a Click widget. The closure provided will be called when the widget is clicked with the left mouse button. Read more
Source§

fn debug_paint_layout(self) -> EnvScope<T, Self>

Draw the layout Rects of this widget and its children.
Source§

fn debug_widget_id(self) -> EnvScope<T, Self>

Display the WidgetIds for this widget and its children, when hot. Read more
Source§

fn debug_invalidation(self) -> DebugInvalidation<T, Self>

Draw a color-changing rectangle over this widget, allowing you to see the invalidation regions.
Source§

fn debug_widget(self) -> EnvScope<T, Self>

Set the DEBUG_WIDGET env variable for this widget (and its descendants). Read more
Source§

fn lens<S: Data, L: Lens<S, T>>(self, lens: L) -> LensWrap<S, T, L, Self>

Wrap this widget in a LensWrap widget for the provided Lens.
Source§

fn with_id(self, id: WidgetId) -> IdentityWrapper<Self>

Assign the widget a specific WidgetId. Read more
Source§

fn boxed(self) -> Box<dyn Widget<T>>

Wrap this widget in a Box.
Source§

fn scroll(self) -> Scroll<T, Self>

Wrap this widget in a Scroll widget.
Source§

fn disabled_if( self, disabled_if: impl Fn(&T, &Env) -> bool + 'static, ) -> DisabledIf<T, Self>

Wrap this widget in a DisabledIf widget. Read more
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more