Skip to content

Commit

Permalink
Add ability to hide button backgrounds (#2621)
Browse files Browse the repository at this point in the history
* Add Spacing::combo_width

* Put ComboBox arrow closer to the text

* Tweak faint_bg_color

* Make it possible to have buttons without background

…while still having background for sliders, checkboxes, etc

* Rename mandatory_bg_fill -> bg_fill

* tweak grid stripe color (again)

* Make the animated part of the ProgressBar more visible

* Add line in changelog

* Add another line in changelog

* Menu fix: use the `open` widget style for open menus

* Adjust sizes on menu buttons and regular buttons to make sure they match

* Update comment

Co-authored-by: Andreas Reich <[email protected]>

* optional_bg_fill -> weak_bg_fill

Co-authored-by: Andreas Reich <[email protected]>
  • Loading branch information
emilk and Wumpf authored Jan 24, 2023
1 parent c75e726 commit 4bd4eca
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 44 deletions.
8 changes: 5 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG
* Add `Plot::clamp_grid` to only show grid where there is data ([#2480](https://github.com/emilk/egui/pull/2480)).
* Add `ScrollArea::drag_to_scroll` if you want to turn off that feature.
* Add `Response::on_hover_and_drag_cursor`.
* Add `Window::default_open` ([#2539](https://github.com/emilk/egui/pull/2539))
* Add `ProgressBar::fill` if you want to set the fill color manually. ([#2618](https://github.com/emilk/egui/pull/2618))
* Add `Button::rounding` to enable round buttons ([#2539](https://github.com/emilk/egui/pull/2539))
* Add `Window::default_open` ([#2539](https://github.com/emilk/egui/pull/2539)).
* Add `ProgressBar::fill` if you want to set the fill color manually. ([#2618](https://github.com/emilk/egui/pull/2618)).
* Add `Button::rounding` to enable round buttons ([#2616](https://github.com/emilk/egui/pull/2616)).
* Add `WidgetVisuals::optional_bg_color` - set it to `Color32::TRANSPARENT` to hide button backgrounds ([#2621](https://github.com/emilk/egui/pull/2621)).

### Changed 🔧
* Improved plot grid appearance ([#2412](https://github.com/emilk/egui/pull/2412)).
* Improved the algorithm for picking the number of decimals to show when hovering values in the `Plot`.
* Default `ComboBox` is now controlled with `Spacing::combo_width` ([#2621](https://github.com/emilk/egui/pull/2621)).

### Fixed 🐛
* Expose `TextEdit`'s multiline flag to AccessKit ([#2448](https://github.com/emilk/egui/pull/2448)).
Expand Down
2 changes: 1 addition & 1 deletion crates/egui/src/containers/collapsing_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ impl CollapsingHeader {
ui.painter().add(epaint::RectShape {
rect: header_response.rect.expand(visuals.expansion),
rounding: visuals.rounding,
fill: visuals.bg_fill,
fill: visuals.weak_bg_fill,
stroke: visuals.bg_stroke,
// stroke: Default::default(),
});
Expand Down
17 changes: 9 additions & 8 deletions crates/egui/src/containers/combo_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,16 +162,14 @@ impl ComboBox {
let button_id = ui.make_persistent_id(id_source);

ui.horizontal(|ui| {
if let Some(width) = width {
ui.spacing_mut().slider_width = width; // yes, this is ugly. Will remove later.
}
let mut ir = combo_box_dyn(
ui,
button_id,
selected_text,
menu_contents,
icon,
wrap_enabled,
width,
);
if let Some(label) = label {
ir.response
Expand Down Expand Up @@ -240,6 +238,7 @@ fn combo_box_dyn<'c, R>(
menu_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
icon: Option<IconPainter>,
wrap_enabled: bool,
width: Option<f32>,
) -> InnerResponse<Option<R>> {
let popup_id = button_id.with("popup");

Expand All @@ -263,18 +262,20 @@ fn combo_box_dyn<'c, R>(

let margin = ui.spacing().button_padding;
let button_response = button_frame(ui, button_id, is_popup_open, Sense::click(), |ui| {
let icon_spacing = ui.spacing().icon_spacing;
// We don't want to change width when user selects something new
let full_minimum_width = if wrap_enabled {
// Currently selected value's text will be wrapped if needed, so occupy the available width.
ui.available_width()
} else {
// Occupy at least the minimum width assigned to Slider and ComboBox.
ui.spacing().slider_width - 2.0 * margin.x
// Occupy at least the minimum width assigned to ComboBox.
let width = width.unwrap_or_else(|| ui.spacing().combo_width);
width - 2.0 * margin.x
};
let icon_size = Vec2::splat(ui.spacing().icon_width);
let wrap_width = if wrap_enabled {
// Use the available width, currently selected value's text will be wrapped if exceeds this value.
ui.available_width() - ui.spacing().item_spacing.x - icon_size.x
ui.available_width() - icon_spacing - icon_size.x
} else {
// Use all the width necessary to display the currently selected value's text.
f32::INFINITY
Expand All @@ -288,7 +289,7 @@ fn combo_box_dyn<'c, R>(
full_minimum_width
} else {
// Occupy at least the minimum width needed to contain the widget with the currently selected value's text.
galley.size().x + ui.spacing().item_spacing.x + icon_size.x
galley.size().x + icon_spacing + icon_size.x
};

// Case : wrap_enabled : occupy all the available width.
Expand Down Expand Up @@ -390,7 +391,7 @@ fn button_frame(
epaint::RectShape {
rect: outer_rect.expand(visuals.expansion),
rounding: visuals.rounding,
fill: visuals.bg_fill,
fill: visuals.weak_bg_fill,
stroke: visuals.bg_stroke,
},
);
Expand Down
2 changes: 2 additions & 0 deletions crates/egui/src/containers/popup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,8 @@ pub fn popup_below_widget<R>(
///
/// Useful for drop-down menus (combo boxes) or suggestion menus under text fields.
///
/// The opened popup will have the same width as the parent.
///
/// You must open the popup with [`Memory::open_popup`] or [`Memory::toggle_popup`].
///
/// Returns `None` if the popup is not open.
Expand Down
11 changes: 6 additions & 5 deletions crates/egui/src/menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ fn set_menu_style(style: &mut Style) {
style.spacing.button_padding = vec2(2.0, 0.0);
style.visuals.widgets.active.bg_stroke = Stroke::NONE;
style.visuals.widgets.hovered.bg_stroke = Stroke::NONE;
style.visuals.widgets.inactive.bg_fill = Color32::TRANSPARENT;
style.visuals.widgets.inactive.weak_bg_fill = Color32::TRANSPARENT;
style.visuals.widgets.inactive.bg_stroke = Stroke::NONE;
}

Expand Down Expand Up @@ -180,7 +180,7 @@ fn stationary_menu_impl<'c, R>(
let mut button = Button::new(title);

if bar_state.open_menu.is_menu_open(menu_id) {
button = button.fill(ui.visuals().widgets.open.bg_fill);
button = button.fill(ui.visuals().widgets.open.weak_bg_fill);
button = button.stroke(ui.visuals().widgets.open.bg_stroke);
}

Expand Down Expand Up @@ -443,7 +443,7 @@ impl SubMenuButton {
sub_id: Id,
) -> &'a WidgetVisuals {
if menu_state.is_open(sub_id) {
&ui.style().visuals.widgets.hovered
&ui.style().visuals.widgets.open
} else {
ui.style().interact(response)
}
Expand Down Expand Up @@ -472,7 +472,8 @@ impl SubMenuButton {
text_galley.size().x + icon_galley.size().x,
text_galley.size().y.max(icon_galley.size().y),
);
let desired_size = text_and_icon_size + 2.0 * button_padding;
let mut desired_size = text_and_icon_size + 2.0 * button_padding;
desired_size.y = desired_size.y.at_least(ui.spacing().interact_size.y);

let (rect, response) = ui.allocate_at_least(desired_size, sense);
response.widget_info(|| {
Expand All @@ -492,7 +493,7 @@ impl SubMenuButton {
ui.painter().rect_filled(
rect.expand(visuals.expansion),
visuals.rounding,
visuals.bg_fill,
visuals.weak_bg_fill,
);
}

Expand Down
58 changes: 45 additions & 13 deletions crates/egui/src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ impl Style {
pub fn interact_selectable(&self, response: &Response, selected: bool) -> WidgetVisuals {
let mut visuals = *self.visuals.widgets.style(response);
if selected {
visuals.weak_bg_fill = self.visuals.selection.bg_fill;
visuals.bg_fill = self.visuals.selection.bg_fill;
// visuals.bg_stroke = self.visuals.selection.stroke;
visuals.fg_stroke = self.visuals.selection.stroke;
Expand Down Expand Up @@ -264,8 +265,11 @@ pub struct Spacing {
/// Anything clickable should be (at least) this size.
pub interact_size: Vec2, // TODO(emilk): rename min_interact_size ?

/// Default width of a [`Slider`] and [`ComboBox`](crate::ComboBox).
pub slider_width: f32, // TODO(emilk): rename big_interact_size ?
/// Default width of a [`Slider`].
pub slider_width: f32,

/// Default (minimum) width of a [`ComboBox`](crate::ComboBox).
pub combo_width: f32,

/// Default width of a [`TextEdit`].
pub text_edit_width: f32,
Expand Down Expand Up @@ -533,7 +537,7 @@ impl Visuals {
// TODO(emilk): replace with an alpha
#[inline(always)]
pub fn fade_out_to_color(&self) -> Color32 {
self.widgets.noninteractive.bg_fill
self.widgets.noninteractive.weak_bg_fill
}

/// Returned a "grayed out" version of the given color.
Expand Down Expand Up @@ -594,9 +598,17 @@ impl Widgets {
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct WidgetVisuals {
/// Background color of widget.
/// Background color of widgets that must have a background fill,
/// such as the slider background, a checkbox background, or a radio button background.
///
/// Must never be [`Color32::TRANSPARENT`].
pub bg_fill: Color32,

/// Background color of widgets that can _optionally_ have a background fill, such as buttons.
///
/// May be [`Color32::TRANSPARENT`].
pub weak_bg_fill: Color32,

/// For surrounding rectangle of things that need it,
/// like buttons, the box of the checkbox, etc.
/// Should maybe be called `frame_stroke`.
Expand Down Expand Up @@ -684,6 +696,7 @@ impl Default for Spacing {
indent: 18.0, // match checkbox/radio-button with `button_padding.x + icon_width + icon_spacing`
interact_size: vec2(40.0, 18.0),
slider_width: 100.0,
combo_width: 100.0,
text_edit_width: 280.0,
icon_width: 14.0,
icon_width_inner: 8.0,
Expand Down Expand Up @@ -717,8 +730,8 @@ impl Visuals {
widgets: Widgets::default(),
selection: Selection::default(),
hyperlink_color: Color32::from_rgb(90, 170, 255),
faint_bg_color: Color32::from_gray(35),
extreme_bg_color: Color32::from_gray(10), // e.g. TextEdit background
faint_bg_color: Color32::from_additive_luminance(5), // visible, but barely so
extreme_bg_color: Color32::from_gray(10), // e.g. TextEdit background
code_bg_color: Color32::from_gray(64),
warn_fg_color: Color32::from_rgb(255, 143, 0), // orange
error_fg_color: Color32::from_rgb(255, 0, 0), // red
Expand Down Expand Up @@ -751,8 +764,8 @@ impl Visuals {
widgets: Widgets::light(),
selection: Selection::light(),
hyperlink_color: Color32::from_rgb(0, 155, 255),
faint_bg_color: Color32::from_gray(242),
extreme_bg_color: Color32::from_gray(255), // e.g. TextEdit background
faint_bg_color: Color32::from_additive_luminance(5), // visible, but barely so
extreme_bg_color: Color32::from_gray(255), // e.g. TextEdit background
code_bg_color: Color32::from_gray(230),
warn_fg_color: Color32::from_rgb(255, 100, 0), // slightly orange red. it's difficult to find a warning color that pops on bright background.
error_fg_color: Color32::from_rgb(255, 0, 0), // red
Expand Down Expand Up @@ -801,34 +814,39 @@ impl Widgets {
pub fn dark() -> Self {
Self {
noninteractive: WidgetVisuals {
weak_bg_fill: Color32::from_gray(27),
bg_fill: Color32::from_gray(27),
bg_stroke: Stroke::new(1.0, Color32::from_gray(60)), // separators, indentation lines
fg_stroke: Stroke::new(1.0, Color32::from_gray(140)), // normal text color
rounding: Rounding::same(2.0),
expansion: 0.0,
},
inactive: WidgetVisuals {
bg_fill: Color32::from_gray(60), // button background
weak_bg_fill: Color32::from_gray(60), // button background
bg_fill: Color32::from_gray(60), // checkbox background
bg_stroke: Default::default(),
fg_stroke: Stroke::new(1.0, Color32::from_gray(180)), // button text
rounding: Rounding::same(2.0),
expansion: 0.0,
},
hovered: WidgetVisuals {
weak_bg_fill: Color32::from_gray(70),
bg_fill: Color32::from_gray(70),
bg_stroke: Stroke::new(1.0, Color32::from_gray(150)), // e.g. hover over window edge or button
fg_stroke: Stroke::new(1.5, Color32::from_gray(240)),
rounding: Rounding::same(3.0),
expansion: 1.0,
},
active: WidgetVisuals {
weak_bg_fill: Color32::from_gray(55),
bg_fill: Color32::from_gray(55),
bg_stroke: Stroke::new(1.0, Color32::WHITE),
fg_stroke: Stroke::new(2.0, Color32::WHITE),
rounding: Rounding::same(2.0),
expansion: 1.0,
},
open: WidgetVisuals {
weak_bg_fill: Color32::from_gray(27),
bg_fill: Color32::from_gray(27),
bg_stroke: Stroke::new(1.0, Color32::from_gray(60)),
fg_stroke: Stroke::new(1.0, Color32::from_gray(210)),
Expand All @@ -841,34 +859,39 @@ impl Widgets {
pub fn light() -> Self {
Self {
noninteractive: WidgetVisuals {
weak_bg_fill: Color32::from_gray(248),
bg_fill: Color32::from_gray(248),
bg_stroke: Stroke::new(1.0, Color32::from_gray(190)), // separators, indentation lines
fg_stroke: Stroke::new(1.0, Color32::from_gray(80)), // normal text color
rounding: Rounding::same(2.0),
expansion: 0.0,
},
inactive: WidgetVisuals {
bg_fill: Color32::from_gray(230), // button background
weak_bg_fill: Color32::from_gray(230), // button background
bg_fill: Color32::from_gray(230), // checkbox background
bg_stroke: Default::default(),
fg_stroke: Stroke::new(1.0, Color32::from_gray(60)), // button text
rounding: Rounding::same(2.0),
expansion: 0.0,
},
hovered: WidgetVisuals {
weak_bg_fill: Color32::from_gray(220),
bg_fill: Color32::from_gray(220),
bg_stroke: Stroke::new(1.0, Color32::from_gray(105)), // e.g. hover over window edge or button
fg_stroke: Stroke::new(1.5, Color32::BLACK),
rounding: Rounding::same(3.0),
expansion: 1.0,
},
active: WidgetVisuals {
weak_bg_fill: Color32::from_gray(165),
bg_fill: Color32::from_gray(165),
bg_stroke: Stroke::new(1.0, Color32::BLACK),
fg_stroke: Stroke::new(2.0, Color32::BLACK),
rounding: Rounding::same(2.0),
expansion: 1.0,
},
open: WidgetVisuals {
weak_bg_fill: Color32::from_gray(220),
bg_fill: Color32::from_gray(220),
bg_stroke: Stroke::new(1.0, Color32::from_gray(160)),
fg_stroke: Stroke::new(1.0, Color32::BLACK),
Expand Down Expand Up @@ -984,6 +1007,7 @@ impl Spacing {
indent,
interact_size,
slider_width,
combo_width,
text_edit_width,
icon_width,
icon_width_inner,
Expand Down Expand Up @@ -1012,6 +1036,10 @@ impl Spacing {
ui.add(DragValue::new(slider_width).clamp_range(0.0..=1000.0));
ui.label("Slider width");
});
ui.horizontal(|ui| {
ui.add(DragValue::new(combo_width).clamp_range(0.0..=1000.0));
ui.label("ComboBox width");
});
ui.horizontal(|ui| {
ui.add(DragValue::new(text_edit_width).clamp_range(0.0..=1000.0));
ui.label("TextEdit width");
Expand Down Expand Up @@ -1185,13 +1213,17 @@ impl Selection {
impl WidgetVisuals {
pub fn ui(&mut self, ui: &mut crate::Ui) {
let Self {
bg_fill,
weak_bg_fill,
bg_fill: mandatory_bg_fill,
bg_stroke,
rounding,
fg_stroke,
expansion,
} = self;
ui_color(ui, bg_fill, "background fill");
ui_color(ui, weak_bg_fill, "optional background fill")
.on_hover_text("For buttons, combo-boxes, etc");
ui_color(ui, mandatory_bg_fill, "mandatory background fill")
.on_hover_text("For checkboxes, sliders, etc");
stroke_ui(ui, bg_stroke, "background stroke");

rounding_ui(ui, rounding);
Expand Down Expand Up @@ -1270,7 +1302,7 @@ impl Visuals {
} = self;

ui.collapsing("Background Colors", |ui| {
ui_color(ui, &mut widgets.inactive.bg_fill, "Buttons");
ui_color(ui, &mut widgets.inactive.weak_bg_fill, "Buttons");
ui_color(ui, window_fill, "Windows");
ui_color(ui, panel_fill, "Panels");
ui_color(ui, faint_bg_color, "Faint accent").on_hover_text(
Expand Down
6 changes: 3 additions & 3 deletions crates/egui/src/widgets/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,10 @@ impl Widget for Button {
desired_size.x += ui.spacing().item_spacing.x + shortcut_text.size().x;
desired_size.y = desired_size.y.max(shortcut_text.size().y);
}
desired_size += 2.0 * button_padding;
if !small {
desired_size.y = desired_size.y.at_least(ui.spacing().interact_size.y);
}
desired_size += 2.0 * button_padding;
desired_size = desired_size.at_least(min_size);

let (rect, response) = ui.allocate_at_least(desired_size, sense);
Expand All @@ -193,7 +193,7 @@ impl Widget for Button {
let visuals = ui.style().interact(&response);

if frame {
let fill = fill.unwrap_or(visuals.bg_fill);
let fill = fill.unwrap_or(visuals.weak_bg_fill);
let stroke = stroke.unwrap_or(visuals.bg_stroke);
let rounding = rounding.unwrap_or(visuals.rounding);
ui.painter()
Expand Down Expand Up @@ -540,7 +540,7 @@ impl Widget for ImageButton {
(
expansion,
visuals.rounding,
visuals.bg_fill,
visuals.weak_bg_fill,
visuals.bg_stroke,
)
} else {
Expand Down
Loading

0 comments on commit 4bd4eca

Please sign in to comment.