Merge pull request #2873 from Krahos/optional-label

refactor(checkbox): make label optional for checkbox
This commit is contained in:
Héctor 2025-11-25 09:08:44 +01:00 committed by GitHub
commit 7e8cf76db1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 87 additions and 58 deletions

View file

@ -39,11 +39,13 @@ impl Example {
}
fn view(&self) -> Element<'_, Message> {
let default_checkbox = checkbox("Default", self.default)
let default_checkbox = checkbox(self.default)
.label("Default")
.on_toggle(Message::DefaultToggled);
let styled_checkbox = |label| {
checkbox(label, self.styled)
checkbox(self.styled)
.label(label)
.on_toggle_maybe(self.default.then_some(Message::StyledToggled))
};
@ -55,7 +57,8 @@ impl Example {
]
.spacing(20);
let custom_checkbox = checkbox("Custom", self.custom)
let custom_checkbox = checkbox(self.custom)
.label("Custom")
.on_toggle(Message::CustomToggled)
.icon(checkbox::Icon {
font: ICON_FONT,

View file

@ -73,7 +73,8 @@ impl IcedCubes {
.step(0.01)
.width(100),
),
checkbox("Show Depth Buffer", self.scene.show_depth_buffer)
checkbox(self.scene.show_depth_buffer)
.label("Show Depth Buffer")
.on_toggle(Message::ShowDepthBuffer),
]
.spacing(40);

View file

@ -63,7 +63,8 @@ impl Events {
.map(Element::from),
);
let toggle = checkbox("Listen to runtime events", self.enabled)
let toggle = checkbox(self.enabled)
.label("Listen to runtime events")
.on_toggle(Message::Toggled);
let exit = button(text("Exit").width(Fill).align_x(Center))

View file

@ -153,7 +153,8 @@ impl Image {
self.rotation.degrees(),
Message::RotationChanged
),
checkbox("Spin!", self.spin)
checkbox(self.spin)
.label("Spin!")
.text_size(12)
.on_toggle(Message::SpinToggled)
.size(12)

View file

@ -162,7 +162,9 @@ fn view_controls<'a>(
row![
playback_controls,
speed_controls,
checkbox("Grid", is_grid_enabled).on_toggle(Message::ToggleGrid),
checkbox(is_grid_enabled)
.label("Grid")
.on_toggle(Message::ToggleGrid),
row![
pick_list(preset::ALL, Some(preset), Message::PresetPicked),
button("Clear")

View file

@ -78,7 +78,8 @@ impl Gradient {
.align_y(Center);
let transparency_toggle = iced::widget::Container::new(
checkbox("Transparent window", transparent)
checkbox(transparent)
.label("Transparent window")
.on_toggle(Message::TransparentToggled),
)
.padding(8);

View file

@ -71,7 +71,8 @@ impl Layout {
let header = row![
text(self.example.title).size(20).font(Font::MONOSPACE),
space::horizontal(),
checkbox("Explain", self.explain)
checkbox(self.explain)
.label("Explain")
.on_toggle(Message::ExplainToggled),
pick_list(Theme::ALL, self.theme.as_ref(), Message::ThemeSelected)
.placeholder("Theme"),

View file

@ -58,7 +58,8 @@ impl Progress {
)
},
center_x(
checkbox("Vertical", self.is_vertical)
checkbox(self.is_vertical)
.label("Vertical")
.on_toggle(Message::ToggleVertical)
),
]

View file

@ -133,10 +133,11 @@ impl Styling {
.width(Fill)
.height(Fill);
let check = checkbox("Check me!", self.checkbox_value)
let check = checkbox(self.checkbox_value)
.label("Check me!")
.on_toggle(Message::CheckboxToggled);
let check_disabled = checkbox("Disabled", self.checkbox_value);
let check_disabled = checkbox(self.checkbox_value).label("Disabled");
let toggle = toggler(self.toggler_value)
.label("Toggle me!")

View file

@ -37,9 +37,9 @@ impl Tiger {
},
});
let apply_color_filter =
checkbox("Apply a color filter", self.apply_color_filter)
.on_toggle(Message::ToggleColorFilter);
let apply_color_filter = checkbox(self.apply_color_filter)
.label("Apply a color filter")
.on_toggle(Message::ToggleColorFilter);
center(column![svg, center_x(apply_color_filter)].spacing(20))
.padding(20)

View file

@ -339,7 +339,8 @@ impl Task {
fn view(&self, i: usize) -> Element<'_, TaskMessage> {
match &self.state {
TaskState::Idle => {
let checkbox = checkbox(&self.description, self.completed)
let checkbox = checkbox(self.completed)
.label(&self.description)
.on_toggle(TaskMessage::Completed)
.width(Fill)
.size(17)

View file

@ -386,11 +386,9 @@ impl Tour {
.push(slider(100..=500, width, Message::ImageWidthChanged))
.push(text!("Width: {width} px").width(Fill).align_x(Center))
.push(
checkbox(
"Use nearest interpolation",
filter_method == image::FilterMethod::Nearest,
)
.on_toggle(Message::ImageUseNearestToggled),
checkbox(filter_method == image::FilterMethod::Nearest)
.label("Use nearest interpolation")
.on_toggle(Message::ImageUseNearestToggled),
)
.align_x(Center)
}
@ -441,11 +439,13 @@ impl Tour {
.push("Use a text input to ask for different kinds of information.")
.push(text_input.secure(is_secure))
.push(
checkbox("Enable password mode", is_secure)
checkbox(is_secure)
.label("Enable password mode")
.on_toggle(Message::ToggleSecureInput),
)
.push(
checkbox("Show icon", is_showing_icon)
checkbox(is_showing_icon)
.label("Show icon")
.on_toggle(Message::ToggleTextInputIcon),
)
.push(
@ -474,7 +474,8 @@ impl Tour {
see element boundaries.",
)
.push(
checkbox("Explain layout", self.debug)
checkbox(self.debug)
.label("Explain layout")
.on_toggle(Message::DebugToggled),
)
.push("Feel free to go back and take a look.")

View file

@ -58,7 +58,8 @@ impl VectorialText {
column![
canvas(&self.state).width(Fill).height(Fill),
column![
checkbox("Use Japanese", self.state.use_japanese,)
checkbox(self.state.use_japanese,)
.label("Use Japanese")
.on_toggle(Message::ToggleJapanese),
row![
slider_with_label(

View file

@ -16,7 +16,8 @@
//! }
//!
//! fn view(state: &State) -> Element<'_, Message> {
//! checkbox("Toggle me!", state.is_checked)
//! checkbox(state.is_checked)
//! .label("Toggle me!")
//! .on_toggle(Message::CheckboxToggled)
//! .into()
//! }
@ -63,7 +64,8 @@ use crate::core::{
/// }
///
/// fn view(state: &State) -> Element<'_, Message> {
/// checkbox("Toggle me!", state.is_checked)
/// checkbox(state.is_checked)
/// .label("Toggle me!")
/// .on_toggle(Message::CheckboxToggled)
/// .into()
/// }
@ -88,7 +90,7 @@ pub struct Checkbox<
{
is_checked: bool,
on_toggle: Option<Box<dyn Fn(bool) -> Message + 'a>>,
label: String,
label: Option<text::Fragment<'a>>,
width: Length,
size: f32,
spacing: f32,
@ -110,22 +112,18 @@ where
/// The default size of a [`Checkbox`].
const DEFAULT_SIZE: f32 = 16.0;
/// The default spacing of a [`Checkbox`].
const DEFAULT_SPACING: f32 = 8.0;
/// Creates a new [`Checkbox`].
///
/// It expects:
/// * the label of the [`Checkbox`]
/// * a boolean describing whether the [`Checkbox`] is checked or not
pub fn new(label: impl Into<String>, is_checked: bool) -> Self {
pub fn new(is_checked: bool) -> Self {
Checkbox {
is_checked,
on_toggle: None,
label: label.into(),
label: None,
width: Length::Shrink,
size: Self::DEFAULT_SIZE,
spacing: Self::DEFAULT_SPACING,
spacing: Self::DEFAULT_SIZE / 2.0,
text_size: None,
text_line_height: text::LineHeight::default(),
text_shaping: text::Shaping::default(),
@ -143,6 +141,12 @@ where
}
}
/// Sets the label of the [`Checkbox`].
pub fn label(mut self, label: impl text::IntoFragment<'a>) -> Self {
self.label = Some(label.into_fragment());
self
}
/// Sets the function that will be called when the [`Checkbox`] is toggled.
/// It will receive the new state of the [`Checkbox`] and must produce a
/// `Message`.
@ -275,30 +279,38 @@ where
) -> layout::Node {
layout::next_to_each_other(
&limits.width(self.width),
self.spacing,
if self.label.is_some() {
self.spacing
} else {
0.0
},
|_| layout::Node::new(Size::new(self.size, self.size)),
|limits| {
let state = tree
if let Some(label) = self.label.as_deref() {
let state = tree
.state
.downcast_mut::<widget::text::State<Renderer::Paragraph>>();
widget::text::layout(
state,
renderer,
limits,
&self.label,
widget::text::Format {
width: self.width,
height: Length::Shrink,
line_height: self.text_line_height,
size: self.text_size,
font: self.font,
align_x: text::Alignment::Default,
align_y: alignment::Vertical::Top,
shaping: self.text_shaping,
wrapping: self.text_wrapping,
},
)
widget::text::layout(
state,
renderer,
limits,
label,
widget::text::Format {
width: self.width,
height: Length::Shrink,
line_height: self.text_line_height,
size: self.text_size,
font: self.font,
align_x: text::Alignment::Default,
align_y: alignment::Vertical::Top,
shaping: self.text_shaping,
wrapping: self.text_wrapping,
},
)
} else {
layout::Node::new(Size::ZERO)
}
},
)
}
@ -452,7 +464,9 @@ where
_renderer: &Renderer,
operation: &mut dyn widget::Operation,
) {
operation.text(None, layout.bounds(), &self.label);
if let Some(label) = self.label.as_deref() {
operation.text(None, layout.bounds(), label);
}
}
}

View file

@ -1250,7 +1250,8 @@ pub use crate::markdown::view as markdown;
/// }
///
/// fn view(state: &State) -> Element<'_, Message> {
/// checkbox("Toggle me!", state.is_checked)
/// checkbox(state.is_checked)
/// .label("Toggle me!")
/// .on_toggle(Message::CheckboxToggled)
/// .into()
/// }
@ -1265,14 +1266,13 @@ pub use crate::markdown::view as markdown;
/// ```
/// ![Checkbox drawn by `iced_wgpu`](https://github.com/iced-rs/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/checkbox.png?raw=true)
pub fn checkbox<'a, Message, Theme, Renderer>(
label: impl Into<String>,
is_checked: bool,
) -> Checkbox<'a, Message, Theme, Renderer>
where
Theme: checkbox::Catalog + 'a,
Renderer: core::text::Renderer,
{
Checkbox::new(label, is_checked)
Checkbox::new(is_checked)
}
/// Creates a new [`Radio`].