1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 22:53:14 -04:00

Remove SelectableLabel

This commit is contained in:
lucasmerlin
2025-06-30 12:03:21 +02:00
parent d770cd53a6
commit 4e8e5e08ff
5 changed files with 45 additions and 98 deletions

View File

@@ -23,7 +23,7 @@ use crate::{
vec2, widgets,
widgets::{
color_picker, Button, Checkbox, DragValue, Hyperlink, Image, ImageSource, Label, Link,
RadioButton, SelectableLabel, Separator, Spinner, TextEdit, Widget,
RadioButton, Separator, Spinner, TextEdit, Widget,
},
Align, Color32, Context, CursorIcon, DragAndDrop, Id, InnerResponse, InputState, IntoAtoms,
LayerId, Memory, Order, Painter, PlatformOutput, Pos2, Rangef, Rect, Response, Rgba, RichText,
@@ -2136,8 +2136,8 @@ impl Ui {
///
/// See also [`SelectableLabel`] 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_value(checked, text).ui(self)
}
/// Show selectable text. It is selected if `*current_value == selected_value`.
@@ -2146,11 +2146,11 @@ impl Ui {
/// Example: `ui.selectable_value(&mut my_enum, Enum::Alternative, "Alternative")`.
///
/// See also [`SelectableLabel`] and [`Self::toggle_value`].
pub fn selectable_value<Value: PartialEq>(
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 {

View File

@@ -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,
@@ -44,6 +45,7 @@ impl<'a> Button<'a> {
stroke: None,
small: false,
frame: None,
frame_when_inactive: true,
min_size: Vec2::ZERO,
corner_radius: None,
selected: false,
@@ -52,6 +54,25 @@ impl<'a> Button<'a> {
}
}
/// Show a selectable button.
///
/// Equivalent to:
/// ```rust
/// # use egui::{Button, IntoAtoms};
/// let selected = true;
/// Button::new("toggle me").selected(selected).frame_when_inactive(!selected).frame(true)
/// ```
///
/// See also:
/// - [`Ui::selectable_value`]
/// - [`Ui::selectable_label`]
pub fn selectable_value(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
@@ -138,6 +159,15 @@ impl<'a> Button<'a> {
self
}
/// If `false`, the button will not have a frame when inactive.
///
/// Default: `true`.
#[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]
@@ -220,6 +250,7 @@ impl<'a> Button<'a> {
stroke,
small,
frame,
frame_when_inactive,
mut min_size,
corner_radius,
selected,
@@ -243,9 +274,9 @@ impl<'a> Button<'a> {
let text = layout.text().map(String::from);
let has_frame = frame.unwrap_or_else(|| ui.visuals().button_frame);
let mut has_frame = frame.unwrap_or_else(|| ui.visuals().button_frame);
let mut button_padding = if has_frame {
let mut button_padding = if has_frame || !frame_when_inactive {
ui.spacing().button_padding
} else {
Vec2::ZERO
@@ -262,6 +293,12 @@ impl<'a> Button<'a> {
let response = if ui.is_rect_visible(prepared.response.rect) {
let visuals = ui.style().interact_selectable(&prepared.response, selected);
if !frame_when_inactive {
has_frame &= 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()));
}

View File

@@ -16,7 +16,6 @@ mod image_button;
mod label;
mod progress_bar;
mod radio_button;
mod selected_label;
mod separator;
mod slider;
mod spinner;
@@ -35,7 +34,6 @@ pub use self::{
label::Label,
progress_bar::ProgressBar,
radio_button::RadioButton,
selected_label::SelectableLabel,
separator::Separator,
slider::{Slider, SliderClamping, SliderOrientation},
spinner::Spinner,

View File

@@ -1,88 +0,0 @@
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
}
}

View File

@@ -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() {