pub struct Stepper { /* private fields */ }
Expand description
A stepper widget for step-wise increasing and decreasing a value.
Implementations§
source§impl Stepper
impl Stepper
sourcepub fn new() -> Self
pub fn new() -> Self
Create a new Stepper
.
Examples found in repository?
examples/flex.rs (line 224)
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
fn make_spacer_select() -> impl Widget<Params> {
Flex::column()
.cross_axis_alignment(CrossAxisAlignment::Start)
.with_child(Label::new("Insert Spacers:"))
.with_default_spacer()
.with_child(RadioGroup::column(SPACER_OPTIONS.to_vec()).lens(Params::spacers))
.with_default_spacer()
.with_child(
Flex::row()
.with_child(
TextBox::new()
.with_formatter(ParseFormatter::new())
.lens(Params::spacer_size)
.fix_width(60.0),
)
.with_spacer(druid::theme::WIDGET_CONTROL_COMPONENT_PADDING)
.with_child(
Stepper::new()
.with_range(2.0, 50.0)
.with_step(2.0)
.lens(Params::spacer_size),
),
)
}
fn space_if_needed<T: Data>(flex: &mut Flex<T>, params: &Params) {
match params.spacers {
Spacers::None => (),
Spacers::Default => flex.add_default_spacer(),
Spacers::Fixed => flex.add_spacer(params.spacer_size),
Spacers::Flex => flex.add_flex_spacer(1.0),
}
}
fn build_widget(state: &Params) -> Box<dyn Widget<AppState>> {
let mut flex = match state.axis {
FlexType::Column => Flex::column(),
FlexType::Row => Flex::row(),
}
.cross_axis_alignment(state.cross_alignment)
.main_axis_alignment(state.main_alignment)
.must_fill_main_axis(state.fill_major_axis);
flex.add_child(
TextBox::new()
.with_placeholder("Sample text")
.lens(DemoState::input_text),
);
space_if_needed(&mut flex, state);
flex.add_child(
Button::new("Clear").on_click(|_ctx, data: &mut DemoState, _env| {
data.input_text.clear();
data.enabled = false;
data.volume = 0.0;
}),
);
space_if_needed(&mut flex, state);
flex.add_child(
Label::new(|data: &DemoState, _: &Env| data.input_text.clone()).with_text_size(32.0),
);
space_if_needed(&mut flex, state);
flex.add_child(Checkbox::new("Demo").lens(DemoState::enabled));
space_if_needed(&mut flex, state);
flex.add_child(Switch::new().lens(DemoState::enabled));
space_if_needed(&mut flex, state);
flex.add_child(Slider::new().lens(DemoState::volume));
space_if_needed(&mut flex, state);
flex.add_child(ProgressBar::new().lens(DemoState::volume));
space_if_needed(&mut flex, state);
flex.add_child(
Stepper::new()
.with_range(0.0, 1.0)
.with_step(0.1)
.with_wraparound(true)
.lens(DemoState::volume),
);
let mut flex = SizedBox::new(flex);
if state.fix_minor_axis {
match state.axis {
FlexType::Row => flex = flex.height(200.),
FlexType::Column => flex = flex.width(200.),
}
}
if state.fix_major_axis {
match state.axis {
FlexType::Row => flex = flex.width(600.),
FlexType::Column => flex = flex.height(300.),
}
}
let flex = flex
.padding(8.0)
.border(Color::grey(0.6), 2.0)
.rounded(5.0)
.lens(AppState::demo_state);
if state.debug_layout {
flex.debug_paint_layout().boxed()
} else {
flex.boxed()
}
}
More examples
examples/switches.rs (line 46)
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
fn build_widget() -> impl Widget<DemoState> {
let mut col = Flex::column();
let mut row = Flex::row();
let switch = LensWrap::new(Switch::new(), DemoState::value);
let check_box = LensWrap::new(Checkbox::new(""), DemoState::value);
let switch_label = Label::new("Setting label");
row.add_child(Padding::new(5.0, switch_label));
row.add_child(Padding::new(5.0, switch));
row.add_child(Padding::new(5.0, check_box));
let stepper = LensWrap::new(
Stepper::new()
.with_range(0.0, 10.0)
.with_step(0.5)
.with_wraparound(false),
DemoState::stepper_value,
);
let mut textbox_row = Flex::row();
// TODO: Replace Parse usage with TextBox::with_formatter
#[allow(deprecated)]
let textbox = LensWrap::new(
Parse::new(TextBox::new()),
DemoState::stepper_value.map(|x| Some(*x), |x, y| *x = y.unwrap_or(0.0)),
);
textbox_row.add_child(Padding::new(5.0, textbox));
textbox_row.add_child(Padding::new(5.0, stepper.center()));
let mut label_row = Flex::row();
let label = Label::new(|data: &DemoState, _env: &_| {
format!("Stepper value: {0:.2}", data.stepper_value)
});
label_row.add_child(Padding::new(5.0, label));
col.set_main_axis_alignment(MainAxisAlignment::Center);
col.add_child(Padding::new(5.0, row));
col.add_child(Padding::new(5.0, textbox_row));
col.add_child(Padding::new(5.0, label_row));
col.center()
}
examples/disabled.rs (line 72)
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
fn main_widget() -> impl Widget<AppData> {
Flex::column()
.with_child(named_child("text:", TextBox::new().lens(AppData::text)))
.with_default_spacer()
.with_child(
named_child("text (disabled):", TextBox::new().lens(AppData::text))
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_child(named_child("text:", TextBox::new().lens(AppData::text)))
.with_default_spacer()
.with_child(
named_child("text (disabled):", TextBox::new().lens(AppData::text))
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_default_spacer()
.with_child(
named_child(
"value (disabled):",
Slider::new().with_range(0.0, 10.0).lens(AppData::value),
)
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_child(
named_child(
"value (disabled):",
Stepper::new()
.with_range(0.0, 10.0)
.with_step(0.5)
.lens(AppData::value),
)
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_child(
named_child(
"option (disabled):",
Checkbox::new("option").lens(AppData::option),
)
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_child(
named_child("option (disabled):", Switch::new().lens(AppData::option))
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_child(
Flex::row()
.with_child(
Button::new("-")
.on_click(|_, data: &mut f64, _| *data -= 1.0)
.disabled_if(|data, _| *data < 1.0),
)
.with_default_spacer()
.with_child(Label::dynamic(|data: &f64, _| data.to_string()))
.with_default_spacer()
.with_child(
Button::new("+")
.on_click(|_, data: &mut f64, _| *data += 1.0)
.disabled_if(|data, _| *data > 9.0),
)
.lens(AppData::value)
.disabled_if(|data: &AppData, _| data.disabled),
)
.with_default_spacer()
.with_default_spacer()
.with_default_spacer()
.with_child(Checkbox::new("disabled").lens(AppData::disabled))
.with_default_spacer()
.cross_axis_alignment(CrossAxisAlignment::End)
.align_horizontal(UnitPoint::CENTER)
}
examples/styled_text.rs (line 125)
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
fn ui_builder() -> impl Widget<AppData> {
let my_painter = Painter::new(|ctx, _, _| {
let bounds = ctx.size().to_rect();
if ctx.is_hot() {
ctx.fill(bounds, &Color::rgba8(0, 0, 0, 128));
}
if ctx.is_active() {
ctx.stroke(bounds, &Color::WHITE, 2.0);
}
});
// This is Druid's default text style.
// It's set by theme::LABEL_COLOR and theme::UI_FONT
let label =
Label::new(|data: &String, _env: &_| format!("Default: {data}")).lens(AppData::text);
// The text_color, text_size, and font builder methods can override the
// defaults provided by the theme by passing in a Key or a concrete value.
//
// In this example, text_color receives a Key from the theme, text_size
// gets a custom key which we set with the env_scope wrapper, and the
// default font key (theme::FONT_NAME) is overridden in the env_scope
// wrapper. (Like text_color and text_size, the font can be set using the
// with_font builder method, but overriding here makes it easy to fall back
// to the default font)
let styled_label = Label::new(|data: &AppData, _env: &_| format!("{data}"))
.with_text_color(theme::PRIMARY_LIGHT)
.with_font(MY_CUSTOM_FONT)
.background(my_painter)
.on_click(|_, data, _| {
data.size *= 1.1;
})
.env_scope(|env: &mut druid::Env, data: &AppData| {
let new_font = if data.mono {
FontDescriptor::new(FontFamily::MONOSPACE)
} else {
FontDescriptor::new(FontFamily::SYSTEM_UI)
}
.with_size(data.size);
env.set(MY_CUSTOM_FONT, new_font);
});
let labels = Scroll::new(
Flex::column()
.cross_axis_alignment(CrossAxisAlignment::Start)
.with_child(label)
.with_default_spacer()
.with_child(styled_label),
)
.expand_height()
.fix_width(COLUMN_WIDTH);
let stepper = Stepper::new()
.with_range(0.0, 100.0)
.with_step(1.0)
.with_wraparound(false)
.lens(AppData::size);
// TODO: Replace Parse usage with TextBox::with_formatter
#[allow(deprecated)]
let stepper_textbox = LensWrap::new(
Parse::new(TextBox::new()),
AppData::size.map(|x| Some(*x), |x, y| *x = y.unwrap_or(24.0)),
);
let mono_checkbox = Checkbox::new("Monospace").lens(AppData::mono);
let stepper_row = Flex::row()
.with_child(stepper_textbox)
.with_child(stepper)
.with_default_spacer()
.with_child(mono_checkbox);
let input = TextBox::multiline()
.with_placeholder("Your sample text here :)")
.fix_width(COLUMN_WIDTH)
.fix_height(140.0)
.lens(AppData::text);
Flex::column()
.main_axis_alignment(MainAxisAlignment::Center)
.with_default_spacer()
.with_flex_child(labels, 1.0)
.with_default_spacer()
.with_child(input)
.with_default_spacer()
.with_child(stepper_row)
.with_default_spacer()
}
sourcepub fn with_range(self, min: f64, max: f64) -> Self
pub fn with_range(self, min: f64, max: f64) -> Self
Set the range covered by this slider.
The default range is std::f64::MIN..std::f64::MAX
.
Examples found in repository?
examples/flex.rs (line 225)
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
fn make_spacer_select() -> impl Widget<Params> {
Flex::column()
.cross_axis_alignment(CrossAxisAlignment::Start)
.with_child(Label::new("Insert Spacers:"))
.with_default_spacer()
.with_child(RadioGroup::column(SPACER_OPTIONS.to_vec()).lens(Params::spacers))
.with_default_spacer()
.with_child(
Flex::row()
.with_child(
TextBox::new()
.with_formatter(ParseFormatter::new())
.lens(Params::spacer_size)
.fix_width(60.0),
)
.with_spacer(druid::theme::WIDGET_CONTROL_COMPONENT_PADDING)
.with_child(
Stepper::new()
.with_range(2.0, 50.0)
.with_step(2.0)
.lens(Params::spacer_size),
),
)
}
fn space_if_needed<T: Data>(flex: &mut Flex<T>, params: &Params) {
match params.spacers {
Spacers::None => (),
Spacers::Default => flex.add_default_spacer(),
Spacers::Fixed => flex.add_spacer(params.spacer_size),
Spacers::Flex => flex.add_flex_spacer(1.0),
}
}
fn build_widget(state: &Params) -> Box<dyn Widget<AppState>> {
let mut flex = match state.axis {
FlexType::Column => Flex::column(),
FlexType::Row => Flex::row(),
}
.cross_axis_alignment(state.cross_alignment)
.main_axis_alignment(state.main_alignment)
.must_fill_main_axis(state.fill_major_axis);
flex.add_child(
TextBox::new()
.with_placeholder("Sample text")
.lens(DemoState::input_text),
);
space_if_needed(&mut flex, state);
flex.add_child(
Button::new("Clear").on_click(|_ctx, data: &mut DemoState, _env| {
data.input_text.clear();
data.enabled = false;
data.volume = 0.0;
}),
);
space_if_needed(&mut flex, state);
flex.add_child(
Label::new(|data: &DemoState, _: &Env| data.input_text.clone()).with_text_size(32.0),
);
space_if_needed(&mut flex, state);
flex.add_child(Checkbox::new("Demo").lens(DemoState::enabled));
space_if_needed(&mut flex, state);
flex.add_child(Switch::new().lens(DemoState::enabled));
space_if_needed(&mut flex, state);
flex.add_child(Slider::new().lens(DemoState::volume));
space_if_needed(&mut flex, state);
flex.add_child(ProgressBar::new().lens(DemoState::volume));
space_if_needed(&mut flex, state);
flex.add_child(
Stepper::new()
.with_range(0.0, 1.0)
.with_step(0.1)
.with_wraparound(true)
.lens(DemoState::volume),
);
let mut flex = SizedBox::new(flex);
if state.fix_minor_axis {
match state.axis {
FlexType::Row => flex = flex.height(200.),
FlexType::Column => flex = flex.width(200.),
}
}
if state.fix_major_axis {
match state.axis {
FlexType::Row => flex = flex.width(600.),
FlexType::Column => flex = flex.height(300.),
}
}
let flex = flex
.padding(8.0)
.border(Color::grey(0.6), 2.0)
.rounded(5.0)
.lens(AppState::demo_state);
if state.debug_layout {
flex.debug_paint_layout().boxed()
} else {
flex.boxed()
}
}
More examples
examples/switches.rs (line 47)
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
fn build_widget() -> impl Widget<DemoState> {
let mut col = Flex::column();
let mut row = Flex::row();
let switch = LensWrap::new(Switch::new(), DemoState::value);
let check_box = LensWrap::new(Checkbox::new(""), DemoState::value);
let switch_label = Label::new("Setting label");
row.add_child(Padding::new(5.0, switch_label));
row.add_child(Padding::new(5.0, switch));
row.add_child(Padding::new(5.0, check_box));
let stepper = LensWrap::new(
Stepper::new()
.with_range(0.0, 10.0)
.with_step(0.5)
.with_wraparound(false),
DemoState::stepper_value,
);
let mut textbox_row = Flex::row();
// TODO: Replace Parse usage with TextBox::with_formatter
#[allow(deprecated)]
let textbox = LensWrap::new(
Parse::new(TextBox::new()),
DemoState::stepper_value.map(|x| Some(*x), |x, y| *x = y.unwrap_or(0.0)),
);
textbox_row.add_child(Padding::new(5.0, textbox));
textbox_row.add_child(Padding::new(5.0, stepper.center()));
let mut label_row = Flex::row();
let label = Label::new(|data: &DemoState, _env: &_| {
format!("Stepper value: {0:.2}", data.stepper_value)
});
label_row.add_child(Padding::new(5.0, label));
col.set_main_axis_alignment(MainAxisAlignment::Center);
col.add_child(Padding::new(5.0, row));
col.add_child(Padding::new(5.0, textbox_row));
col.add_child(Padding::new(5.0, label_row));
col.center()
}
examples/disabled.rs (line 73)
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
fn main_widget() -> impl Widget<AppData> {
Flex::column()
.with_child(named_child("text:", TextBox::new().lens(AppData::text)))
.with_default_spacer()
.with_child(
named_child("text (disabled):", TextBox::new().lens(AppData::text))
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_child(named_child("text:", TextBox::new().lens(AppData::text)))
.with_default_spacer()
.with_child(
named_child("text (disabled):", TextBox::new().lens(AppData::text))
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_default_spacer()
.with_child(
named_child(
"value (disabled):",
Slider::new().with_range(0.0, 10.0).lens(AppData::value),
)
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_child(
named_child(
"value (disabled):",
Stepper::new()
.with_range(0.0, 10.0)
.with_step(0.5)
.lens(AppData::value),
)
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_child(
named_child(
"option (disabled):",
Checkbox::new("option").lens(AppData::option),
)
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_child(
named_child("option (disabled):", Switch::new().lens(AppData::option))
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_child(
Flex::row()
.with_child(
Button::new("-")
.on_click(|_, data: &mut f64, _| *data -= 1.0)
.disabled_if(|data, _| *data < 1.0),
)
.with_default_spacer()
.with_child(Label::dynamic(|data: &f64, _| data.to_string()))
.with_default_spacer()
.with_child(
Button::new("+")
.on_click(|_, data: &mut f64, _| *data += 1.0)
.disabled_if(|data, _| *data > 9.0),
)
.lens(AppData::value)
.disabled_if(|data: &AppData, _| data.disabled),
)
.with_default_spacer()
.with_default_spacer()
.with_default_spacer()
.with_child(Checkbox::new("disabled").lens(AppData::disabled))
.with_default_spacer()
.cross_axis_alignment(CrossAxisAlignment::End)
.align_horizontal(UnitPoint::CENTER)
}
examples/styled_text.rs (line 126)
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
fn ui_builder() -> impl Widget<AppData> {
let my_painter = Painter::new(|ctx, _, _| {
let bounds = ctx.size().to_rect();
if ctx.is_hot() {
ctx.fill(bounds, &Color::rgba8(0, 0, 0, 128));
}
if ctx.is_active() {
ctx.stroke(bounds, &Color::WHITE, 2.0);
}
});
// This is Druid's default text style.
// It's set by theme::LABEL_COLOR and theme::UI_FONT
let label =
Label::new(|data: &String, _env: &_| format!("Default: {data}")).lens(AppData::text);
// The text_color, text_size, and font builder methods can override the
// defaults provided by the theme by passing in a Key or a concrete value.
//
// In this example, text_color receives a Key from the theme, text_size
// gets a custom key which we set with the env_scope wrapper, and the
// default font key (theme::FONT_NAME) is overridden in the env_scope
// wrapper. (Like text_color and text_size, the font can be set using the
// with_font builder method, but overriding here makes it easy to fall back
// to the default font)
let styled_label = Label::new(|data: &AppData, _env: &_| format!("{data}"))
.with_text_color(theme::PRIMARY_LIGHT)
.with_font(MY_CUSTOM_FONT)
.background(my_painter)
.on_click(|_, data, _| {
data.size *= 1.1;
})
.env_scope(|env: &mut druid::Env, data: &AppData| {
let new_font = if data.mono {
FontDescriptor::new(FontFamily::MONOSPACE)
} else {
FontDescriptor::new(FontFamily::SYSTEM_UI)
}
.with_size(data.size);
env.set(MY_CUSTOM_FONT, new_font);
});
let labels = Scroll::new(
Flex::column()
.cross_axis_alignment(CrossAxisAlignment::Start)
.with_child(label)
.with_default_spacer()
.with_child(styled_label),
)
.expand_height()
.fix_width(COLUMN_WIDTH);
let stepper = Stepper::new()
.with_range(0.0, 100.0)
.with_step(1.0)
.with_wraparound(false)
.lens(AppData::size);
// TODO: Replace Parse usage with TextBox::with_formatter
#[allow(deprecated)]
let stepper_textbox = LensWrap::new(
Parse::new(TextBox::new()),
AppData::size.map(|x| Some(*x), |x, y| *x = y.unwrap_or(24.0)),
);
let mono_checkbox = Checkbox::new("Monospace").lens(AppData::mono);
let stepper_row = Flex::row()
.with_child(stepper_textbox)
.with_child(stepper)
.with_default_spacer()
.with_child(mono_checkbox);
let input = TextBox::multiline()
.with_placeholder("Your sample text here :)")
.fix_width(COLUMN_WIDTH)
.fix_height(140.0)
.lens(AppData::text);
Flex::column()
.main_axis_alignment(MainAxisAlignment::Center)
.with_default_spacer()
.with_flex_child(labels, 1.0)
.with_default_spacer()
.with_child(input)
.with_default_spacer()
.with_child(stepper_row)
.with_default_spacer()
}
sourcepub fn with_step(self, step: f64) -> Self
pub fn with_step(self, step: f64) -> Self
Set the steppers amount by which the value increases or decreases.
The default step is 1.0
.
Examples found in repository?
examples/flex.rs (line 226)
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
fn make_spacer_select() -> impl Widget<Params> {
Flex::column()
.cross_axis_alignment(CrossAxisAlignment::Start)
.with_child(Label::new("Insert Spacers:"))
.with_default_spacer()
.with_child(RadioGroup::column(SPACER_OPTIONS.to_vec()).lens(Params::spacers))
.with_default_spacer()
.with_child(
Flex::row()
.with_child(
TextBox::new()
.with_formatter(ParseFormatter::new())
.lens(Params::spacer_size)
.fix_width(60.0),
)
.with_spacer(druid::theme::WIDGET_CONTROL_COMPONENT_PADDING)
.with_child(
Stepper::new()
.with_range(2.0, 50.0)
.with_step(2.0)
.lens(Params::spacer_size),
),
)
}
fn space_if_needed<T: Data>(flex: &mut Flex<T>, params: &Params) {
match params.spacers {
Spacers::None => (),
Spacers::Default => flex.add_default_spacer(),
Spacers::Fixed => flex.add_spacer(params.spacer_size),
Spacers::Flex => flex.add_flex_spacer(1.0),
}
}
fn build_widget(state: &Params) -> Box<dyn Widget<AppState>> {
let mut flex = match state.axis {
FlexType::Column => Flex::column(),
FlexType::Row => Flex::row(),
}
.cross_axis_alignment(state.cross_alignment)
.main_axis_alignment(state.main_alignment)
.must_fill_main_axis(state.fill_major_axis);
flex.add_child(
TextBox::new()
.with_placeholder("Sample text")
.lens(DemoState::input_text),
);
space_if_needed(&mut flex, state);
flex.add_child(
Button::new("Clear").on_click(|_ctx, data: &mut DemoState, _env| {
data.input_text.clear();
data.enabled = false;
data.volume = 0.0;
}),
);
space_if_needed(&mut flex, state);
flex.add_child(
Label::new(|data: &DemoState, _: &Env| data.input_text.clone()).with_text_size(32.0),
);
space_if_needed(&mut flex, state);
flex.add_child(Checkbox::new("Demo").lens(DemoState::enabled));
space_if_needed(&mut flex, state);
flex.add_child(Switch::new().lens(DemoState::enabled));
space_if_needed(&mut flex, state);
flex.add_child(Slider::new().lens(DemoState::volume));
space_if_needed(&mut flex, state);
flex.add_child(ProgressBar::new().lens(DemoState::volume));
space_if_needed(&mut flex, state);
flex.add_child(
Stepper::new()
.with_range(0.0, 1.0)
.with_step(0.1)
.with_wraparound(true)
.lens(DemoState::volume),
);
let mut flex = SizedBox::new(flex);
if state.fix_minor_axis {
match state.axis {
FlexType::Row => flex = flex.height(200.),
FlexType::Column => flex = flex.width(200.),
}
}
if state.fix_major_axis {
match state.axis {
FlexType::Row => flex = flex.width(600.),
FlexType::Column => flex = flex.height(300.),
}
}
let flex = flex
.padding(8.0)
.border(Color::grey(0.6), 2.0)
.rounded(5.0)
.lens(AppState::demo_state);
if state.debug_layout {
flex.debug_paint_layout().boxed()
} else {
flex.boxed()
}
}
More examples
examples/switches.rs (line 48)
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
fn build_widget() -> impl Widget<DemoState> {
let mut col = Flex::column();
let mut row = Flex::row();
let switch = LensWrap::new(Switch::new(), DemoState::value);
let check_box = LensWrap::new(Checkbox::new(""), DemoState::value);
let switch_label = Label::new("Setting label");
row.add_child(Padding::new(5.0, switch_label));
row.add_child(Padding::new(5.0, switch));
row.add_child(Padding::new(5.0, check_box));
let stepper = LensWrap::new(
Stepper::new()
.with_range(0.0, 10.0)
.with_step(0.5)
.with_wraparound(false),
DemoState::stepper_value,
);
let mut textbox_row = Flex::row();
// TODO: Replace Parse usage with TextBox::with_formatter
#[allow(deprecated)]
let textbox = LensWrap::new(
Parse::new(TextBox::new()),
DemoState::stepper_value.map(|x| Some(*x), |x, y| *x = y.unwrap_or(0.0)),
);
textbox_row.add_child(Padding::new(5.0, textbox));
textbox_row.add_child(Padding::new(5.0, stepper.center()));
let mut label_row = Flex::row();
let label = Label::new(|data: &DemoState, _env: &_| {
format!("Stepper value: {0:.2}", data.stepper_value)
});
label_row.add_child(Padding::new(5.0, label));
col.set_main_axis_alignment(MainAxisAlignment::Center);
col.add_child(Padding::new(5.0, row));
col.add_child(Padding::new(5.0, textbox_row));
col.add_child(Padding::new(5.0, label_row));
col.center()
}
examples/disabled.rs (line 74)
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
fn main_widget() -> impl Widget<AppData> {
Flex::column()
.with_child(named_child("text:", TextBox::new().lens(AppData::text)))
.with_default_spacer()
.with_child(
named_child("text (disabled):", TextBox::new().lens(AppData::text))
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_child(named_child("text:", TextBox::new().lens(AppData::text)))
.with_default_spacer()
.with_child(
named_child("text (disabled):", TextBox::new().lens(AppData::text))
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_default_spacer()
.with_child(
named_child(
"value (disabled):",
Slider::new().with_range(0.0, 10.0).lens(AppData::value),
)
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_child(
named_child(
"value (disabled):",
Stepper::new()
.with_range(0.0, 10.0)
.with_step(0.5)
.lens(AppData::value),
)
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_child(
named_child(
"option (disabled):",
Checkbox::new("option").lens(AppData::option),
)
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_child(
named_child("option (disabled):", Switch::new().lens(AppData::option))
.disabled_if(|data, _| data.disabled),
)
.with_default_spacer()
.with_child(
Flex::row()
.with_child(
Button::new("-")
.on_click(|_, data: &mut f64, _| *data -= 1.0)
.disabled_if(|data, _| *data < 1.0),
)
.with_default_spacer()
.with_child(Label::dynamic(|data: &f64, _| data.to_string()))
.with_default_spacer()
.with_child(
Button::new("+")
.on_click(|_, data: &mut f64, _| *data += 1.0)
.disabled_if(|data, _| *data > 9.0),
)
.lens(AppData::value)
.disabled_if(|data: &AppData, _| data.disabled),
)
.with_default_spacer()
.with_default_spacer()
.with_default_spacer()
.with_child(Checkbox::new("disabled").lens(AppData::disabled))
.with_default_spacer()
.cross_axis_alignment(CrossAxisAlignment::End)
.align_horizontal(UnitPoint::CENTER)
}
examples/styled_text.rs (line 127)
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
fn ui_builder() -> impl Widget<AppData> {
let my_painter = Painter::new(|ctx, _, _| {
let bounds = ctx.size().to_rect();
if ctx.is_hot() {
ctx.fill(bounds, &Color::rgba8(0, 0, 0, 128));
}
if ctx.is_active() {
ctx.stroke(bounds, &Color::WHITE, 2.0);
}
});
// This is Druid's default text style.
// It's set by theme::LABEL_COLOR and theme::UI_FONT
let label =
Label::new(|data: &String, _env: &_| format!("Default: {data}")).lens(AppData::text);
// The text_color, text_size, and font builder methods can override the
// defaults provided by the theme by passing in a Key or a concrete value.
//
// In this example, text_color receives a Key from the theme, text_size
// gets a custom key which we set with the env_scope wrapper, and the
// default font key (theme::FONT_NAME) is overridden in the env_scope
// wrapper. (Like text_color and text_size, the font can be set using the
// with_font builder method, but overriding here makes it easy to fall back
// to the default font)
let styled_label = Label::new(|data: &AppData, _env: &_| format!("{data}"))
.with_text_color(theme::PRIMARY_LIGHT)
.with_font(MY_CUSTOM_FONT)
.background(my_painter)
.on_click(|_, data, _| {
data.size *= 1.1;
})
.env_scope(|env: &mut druid::Env, data: &AppData| {
let new_font = if data.mono {
FontDescriptor::new(FontFamily::MONOSPACE)
} else {
FontDescriptor::new(FontFamily::SYSTEM_UI)
}
.with_size(data.size);
env.set(MY_CUSTOM_FONT, new_font);
});
let labels = Scroll::new(
Flex::column()
.cross_axis_alignment(CrossAxisAlignment::Start)
.with_child(label)
.with_default_spacer()
.with_child(styled_label),
)
.expand_height()
.fix_width(COLUMN_WIDTH);
let stepper = Stepper::new()
.with_range(0.0, 100.0)
.with_step(1.0)
.with_wraparound(false)
.lens(AppData::size);
// TODO: Replace Parse usage with TextBox::with_formatter
#[allow(deprecated)]
let stepper_textbox = LensWrap::new(
Parse::new(TextBox::new()),
AppData::size.map(|x| Some(*x), |x, y| *x = y.unwrap_or(24.0)),
);
let mono_checkbox = Checkbox::new("Monospace").lens(AppData::mono);
let stepper_row = Flex::row()
.with_child(stepper_textbox)
.with_child(stepper)
.with_default_spacer()
.with_child(mono_checkbox);
let input = TextBox::multiline()
.with_placeholder("Your sample text here :)")
.fix_width(COLUMN_WIDTH)
.fix_height(140.0)
.lens(AppData::text);
Flex::column()
.main_axis_alignment(MainAxisAlignment::Center)
.with_default_spacer()
.with_flex_child(labels, 1.0)
.with_default_spacer()
.with_child(input)
.with_default_spacer()
.with_child(stepper_row)
.with_default_spacer()
}
sourcepub fn with_wraparound(self, wrap: bool) -> Self
pub fn with_wraparound(self, wrap: bool) -> Self
Set whether the stepper should wrap around the minimum/maximum values.
When wraparound is enabled incrementing above max behaves like this:
- if the previous value is < max it becomes max
- if the previous value is = max it becomes min Same logic applies for decrementing
The default is false
.
Examples found in repository?
examples/switches.rs (line 49)
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
fn build_widget() -> impl Widget<DemoState> {
let mut col = Flex::column();
let mut row = Flex::row();
let switch = LensWrap::new(Switch::new(), DemoState::value);
let check_box = LensWrap::new(Checkbox::new(""), DemoState::value);
let switch_label = Label::new("Setting label");
row.add_child(Padding::new(5.0, switch_label));
row.add_child(Padding::new(5.0, switch));
row.add_child(Padding::new(5.0, check_box));
let stepper = LensWrap::new(
Stepper::new()
.with_range(0.0, 10.0)
.with_step(0.5)
.with_wraparound(false),
DemoState::stepper_value,
);
let mut textbox_row = Flex::row();
// TODO: Replace Parse usage with TextBox::with_formatter
#[allow(deprecated)]
let textbox = LensWrap::new(
Parse::new(TextBox::new()),
DemoState::stepper_value.map(|x| Some(*x), |x, y| *x = y.unwrap_or(0.0)),
);
textbox_row.add_child(Padding::new(5.0, textbox));
textbox_row.add_child(Padding::new(5.0, stepper.center()));
let mut label_row = Flex::row();
let label = Label::new(|data: &DemoState, _env: &_| {
format!("Stepper value: {0:.2}", data.stepper_value)
});
label_row.add_child(Padding::new(5.0, label));
col.set_main_axis_alignment(MainAxisAlignment::Center);
col.add_child(Padding::new(5.0, row));
col.add_child(Padding::new(5.0, textbox_row));
col.add_child(Padding::new(5.0, label_row));
col.center()
}
More examples
examples/flex.rs (line 283)
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
fn build_widget(state: &Params) -> Box<dyn Widget<AppState>> {
let mut flex = match state.axis {
FlexType::Column => Flex::column(),
FlexType::Row => Flex::row(),
}
.cross_axis_alignment(state.cross_alignment)
.main_axis_alignment(state.main_alignment)
.must_fill_main_axis(state.fill_major_axis);
flex.add_child(
TextBox::new()
.with_placeholder("Sample text")
.lens(DemoState::input_text),
);
space_if_needed(&mut flex, state);
flex.add_child(
Button::new("Clear").on_click(|_ctx, data: &mut DemoState, _env| {
data.input_text.clear();
data.enabled = false;
data.volume = 0.0;
}),
);
space_if_needed(&mut flex, state);
flex.add_child(
Label::new(|data: &DemoState, _: &Env| data.input_text.clone()).with_text_size(32.0),
);
space_if_needed(&mut flex, state);
flex.add_child(Checkbox::new("Demo").lens(DemoState::enabled));
space_if_needed(&mut flex, state);
flex.add_child(Switch::new().lens(DemoState::enabled));
space_if_needed(&mut flex, state);
flex.add_child(Slider::new().lens(DemoState::volume));
space_if_needed(&mut flex, state);
flex.add_child(ProgressBar::new().lens(DemoState::volume));
space_if_needed(&mut flex, state);
flex.add_child(
Stepper::new()
.with_range(0.0, 1.0)
.with_step(0.1)
.with_wraparound(true)
.lens(DemoState::volume),
);
let mut flex = SizedBox::new(flex);
if state.fix_minor_axis {
match state.axis {
FlexType::Row => flex = flex.height(200.),
FlexType::Column => flex = flex.width(200.),
}
}
if state.fix_major_axis {
match state.axis {
FlexType::Row => flex = flex.width(600.),
FlexType::Column => flex = flex.height(300.),
}
}
let flex = flex
.padding(8.0)
.border(Color::grey(0.6), 2.0)
.rounded(5.0)
.lens(AppState::demo_state);
if state.debug_layout {
flex.debug_paint_layout().boxed()
} else {
flex.boxed()
}
}
examples/styled_text.rs (line 128)
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
fn ui_builder() -> impl Widget<AppData> {
let my_painter = Painter::new(|ctx, _, _| {
let bounds = ctx.size().to_rect();
if ctx.is_hot() {
ctx.fill(bounds, &Color::rgba8(0, 0, 0, 128));
}
if ctx.is_active() {
ctx.stroke(bounds, &Color::WHITE, 2.0);
}
});
// This is Druid's default text style.
// It's set by theme::LABEL_COLOR and theme::UI_FONT
let label =
Label::new(|data: &String, _env: &_| format!("Default: {data}")).lens(AppData::text);
// The text_color, text_size, and font builder methods can override the
// defaults provided by the theme by passing in a Key or a concrete value.
//
// In this example, text_color receives a Key from the theme, text_size
// gets a custom key which we set with the env_scope wrapper, and the
// default font key (theme::FONT_NAME) is overridden in the env_scope
// wrapper. (Like text_color and text_size, the font can be set using the
// with_font builder method, but overriding here makes it easy to fall back
// to the default font)
let styled_label = Label::new(|data: &AppData, _env: &_| format!("{data}"))
.with_text_color(theme::PRIMARY_LIGHT)
.with_font(MY_CUSTOM_FONT)
.background(my_painter)
.on_click(|_, data, _| {
data.size *= 1.1;
})
.env_scope(|env: &mut druid::Env, data: &AppData| {
let new_font = if data.mono {
FontDescriptor::new(FontFamily::MONOSPACE)
} else {
FontDescriptor::new(FontFamily::SYSTEM_UI)
}
.with_size(data.size);
env.set(MY_CUSTOM_FONT, new_font);
});
let labels = Scroll::new(
Flex::column()
.cross_axis_alignment(CrossAxisAlignment::Start)
.with_child(label)
.with_default_spacer()
.with_child(styled_label),
)
.expand_height()
.fix_width(COLUMN_WIDTH);
let stepper = Stepper::new()
.with_range(0.0, 100.0)
.with_step(1.0)
.with_wraparound(false)
.lens(AppData::size);
// TODO: Replace Parse usage with TextBox::with_formatter
#[allow(deprecated)]
let stepper_textbox = LensWrap::new(
Parse::new(TextBox::new()),
AppData::size.map(|x| Some(*x), |x, y| *x = y.unwrap_or(24.0)),
);
let mono_checkbox = Checkbox::new("Monospace").lens(AppData::mono);
let stepper_row = Flex::row()
.with_child(stepper_textbox)
.with_child(stepper)
.with_default_spacer()
.with_child(mono_checkbox);
let input = TextBox::multiline()
.with_placeholder("Your sample text here :)")
.fix_width(COLUMN_WIDTH)
.fix_height(140.0)
.lens(AppData::text);
Flex::column()
.main_axis_alignment(MainAxisAlignment::Center)
.with_default_spacer()
.with_flex_child(labels, 1.0)
.with_default_spacer()
.with_child(input)
.with_default_spacer()
.with_child(stepper_row)
.with_default_spacer()
}
Trait Implementations§
source§impl Widget<f64> for Stepper
impl Widget<f64> for Stepper
source§fn paint(&mut self, ctx: &mut PaintCtx<'_, '_, '_>, _data: &f64, env: &Env)
fn paint(&mut self, ctx: &mut PaintCtx<'_, '_, '_>, _data: &f64, env: &Env)
Paint the widget appearance. Read more
source§fn layout(
&mut self,
_layout_ctx: &mut LayoutCtx<'_, '_>,
bc: &BoxConstraints,
_data: &f64,
env: &Env
) -> Size
fn layout( &mut self, _layout_ctx: &mut LayoutCtx<'_, '_>, bc: &BoxConstraints, _data: &f64, env: &Env ) -> Size
Compute layout. Read more
source§fn event(
&mut self,
ctx: &mut EventCtx<'_, '_>,
event: &Event,
data: &mut f64,
env: &Env
)
fn event( &mut self, ctx: &mut EventCtx<'_, '_>, event: &Event, data: &mut f64, env: &Env )
Handle an event. Read more
source§fn lifecycle(
&mut self,
ctx: &mut LifeCycleCtx<'_, '_>,
event: &LifeCycle,
_data: &f64,
_env: &Env
)
fn lifecycle( &mut self, ctx: &mut LifeCycleCtx<'_, '_>, event: &LifeCycle, _data: &f64, _env: &Env )
Handle a life cycle notification. Read more
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
Computes max intrinsic/preferred dimension of a widget on the provided axis. Read more
Auto Trait Implementations§
impl RefUnwindSafe for Stepper
impl Send for Stepper
impl Sync for Stepper
impl Unpin for Stepper
impl UnwindSafe for Stepper
Blanket Implementations§
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> ⓘ
§impl<T> RoundFrom<T> for T
impl<T> RoundFrom<T> for T
§fn round_from(x: T) -> T
fn round_from(x: T) -> T
Performs the conversion.
§impl<T, U> RoundInto<U> for Twhere
U: RoundFrom<T>,
impl<T, U> RoundInto<U> for Twhere U: RoundFrom<T>,
§fn round_into(self) -> U
fn round_into(self) -> U
Performs the conversion.