Skip to content
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

Smaller checkboxes and radiobutton without a label #1456

Merged
merged 2 commits into from
Apr 5, 2022
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w
* Renamed `Frame::margin` to `Frame::inner_margin`.
* Renamed `AlphaImage` to `FontImage` to discourage any other use for it ([#1412](https://github.com/emilk/egui/pull/1412)).
* Warnings will pe painted on screen when there is an `Id` clash for `Grid`, `Plot` or `ScrollArea` ([#1452](https://github.com/emilk/egui/pull/1452)).
* `Checkbox` and `RadioButton` with an empty label (`""`) will now take up much less space ([#1456](https://github.com/emilk/egui/pull/1456)).

### Fixed 🐛
* Fixed ComboBoxes always being rendered left-aligned ([#1304](https://github.com/emilk/egui/pull/1304)).
Expand Down
2 changes: 1 addition & 1 deletion egui/src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ impl Default for Spacing {
slider_width: 100.0,
text_edit_width: 280.0,
icon_width: 14.0,
icon_spacing: 0.0,
icon_spacing: 4.0,
tooltip_width: 600.0,
combo_height: 200.0,
scroll_bar_width: 8.0,
Expand Down
91 changes: 61 additions & 30 deletions egui/src/widgets/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,31 +237,41 @@ impl<'a> Widget for Checkbox<'a> {

let spacing = &ui.spacing();
let icon_width = spacing.icon_width;
let icon_spacing = ui.spacing().icon_spacing;
let button_padding = spacing.button_padding;
let total_extra = button_padding + vec2(icon_width + icon_spacing, 0.0) + button_padding;
let icon_spacing = spacing.icon_spacing;

let wrap_width = ui.available_width() - total_extra.x;
let text = text.into_galley(ui, None, wrap_width, TextStyle::Button);
let (text, mut desired_size) = if text.is_empty() {
(None, vec2(icon_width, 0.0))
} else {
let total_extra = vec2(icon_width + icon_spacing, 0.0);

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

let mut desired_size = total_extra + text.size();
desired_size = desired_size.at_least(spacing.interact_size);

let mut desired_size = total_extra + text.size();
desired_size = desired_size.at_least(spacing.interact_size);
(Some(text), desired_size)
};

desired_size = desired_size.at_least(Vec2::splat(spacing.interact_size.y));
desired_size.y = desired_size.y.max(icon_width);
let (rect, mut response) = ui.allocate_exact_size(desired_size, Sense::click());

if response.clicked() {
*checked = !*checked;
response.mark_changed();
}
response.widget_info(|| WidgetInfo::selected(WidgetType::Checkbox, *checked, text.text()));
response.widget_info(|| {
WidgetInfo::selected(
WidgetType::Checkbox,
*checked,
text.as_ref().map_or("", |x| x.text()),
)
});

if ui.is_rect_visible(rect) {
// let visuals = ui.style().interact_selectable(&response, *checked); // too colorful
let visuals = ui.style().interact(&response);
let text_pos = pos2(
rect.min.x + button_padding.x + icon_width + icon_spacing,
rect.center().y - 0.5 * text.size().y,
);
let (small_icon_rect, big_icon_rect) = ui.spacing().icon_rectangles(rect);
ui.painter().add(epaint::RectShape {
rect: big_icon_rect.expand(visuals.expansion),
Expand All @@ -281,8 +291,13 @@ impl<'a> Widget for Checkbox<'a> {
visuals.fg_stroke,
));
}

text.paint_with_visuals(ui.painter(), text_pos, visuals);
if let Some(text) = text {
let text_pos = pos2(
rect.min.x + icon_width + icon_spacing,
rect.center().y - 0.5 * text.size().y,
);
text.paint_with_visuals(ui.painter(), text_pos, visuals);
}
}

response
Expand Down Expand Up @@ -329,27 +344,37 @@ impl Widget for RadioButton {
fn ui(self, ui: &mut Ui) -> Response {
let RadioButton { checked, text } = self;

let icon_width = ui.spacing().icon_width;
let icon_spacing = ui.spacing().icon_spacing;
let button_padding = ui.spacing().button_padding;
let total_extra = button_padding + vec2(icon_width + icon_spacing, 0.0) + button_padding;
let spacing = &ui.spacing();
let icon_width = spacing.icon_width;
let icon_spacing = spacing.icon_spacing;

let (text, mut desired_size) = if text.is_empty() {
(None, vec2(icon_width, 0.0))
} else {
let total_extra = vec2(icon_width + icon_spacing, 0.0);

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

let wrap_width = ui.available_width() - total_extra.x;
let text = text.into_galley(ui, None, wrap_width, TextStyle::Button);
let mut desired_size = total_extra + text.size();
desired_size = desired_size.at_least(spacing.interact_size);

let mut desired_size = total_extra + text.size();
desired_size = desired_size.at_least(ui.spacing().interact_size);
(Some(text), desired_size)
};

desired_size = desired_size.at_least(Vec2::splat(spacing.interact_size.y));
desired_size.y = desired_size.y.max(icon_width);
let (rect, response) = ui.allocate_exact_size(desired_size, Sense::click());
response
.widget_info(|| WidgetInfo::selected(WidgetType::RadioButton, checked, text.text()));

if ui.is_rect_visible(rect) {
let text_pos = pos2(
rect.min.x + button_padding.x + icon_width + icon_spacing,
rect.center().y - 0.5 * text.size().y,
);
response.widget_info(|| {
WidgetInfo::selected(
WidgetType::RadioButton,
checked,
text.as_ref().map_or("", |x| x.text()),
)
});

if ui.is_rect_visible(rect) {
// let visuals = ui.style().interact_selectable(&response, checked); // too colorful
let visuals = ui.style().interact(&response);

Expand All @@ -374,7 +399,13 @@ impl Widget for RadioButton {
});
}

text.paint_with_visuals(ui.painter(), text_pos, visuals);
if let Some(text) = text {
let text_pos = pos2(
rect.min.x + icon_width + icon_spacing,
rect.center().y - 0.5 * text.size().y,
);
text.paint_with_visuals(ui.painter(), text_pos, visuals);
}
}

response
Expand Down
28 changes: 28 additions & 0 deletions egui_demo_lib/src/apps/demo/misc_demo_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ pub struct MiscDemoWindow {
colors: ColorWidgets,
tree: Tree,
box_painting: BoxPainting,

dummy_bool: bool,
dummy_usize: usize,
}

impl Default for MiscDemoWindow {
Expand All @@ -31,6 +34,9 @@ impl Default for MiscDemoWindow {
colors: Default::default(),
tree: Tree::demo(),
box_painting: Default::default(),

dummy_bool: false,
dummy_usize: 0,
}
}
}
Expand Down Expand Up @@ -80,6 +86,28 @@ impl View for MiscDemoWindow {
.default_open(false)
.show(ui, |ui| self.tree.ui(ui));

CollapsingHeader::new("Checkboxes")
.default_open(false)
.show(ui, |ui| {
ui.label("Checkboxes with empty labels take up very little space:");
ui.spacing_mut().item_spacing = Vec2::ZERO;
ui.horizontal_wrapped(|ui| {
for _ in 0..64 {
ui.checkbox(&mut self.dummy_bool, "");
}
});
ui.checkbox(&mut self.dummy_bool, "checkbox");

ui.label("Radiobuttons are similar:");
ui.spacing_mut().item_spacing = Vec2::ZERO;
ui.horizontal_wrapped(|ui| {
for i in 0..64 {
ui.radio_value(&mut self.dummy_usize, i, "");
}
});
ui.radio_value(&mut self.dummy_usize, 64, "radio_value");
});

ui.collapsing("Columns", |ui| {
ui.add(Slider::new(&mut self.num_columns, 1..=10).text("Columns"));
ui.columns(self.num_columns, |cols| {
Expand Down