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>
impl<T: TextStorage> Label<T>
Source§impl<T: Data> Label<T>
impl<T: Data> Label<T>
Sourcepub fn new(text: impl Into<LabelText<T>>) -> Self
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?
More examples
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}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}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}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}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/lens.rs
- examples/blocking_function.rs
- examples/multiwin.rs
- examples/event_viewer.rs
- examples/switches.rs
- examples/text.rs
- examples/input_region.rs
- examples/transparency.rs
- examples/split_demo.rs
- examples/panels.rs
- examples/flex.rs
- examples/view_switcher.rs
- examples/layout.rs
- examples/game_of_life.rs
- examples/styled_text.rs
- examples/list.rs
- examples/sub_window.rs
Sourcepub fn dynamic(text: impl Fn(&T, &Env) -> String + 'static) -> Self
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?
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
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}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}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}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}Sourcepub fn set_text(&mut self, text: impl Into<LabelText<T>>)
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.
Sourcepub fn with_text_color(self, color: impl Into<KeyOrValue<Color>>) -> Self
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?
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
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}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}Sourcepub fn with_text_size(self, size: impl Into<KeyOrValue<f64>>) -> Self
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?
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
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}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}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}Sourcepub fn with_font(self, font: impl Into<KeyOrValue<FontDescriptor>>) -> Self
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?
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}Sourcepub fn with_line_break_mode(self, mode: LineBreaking) -> Self
pub fn with_line_break_mode(self, mode: LineBreaking) -> Self
Builder-style method to set the LineBreaking behaviour.
Examples found in repository?
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
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 }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}Sourcepub fn with_text_alignment(self, alignment: TextAlignment) -> Self
pub fn with_text_alignment(self, alignment: TextAlignment) -> Self
Builder-style method to set the TextAlignment.
Sourcepub fn draw_at(&self, ctx: &mut PaintCtx<'_, '_, '_>, origin: impl Into<Point>)
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>>§
Sourcepub fn set_text_color(&mut self, color: impl Into<KeyOrValue<Color>>)
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.
Sourcepub fn set_text_size(&mut self, size: impl Into<KeyOrValue<f64>>)
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.
Sourcepub fn set_font(&mut self, font: impl Into<KeyOrValue<FontDescriptor>>)
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.
Sourcepub fn set_line_break_mode(&mut self, mode: LineBreaking)
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?
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 }Sourcepub fn set_text_alignment(&mut self, alignment: TextAlignment)
pub fn set_text_alignment(&mut self, alignment: TextAlignment)
Set the TextAlignment for this layout.
Examples found in repository?
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 }Sourcepub fn draw_at(&self, ctx: &mut PaintCtx<'_, '_, '_>, origin: impl Into<Point>)
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.
Sourcepub fn baseline_offset(&self) -> f64
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: Data> Widget<T> for Label<T>
impl<T: Data> Widget<T> for Label<T>
Source§fn event(
&mut self,
_ctx: &mut EventCtx<'_, '_>,
_event: &Event,
_data: &mut T,
_env: &Env,
)
fn event( &mut self, _ctx: &mut EventCtx<'_, '_>, _event: &Event, _data: &mut T, _env: &Env, )
Source§fn lifecycle(
&mut self,
ctx: &mut LifeCycleCtx<'_, '_>,
event: &LifeCycle,
data: &T,
env: &Env,
)
fn lifecycle( &mut self, ctx: &mut LifeCycleCtx<'_, '_>, event: &LifeCycle, data: &T, env: &Env, )
Source§fn layout(
&mut self,
ctx: &mut LayoutCtx<'_, '_>,
bc: &BoxConstraints,
_data: &T,
env: &Env,
) -> Size
fn layout( &mut self, ctx: &mut LayoutCtx<'_, '_>, bc: &BoxConstraints, _data: &T, env: &Env, ) -> Size
Source§fn paint(&mut self, ctx: &mut PaintCtx<'_, '_, '_>, _data: &T, env: &Env)
fn paint(&mut self, ctx: &mut PaintCtx<'_, '_, '_>, _data: &T, env: &Env)
Source§fn compute_max_intrinsic(
&mut self,
axis: Axis,
ctx: &mut LayoutCtx<'_, '_>,
bc: &BoxConstraints,
_data: &T,
env: &Env,
) -> f64
fn compute_max_intrinsic( &mut self, axis: Axis, ctx: &mut LayoutCtx<'_, '_>, bc: &BoxConstraints, _data: &T, env: &Env, ) -> f64
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> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T, U> RoundInto<U> for Twhere
U: RoundFrom<T>,
impl<T, U> RoundInto<U> for Twhere
U: RoundFrom<T>,
Source§fn round_into(self) -> U
fn round_into(self) -> U
Source§impl<T, W> TestWidgetExt<T> for W
impl<T, W> TestWidgetExt<T> for W
Source§impl<T, W> WidgetExt<T> for W
impl<T, W> WidgetExt<T> for W
Source§fn align_left(self) -> Align<T>
fn align_left(self) -> Align<T>
Align widget, configured to align left.Source§fn align_right(self) -> Align<T>
fn align_right(self) -> Align<T>
Align widget, configured to align right.Source§fn align_vertical(self, align: UnitPoint) -> Align<T>
fn align_vertical(self, align: UnitPoint) -> Align<T>
Align widget, configured to align vertically.Source§fn align_horizontal(self, align: UnitPoint) -> Align<T>
fn align_horizontal(self, align: UnitPoint) -> Align<T>
Align widget, configured to align horizontally.Source§fn fix_width(self, width: impl Into<KeyOrValue<f64>>) -> SizedBox<T>
fn fix_width(self, width: impl Into<KeyOrValue<f64>>) -> SizedBox<T>
SizedBox with an explicit width.Source§fn fix_height(self, height: impl Into<KeyOrValue<f64>>) -> SizedBox<T>
fn fix_height(self, height: impl Into<KeyOrValue<f64>>) -> SizedBox<T>
SizedBox with an explicit height.Source§fn fix_size(
self,
width: impl Into<KeyOrValue<f64>>,
height: impl Into<KeyOrValue<f64>>,
) -> SizedBox<T>
fn fix_size( self, width: impl Into<KeyOrValue<f64>>, height: impl Into<KeyOrValue<f64>>, ) -> SizedBox<T>
SizedBox with an explicit width and heightSource§fn expand_width(self) -> SizedBox<T>
fn expand_width(self) -> SizedBox<T>
Source§fn expand_height(self) -> SizedBox<T>
fn expand_height(self) -> SizedBox<T>
Source§fn background(self, brush: impl Into<BackgroundBrush<T>>) -> Container<T>
fn background(self, brush: impl Into<BackgroundBrush<T>>) -> Container<T>
Source§fn foreground(self, brush: impl Into<BackgroundBrush<T>>) -> Container<T>
fn foreground(self, brush: impl Into<BackgroundBrush<T>>) -> Container<T>
Source§fn border(
self,
color: impl Into<KeyOrValue<Color>>,
width: impl Into<KeyOrValue<f64>>,
) -> Container<T>
fn border( self, color: impl Into<KeyOrValue<Color>>, width: impl Into<KeyOrValue<f64>>, ) -> Container<T>
Source§fn controller<C: Controller<T, Self>>(
self,
controller: C,
) -> ControllerHost<Self, C>
fn controller<C: Controller<T, Self>>( self, controller: C, ) -> ControllerHost<Self, C>
Controller.Source§fn on_added(
self,
f: impl Fn(&mut Self, &mut LifeCycleCtx<'_, '_>, &T, &Env) + 'static,
) -> ControllerHost<Self, Added<T, Self>>
fn on_added( self, f: impl Fn(&mut Self, &mut LifeCycleCtx<'_, '_>, &T, &Env) + 'static, ) -> ControllerHost<Self, Added<T, Self>>
Source§fn on_click(
self,
f: impl Fn(&mut EventCtx<'_, '_>, &mut T, &Env) + 'static,
) -> ControllerHost<Self, Click<T>>
fn on_click( self, f: impl Fn(&mut EventCtx<'_, '_>, &mut T, &Env) + 'static, ) -> ControllerHost<Self, Click<T>>
Source§fn debug_paint_layout(self) -> EnvScope<T, Self>
fn debug_paint_layout(self) -> EnvScope<T, Self>
layout Rects of this widget and its children.Source§fn debug_widget_id(self) -> EnvScope<T, Self>
fn debug_widget_id(self) -> EnvScope<T, Self>
WidgetIds for this widget and its children, when hot. Read moreSource§fn debug_invalidation(self) -> DebugInvalidation<T, Self>
fn debug_invalidation(self) -> DebugInvalidation<T, Self>
Source§fn debug_widget(self) -> EnvScope<T, Self>
fn debug_widget(self) -> EnvScope<T, Self>
DEBUG_WIDGET env variable for this widget (and its descendants). Read moreSource§fn with_id(self, id: WidgetId) -> IdentityWrapper<Self>
fn with_id(self, id: WidgetId) -> IdentityWrapper<Self>
Source§fn disabled_if(
self,
disabled_if: impl Fn(&T, &Env) -> bool + 'static,
) -> DisabledIf<T, Self>
fn disabled_if( self, disabled_if: impl Fn(&T, &Env) -> bool + 'static, ) -> DisabledIf<T, Self>
DisabledIf widget. Read more