8000 Remove `SelectableLabel` by lucasmerlin · Pull Request #7277 · emilk/egui · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Remove SelectableLabel #7277

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jul 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions crates/egui/src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::{
vec2, widgets,
widgets::{
Button, Checkbox, DragValue, Hyperlink, Image, ImageSource, Label, Link, RadioButton,
SelectableLabel, Separator, Spinner, TextEdit, Widget, color_picker,
Separator, Spinner, TextEdit, Widget, color_picker,
},
};
// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -2077,13 +2077,13 @@ impl Ui {
Checkbox::new(checked, atoms).ui(self)
}

/// Acts like a checkbox, but looks like a [`SelectableLabel`].
/// Acts like a checkbox, but looks like a [`Button::selectable`].
///
/// Click to toggle to bool.
///
/// See also [`Self::checkbox`].
pub fn toggle_value(&mut self, selected: &mut bool, text: impl Into<WidgetText>) -> Response {
let mut response = self.selectable_label(*selected, text);
pub fn toggle_value<'a>(&mut self, selected: &mut bool, atoms: impl IntoAtoms<'a>) -> Response {
let mut response = self.selectable_label(*selected, atoms);
if response.clicked() {
*selected = !*selected;
response.mark_changed();
Expand Down Expand Up @@ -2134,23 +2134,23 @@ impl Ui {

/// Show a label which can be selected or not.
///
/// See also [`SelectableLabel`] and [`Self::toggle_value`].
/// See also [`Button::selectable`] and [`Self::toggle_value`].
#[must_use = "You should check if the user clicked this with `if ui.selectable_label(…).clicked() { … } "]
pub fn selectable_label(&mut self, checked: bool, text: impl Into<WidgetText>) -> Response {
SelectableLabel::new(checked, text).ui(self)
pub fn selectable_label<'a>(&mut self, checked: bool, text: impl IntoAtoms<'a>) -> Response {
Button::selectable(checked, text).ui(self)
}

/// Show selectable text. It is selected if `*current_value == selected_value`.
/// If clicked, `selected_value` is assigned to `*current_value`.
///
/// Example: `ui.selectable_value(&mut my_enum, Enum::Alternative, "Alternative")`.
///
/// See also [`SelectableLabel`] and [`Self::toggle_value`].
pub fn selectable_value<Value: PartialEq>(
/// See also [`Button::selectable`] and [`Self::toggle_value`].
pub fn selectable_value<'a, Value: PartialEq>(
&mut self,
current_value: &mut Value,
selected_value: Value,
text: impl Into<WidgetText>,
text: impl IntoAtoms<'a>,
) -> Response {
let mut response = self.selectable_label(*current_value == selected_value, text);
if response.clicked() && *current_value != selected_value {
Expand Down
51 changes: 48 additions & 3 deletions crates/egui/src/widgets/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub struct Button<'a> {
stroke: Option<Stroke>,
small: bool,
frame: Option<bool>,
frame_when_inactive: bool,
min_size: Vec2,
corner_radius: Option<CornerRadius>,
selected: bool,
Expand All @@ -44,6 +45,7 @@ impl<'a> Button<'a> {
stro 8000 ke: None,
small: false,
frame: None,
frame_when_inactive: true,
min_size: Vec2::ZERO,
corner_radius: None,
selected: false,
Expand All @@ -52,6 +54,27 @@ impl<'a> Button<'a> {
}
}

/// Show a selectable button.
///
/// Equivalent to:
/// ```rust
/// # use egui::{Button, IntoAtoms, __run_test_ui};
/// # __run_test_ui(|ui| {
/// let selected = true;
/// ui.add(Button::new("toggle me").selected(selected).frame_when_inactive(!selected).frame(true));
/// # });
/// ```
///
/// See also:
/// - [`Ui::selectable_value`]
/// - [`Ui::selectable_label`]
pub fn selectable(selected: bool, atoms: impl IntoAtoms<'a>) -> Self {
Self::new(atoms)
.selected(selected)
.frame_when_inactive(selected)
.frame(true)
}

/// Creates a button with an image. The size of the image as displayed is defined by the provided size.
///
/// Note: In contrast to [`Button::new`], this limits the image size to the default font height
Expand Down Expand Up @@ -138,6 +161,18 @@ impl<'a> Button<'a> {
self
}

/// If `false`, the button will not have a frame when inactive.
///
/// Default: `true`.
///
/// Note: When [`Self::frame`] (or `ui.visuals().button_frame`) is `false`, this setting
/// has no effect.
#[inline]
pub fn frame_when_inactive(mut self, frame_when_inactive: bool) -> Self {
self.frame_when_inactive = frame_when_inactive;
self
}

/// By default, buttons senses clicks.
/// Change this to a drag-button with `Sense::drag()`.
#[inline]
Expand Down Expand Up @@ -220,6 +255,7 @@ impl<'a> Button<'a> {
stroke,
small,
frame,
frame_when_inactive,
mut min_size,
corner_radius,
selected,
Expand All @@ -243,9 +279,9 @@ impl<'a> Button<'a> {

let text = layout.text().map(String::from);

let has_frame = frame.unwrap_or_else(|| ui.visuals().button_frame);
let has_frame_margin = frame.unwrap_or_else(|| ui.visuals().button_frame);

let mut button_padding = if has_frame {
let mut button_padding = if has_frame_margin {
ui.spacing().button_padding
} else {
Vec2::ZERO
Expand All @@ -262,13 +298,22 @@ impl<'a> Button<'a> {
let response = if ui.is_rect_visible(prepared.response.rect) {
let visuals = ui.style().interact_selectable(&prepared.response, selected);

let visible_frame = if frame_when_inactive {
has_frame_margin
} else {
has_frame_margin
&& (prepared.response.hovered()
|| prepared.response.is_pointer_button_down_on()
|| prepared.response.has_focus())
};

if image_tint_follows_text_color {
prepared.map_images(|image| image.tint(visuals.text_color()));
}

prepared.fallback_text_color = visuals.text_color();

if has_frame {
if visible_frame {
let stroke = stroke.unwrap_or(visuals.bg_stroke);
let fill = fill.unwrap_or(visuals.weak_bg_fill);
prepared.frame = prepared
Expand Down
3 changes: 2 additions & 1 deletion crates/egui/src/widgets/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ mod slider;
mod spinner;
pub mod text_edit;

#[expect(deprecated)]
pub use self::selected_label::SelectableLabel;
pub use self::{
button::Button,
checkbox::Checkbox,
Expand All @@ -35,7 +37,6 @@ pub use self::{
label::Label,
progress_bar::ProgressBar,
radio_button::RadioButton,
selected_label::SelectableLabel,
separator::Separator,
slider::{Slider, SliderClamping, SliderOrientation},
spinner::Spinner,
Expand Down
90 changes: 2 additions & 88 deletions crates/egui/src/widgets/selected_label.rs
Original file line number Diff line number Diff line change
@@ -1,88 +1,2 @@
use crate::{
NumExt as _, Response, Sense, TextStyle, Ui, Widget, WidgetInfo, WidgetText, WidgetType,
};

/// One out of several alternatives, either selected or not.
/// Will mark selected items with a different background color.
/// An alternative to [`crate::RadioButton`] and [`crate::Checkbox`].
///
/// Usually you'd use [`Ui::selectable_value`] or [`Ui::selectable_label`] instead.
///
/// ```
/// # egui::__run_test_ui(|ui| {
/// #[derive(PartialEq)]
/// enum Enum { First, Second, Third }
/// let mut my_enum = Enum::First;
///
/// ui.selectable_value(&mut my_enum, Enum::First, "First");
///
/// // is equivalent to:
///
/// if ui.add(egui::SelectableLabel::new(my_enum == Enum::First, "First")).clicked() {
/// my_enum = Enum::First
/// }
/// # });
/// ```
#[must_use = "You should put this widget in a ui with `ui.add(widget);`"]
pub struct SelectableLabel {
selected: bool,
text: WidgetText,
}

impl SelectableLabel {
pub fn new(selected: bool, text: impl Into<WidgetText>) -> Self {
Self {
selected,
text: text.into(),
}
}
}

impl Widget for SelectableLabel {
fn ui(self, ui: &mut Ui) -> Response {
let Self { selected, text } = self;

let button_padding = ui.spacing().button_padding;
let total_extra = button_padding + button_padding;

let wrap_width = ui.available_width() - total_extra.x;
let galley = text.into_galley(ui, None, wrap_width, TextStyle::Button);

let mut desired_size = total_extra + galley.size();
desired_size.y = desired_size.y.at_least(ui.spacing().interact_size.y);
let (rect, response) = ui.allocate_at_least(desired_size, Sense::click());
response.widget_info(|| {
WidgetInfo::selected(
WidgetType::SelectableLabel,
ui.is_enabled(),
selected,
galley.text(),
)
});

if ui.is_rect_visible(response.rect) {
let text_pos = ui
.layout()
.align_size_within_rect(galley.size(), rect.shrink2(button_padding))
.min;

let visuals = ui.style().interact_selectable(&response, selected);

if selected || response.hovered() || response.highlighted() || response.has_focus() {
let rect = rect.expand(visuals.expansion);

ui.painter().rect(
rect,
visuals.corner_radius,
visuals.weak_bg_fill,
visuals.bg_stroke,
epaint::StrokeKind::Inside,
);
}

ui.painter().galley(text_pos, galley, visuals.text_color());
}

response
}
}
#[deprecated = "SelectableLabel has been removed. Use Button::selectable() instead"]
pub struct SelectableLabel {}
2 changes: 1 addition & 1 deletion crates/egui_demo_lib/src/demo/password.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub fn password_ui(ui: &mut egui::Ui, password: &mut String) -> egui::Response {
let result = ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
// Toggle the `show_plaintext` bool with a button:
let response = ui
.add(egui::SelectableLabel::new(show_plaintext, "👁"))
.selectable_label(show_plaintext, "👁")
.on_hover_text("Show/hide password");

if response.clicked() {
Expand Down
0