Simplify and unify colors of selectable widgets

This commit is contained in:
Emil Ernerfeldt 2021-02-20 11:28:00 +01:00
parent 741f0bfe8a
commit 6fe70e685b
4 changed files with 29 additions and 36 deletions

View file

@ -39,6 +39,16 @@ impl Style {
self.visuals.widgets.style(response) self.visuals.widgets.style(response)
} }
pub fn interact_selectable(&self, response: &Response, selected: bool) -> WidgetVisuals {
let mut visuals = *self.visuals.widgets.style(response);
if selected {
visuals.bg_fill = self.visuals.selection.bg_fill;
// visuals.bg_stroke = self.visuals.selection.stroke;
visuals.fg_stroke = self.visuals.selection.stroke;
}
visuals
}
/// Style to use for non-interactive widgets. /// Style to use for non-interactive widgets.
pub fn noninteractive(&self) -> &WidgetVisuals { pub fn noninteractive(&self) -> &WidgetVisuals {
&self.visuals.widgets.noninteractive &self.visuals.widgets.noninteractive
@ -357,17 +367,14 @@ impl Default for Visuals {
impl Selection { impl Selection {
fn dark() -> Self { fn dark() -> Self {
Self { Self {
bg_fill: Rgba::from_rgb(0.0, 0.5, 1.0) bg_fill: Color32::from_rgb(0, 92, 128),
.additive() stroke: Stroke::new(1.0, Color32::from_rgb(192, 222, 255)),
.multiply(0.10)
.into(),
stroke: Stroke::new(1.0, Rgba::from_rgb(0.3, 0.6, 1.0)),
} }
} }
fn light() -> Self { fn light() -> Self {
Self { Self {
bg_fill: Rgba::from_rgb(0.0, 0.5, 1.0).multiply(0.5).into(), bg_fill: Color32::from_rgb(144, 209, 255),
stroke: Stroke::new(1.0, Rgba::from_rgb(0.3, 0.6, 1.0)), stroke: Stroke::new(1.0, Color32::from_rgb(0, 83, 125)),
} }
} }
} }

View file

@ -212,6 +212,7 @@ impl<'a> Widget for Checkbox<'a> {
*checked = !*checked; *checked = !*checked;
} }
// let visuals = ui.style().interact_selectable(&response, *checked); // too colorful
let visuals = ui.style().interact(&response); let visuals = ui.style().interact(&response);
let text_cursor = pos2( let text_cursor = pos2(
rect.min.x + button_padding.x + icon_width + icon_spacing, rect.min.x + button_padding.x + icon_width + icon_spacing,
@ -234,7 +235,6 @@ impl<'a> Widget for Checkbox<'a> {
pos2(small_icon_rect.right(), small_icon_rect.top()), pos2(small_icon_rect.right(), small_icon_rect.top()),
], ],
visuals.fg_stroke, visuals.fg_stroke,
// ui.visuals().selection.stroke, // too much color
)); ));
} }
@ -305,6 +305,7 @@ impl Widget for RadioButton {
rect.center().y - 0.5 * galley.size.y, rect.center().y - 0.5 * galley.size.y,
); );
// let visuals = ui.style().interact_selectable(&response, checked); // too colorful
let visuals = ui.style().interact(&response); let visuals = ui.style().interact(&response);
let (small_icon_rect, big_icon_rect) = ui.spacing().icon_rectangles(rect); let (small_icon_rect, big_icon_rect) = ui.spacing().icon_rectangles(rect);

View file

@ -44,25 +44,14 @@ impl Widget for SelectableLabel {
.align_size_within_rect(galley.size, rect.shrink2(button_padding)) .align_size_within_rect(galley.size, rect.shrink2(button_padding))
.min; .min;
let visuals = ui.style().interact(&response); let visuals = ui.style().interact_selectable(&response, selected);
if selected || response.hovered() { if selected || response.hovered() {
let rect = rect.expand(visuals.expansion); let rect = rect.expand(visuals.expansion);
let fill = if selected {
ui.visuals().selection.bg_fill
} else {
Default::default()
};
let stroke = if selected {
ui.visuals().selection.stroke
} else {
visuals.bg_stroke
};
let corner_radius = 2.0; let corner_radius = 2.0;
ui.painter().rect(rect, corner_radius, fill, stroke); ui.painter()
.rect(rect, corner_radius, visuals.bg_fill, visuals.bg_stroke);
} }
let text_color = ui let text_color = ui

View file

@ -18,8 +18,8 @@ pub fn toggle(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
// 1. Deciding widget size: // 1. Deciding widget size:
// You can query the `ui` how much space is available, // You can query the `ui` how much space is available,
// but in this example we have a fixed size widget of the default size for a button: // but in this example we have a fixed size widget based on the height of a standard button:
let desired_size = ui.spacing().interact_size; let desired_size = ui.spacing().interact_size.y * egui::vec2(2.0, 1.0);
// 2. Allocating space: // 2. Allocating space:
// This is where we get a region of the screen assigned. // This is where we get a region of the screen assigned.
@ -39,14 +39,12 @@ pub fn toggle(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
// We will follow the current style by asking // We will follow the current style by asking
// "how should something that is being interacted with be painted?". // "how should something that is being interacted with be painted?".
// This will, for instance, give us different colors when the widget is hovered or clicked. // This will, for instance, give us different colors when the widget is hovered or clicked.
let visuals = ui.style().interact(&response); let visuals = ui.style().interact_selectable(&response, *on);
let off_bg_fill = egui::Rgba::from(visuals.bg_fill);
let on_bg_fill = egui::Rgba::from_rgb(0.0, 0.5, 0.0);
let bg_fill = egui::lerp(off_bg_fill..=on_bg_fill, how_on);
// All coordinates are in absolute screen coordinates so we use `rect` to place the elements. // All coordinates are in absolute screen coordinates so we use `rect` to place the elements.
let rect = rect.expand(visuals.expansion); let rect = rect.expand(visuals.expansion);
let radius = 0.5 * rect.height(); let radius = 0.5 * rect.height();
ui.painter().rect(rect, radius, bg_fill, visuals.bg_stroke); ui.painter()
.rect(rect, radius, visuals.bg_fill, visuals.bg_stroke);
// Paint the circle, animating it from left to right with `how_on`: // Paint the circle, animating it from left to right with `how_on`:
let circle_x = egui::lerp((rect.left() + radius)..=(rect.right() - radius), how_on); let circle_x = egui::lerp((rect.left() + radius)..=(rect.right() - radius), how_on);
let center = egui::pos2(circle_x, rect.center().y); let center = egui::pos2(circle_x, rect.center().y);
@ -61,18 +59,16 @@ pub fn toggle(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
/// Here is the same code again, but a bit more compact: /// Here is the same code again, but a bit more compact:
#[allow(dead_code)] #[allow(dead_code)]
fn toggle_compact(ui: &mut egui::Ui, on: &mut bool) -> egui::Response { fn toggle_compact(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
let desired_size = ui.spacing().interact_size; let desired_size = ui.spacing().interact_size.y * egui::vec2(2.0, 1.0);
let (rect, response) = ui.allocate_exact_size(desired_size, egui::Sense::click()); let (rect, response) = ui.allocate_exact_size(desired_size, egui::Sense::click());
*on ^= response.clicked(); // toggle if clicked *on ^= response.clicked(); // toggle if clicked
let how_on = ui.ctx().animate_bool(response.id, *on); let how_on = ui.ctx().animate_bool(response.id, *on);
let visuals = ui.style().interact(&response); let visuals = ui.style().interact_selectable(&response, *on);
let off_bg_fill = egui::Rgba::from(visuals.bg_fill);
let on_bg_fill = egui::Rgba::from_rgb(0.0, 0.5, 0.0);
let bg_fill = egui::lerp(off_bg_fill..=on_bg_fill, how_on);
let rect = rect.expand(visuals.expansion); let rect = rect.expand(visuals.expansion);
let radius = 0.5 * rect.height(); let radius = 0.5 * rect.height();
ui.painter().rect(rect, radius, bg_fill, visuals.bg_stroke); ui.painter()
.rect(rect, radius, visuals.bg_fill, visuals.bg_stroke);
let circle_x = egui::lerp((rect.left() + radius)..=(rect.right() - radius), how_on); let circle_x = egui::lerp((rect.left() + radius)..=(rect.right() - radius), how_on);
let center = egui::pos2(circle_x, rect.center().y); let center = egui::pos2(circle_x, rect.center().y);
ui.painter() ui.painter()
@ -89,6 +85,6 @@ pub fn demo(ui: &mut egui::Ui, on: &mut bool) {
.response .response
.on_hover_text( .on_hover_text(
"It's easy to create your own widgets!\n\ "It's easy to create your own widgets!\n\
This toggle switch is just one function and 20 lines of code.", This toggle switch is just one function and 15 lines of code.",
); );
} }