[style] Slightly expand buttons when hovering and interacting
This commit is contained in:
parent
1b40a5dda5
commit
6d8a766614
10 changed files with 45 additions and 20 deletions
|
@ -106,12 +106,14 @@ impl State {
|
||||||
|
|
||||||
/// Paint the arrow icon that indicated if the region is open or not
|
/// Paint the arrow icon that indicated if the region is open or not
|
||||||
pub(crate) fn paint_icon(ui: &mut Ui, openness: f32, response: &Response) {
|
pub(crate) fn paint_icon(ui: &mut Ui, openness: f32, response: &Response) {
|
||||||
let stroke = ui.style().interact(response).fg_stroke;
|
let visuals = ui.style().interact(response);
|
||||||
|
let stroke = visuals.fg_stroke;
|
||||||
|
|
||||||
let rect = response.rect;
|
let rect = response.rect;
|
||||||
|
|
||||||
// Draw a pointy triangle arrow:
|
// Draw a pointy triangle arrow:
|
||||||
let rect = Rect::from_center_size(rect.center(), vec2(rect.width(), rect.height()) * 0.75);
|
let rect = Rect::from_center_size(rect.center(), vec2(rect.width(), rect.height()) * 0.75);
|
||||||
|
let rect = rect.expand(visuals.expansion);
|
||||||
let mut points = vec![rect.left_top(), rect.right_top(), rect.center_bottom()];
|
let mut points = vec![rect.left_top(), rect.right_top(), rect.center_bottom()];
|
||||||
use std::f32::consts::TAU;
|
use std::f32::consts::TAU;
|
||||||
let rotation = math::Rot2::from_angle(remap(openness, 0.0..=1.0, -TAU / 4.0..=0.0));
|
let rotation = math::Rot2::from_angle(remap(openness, 0.0..=1.0, -TAU / 4.0..=0.0));
|
||||||
|
@ -203,10 +205,12 @@ impl CollapsingHeader {
|
||||||
state.toggle(ui);
|
state.toggle(ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let visuals = ui.style().interact(&header_response);
|
||||||
|
let text_color = visuals.text_color();
|
||||||
ui.painter().add(Shape::Rect {
|
ui.painter().add(Shape::Rect {
|
||||||
rect: header_response.rect,
|
rect: header_response.rect.expand(visuals.expansion),
|
||||||
corner_radius: ui.style().interact(&header_response).corner_radius,
|
corner_radius: visuals.corner_radius,
|
||||||
fill: ui.style().interact(&header_response).bg_fill,
|
fill: visuals.bg_fill,
|
||||||
stroke: Default::default(),
|
stroke: Default::default(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -228,7 +232,7 @@ impl CollapsingHeader {
|
||||||
text_pos,
|
text_pos,
|
||||||
galley,
|
galley,
|
||||||
label.text_style_or_default(ui.style()),
|
label.text_style_or_default(ui.style()),
|
||||||
ui.style().interact(&header_response).text_color(),
|
text_color,
|
||||||
);
|
);
|
||||||
|
|
||||||
Prepared {
|
Prepared {
|
||||||
|
|
|
@ -79,7 +79,7 @@ pub fn combo_box(
|
||||||
|
|
||||||
let icon_rect = Align2::RIGHT_CENTER.align_size_within_rect(icon_size, rect);
|
let icon_rect = Align2::RIGHT_CENTER.align_size_within_rect(icon_size, rect);
|
||||||
let visuals = ui.style().interact(&response);
|
let visuals = ui.style().interact(&response);
|
||||||
paint_icon(ui.painter(), icon_rect, visuals);
|
paint_icon(ui.painter(), icon_rect.expand(visuals.expansion), visuals);
|
||||||
|
|
||||||
let text_rect = Align2::LEFT_CENTER.align_size_within_rect(galley.size, rect);
|
let text_rect = Align2::LEFT_CENTER.align_size_within_rect(galley.size, rect);
|
||||||
ui.painter()
|
ui.painter()
|
||||||
|
@ -145,7 +145,7 @@ fn button_frame(
|
||||||
ui.painter().set(
|
ui.painter().set(
|
||||||
where_to_put_background,
|
where_to_put_background,
|
||||||
Shape::Rect {
|
Shape::Rect {
|
||||||
rect: outer_rect,
|
rect: outer_rect.expand(visuals.expansion),
|
||||||
corner_radius: visuals.corner_radius,
|
corner_radius: visuals.corner_radius,
|
||||||
fill: visuals.bg_fill,
|
fill: visuals.bg_fill,
|
||||||
stroke: visuals.bg_stroke,
|
stroke: visuals.bg_stroke,
|
||||||
|
|
|
@ -767,9 +767,9 @@ fn close_button(ui: &mut Ui, rect: Rect) -> Response {
|
||||||
let response = ui.interact(rect, close_id, Sense::click());
|
let response = ui.interact(rect, close_id, Sense::click());
|
||||||
ui.expand_to_include_rect(response.rect);
|
ui.expand_to_include_rect(response.rect);
|
||||||
|
|
||||||
let rect = rect.shrink(2.0);
|
let visuals = ui.style().interact(&response);
|
||||||
|
let rect = rect.shrink(2.0).expand(visuals.expansion);
|
||||||
let stroke = ui.style().interact(&response).fg_stroke;
|
let stroke = visuals.fg_stroke;
|
||||||
ui.painter()
|
ui.painter()
|
||||||
.line_segment([rect.left_top(), rect.right_bottom()], stroke);
|
.line_segment([rect.left_top(), rect.right_bottom()], stroke);
|
||||||
ui.painter()
|
ui.painter()
|
||||||
|
|
|
@ -227,6 +227,9 @@ pub struct WidgetVisuals {
|
||||||
|
|
||||||
/// Stroke and text color of the interactive part of a component (button text, slider grab, check-mark, ...)
|
/// Stroke and text color of the interactive part of a component (button text, slider grab, check-mark, ...)
|
||||||
pub fg_stroke: Stroke,
|
pub fg_stroke: Stroke,
|
||||||
|
|
||||||
|
/// Make the frame this much larger
|
||||||
|
pub expansion: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WidgetVisuals {
|
impl WidgetVisuals {
|
||||||
|
@ -287,7 +290,7 @@ impl Default for Visuals {
|
||||||
window_shadow: Shadow::big(),
|
window_shadow: Shadow::big(),
|
||||||
resize_corner_size: 12.0,
|
resize_corner_size: 12.0,
|
||||||
text_cursor_width: 2.0,
|
text_cursor_width: 2.0,
|
||||||
clip_rect_margin: 1.0, // should be half the size of the widest frame stroke
|
clip_rect_margin: 3.0, // should be at least half the size of the widest frame stroke + max WidgetVisuals::expansion
|
||||||
debug_expand_width: false,
|
debug_expand_width: false,
|
||||||
debug_expand_height: false,
|
debug_expand_height: false,
|
||||||
debug_resize: false,
|
debug_resize: false,
|
||||||
|
@ -316,6 +319,7 @@ impl Default for Widgets {
|
||||||
corner_radius: 4.0,
|
corner_radius: 4.0,
|
||||||
fg_fill: Color32::from_rgb(120, 120, 200),
|
fg_fill: Color32::from_rgb(120, 120, 200),
|
||||||
fg_stroke: Stroke::new(2.0, Color32::WHITE),
|
fg_stroke: Stroke::new(2.0, Color32::WHITE),
|
||||||
|
expansion: 2.0,
|
||||||
},
|
},
|
||||||
hovered: WidgetVisuals {
|
hovered: WidgetVisuals {
|
||||||
bg_fill: Rgba::from_luminance_alpha(0.06, 0.5).into(),
|
bg_fill: Rgba::from_luminance_alpha(0.06, 0.5).into(),
|
||||||
|
@ -323,6 +327,7 @@ impl Default for Widgets {
|
||||||
corner_radius: 4.0,
|
corner_radius: 4.0,
|
||||||
fg_fill: Color32::from_rgb(100, 100, 150),
|
fg_fill: Color32::from_rgb(100, 100, 150),
|
||||||
fg_stroke: Stroke::new(1.5, Color32::from_gray(240)),
|
fg_stroke: Stroke::new(1.5, Color32::from_gray(240)),
|
||||||
|
expansion: 1.0,
|
||||||
},
|
},
|
||||||
inactive: WidgetVisuals {
|
inactive: WidgetVisuals {
|
||||||
bg_fill: Rgba::from_luminance_alpha(0.04, 0.5).into(),
|
bg_fill: Rgba::from_luminance_alpha(0.04, 0.5).into(),
|
||||||
|
@ -330,6 +335,7 @@ impl Default for Widgets {
|
||||||
corner_radius: 4.0,
|
corner_radius: 4.0,
|
||||||
fg_fill: Color32::from_rgb(60, 60, 80),
|
fg_fill: Color32::from_rgb(60, 60, 80),
|
||||||
fg_stroke: Stroke::new(1.0, Color32::from_gray(200)), // Should NOT look grayed out!
|
fg_stroke: Stroke::new(1.0, Color32::from_gray(200)), // Should NOT look grayed out!
|
||||||
|
expansion: 0.0,
|
||||||
},
|
},
|
||||||
disabled: WidgetVisuals {
|
disabled: WidgetVisuals {
|
||||||
bg_fill: Rgba::from_luminance_alpha(0.02, 0.5).into(),
|
bg_fill: Rgba::from_luminance_alpha(0.02, 0.5).into(),
|
||||||
|
@ -337,6 +343,7 @@ impl Default for Widgets {
|
||||||
corner_radius: 4.0,
|
corner_radius: 4.0,
|
||||||
fg_fill: Color32::from_rgb(50, 50, 50),
|
fg_fill: Color32::from_rgb(50, 50, 50),
|
||||||
fg_stroke: Stroke::new(1.0, Color32::from_gray(140)), // Should look grayed out
|
fg_stroke: Stroke::new(1.0, Color32::from_gray(140)), // Should look grayed out
|
||||||
|
expansion: 0.0,
|
||||||
},
|
},
|
||||||
noninteractive: WidgetVisuals {
|
noninteractive: WidgetVisuals {
|
||||||
bg_stroke: Stroke::new(1.0, Rgba::from_white_alpha(0.06)),
|
bg_stroke: Stroke::new(1.0, Rgba::from_white_alpha(0.06)),
|
||||||
|
@ -344,6 +351,7 @@ impl Default for Widgets {
|
||||||
corner_radius: 4.0,
|
corner_radius: 4.0,
|
||||||
fg_fill: Default::default(),
|
fg_fill: Default::default(),
|
||||||
fg_stroke: Stroke::new(1.0, Color32::from_gray(160)), // text color
|
fg_stroke: Stroke::new(1.0, Color32::from_gray(160)), // text color
|
||||||
|
expansion: 0.0,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -460,6 +468,7 @@ impl WidgetVisuals {
|
||||||
corner_radius,
|
corner_radius,
|
||||||
fg_fill,
|
fg_fill,
|
||||||
fg_stroke,
|
fg_stroke,
|
||||||
|
expansion,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
ui_color(ui, bg_fill, "bg_fill");
|
ui_color(ui, bg_fill, "bg_fill");
|
||||||
|
@ -467,6 +476,7 @@ impl WidgetVisuals {
|
||||||
ui.add(Slider::f32(corner_radius, 0.0..=10.0).text("corner_radius"));
|
ui.add(Slider::f32(corner_radius, 0.0..=10.0).text("corner_radius"));
|
||||||
ui_color(ui, fg_fill, "fg_fill");
|
ui_color(ui, fg_fill, "fg_fill");
|
||||||
stroke_ui(ui, fg_stroke, "fg_stroke (text)");
|
stroke_ui(ui, fg_stroke, "fg_stroke (text)");
|
||||||
|
ui.add(Slider::f32(expansion, -5.0..=5.0).text("expansion"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,8 +117,12 @@ impl Widget for Button {
|
||||||
|
|
||||||
if frame {
|
if frame {
|
||||||
let fill = fill.unwrap_or(visuals.bg_fill);
|
let fill = fill.unwrap_or(visuals.bg_fill);
|
||||||
ui.painter()
|
ui.painter().rect(
|
||||||
.rect(rect, visuals.corner_radius, fill, visuals.bg_stroke);
|
rect.expand(visuals.expansion),
|
||||||
|
visuals.corner_radius,
|
||||||
|
fill,
|
||||||
|
visuals.bg_stroke,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let text_color = text_color
|
let text_color = text_color
|
||||||
|
@ -198,7 +202,7 @@ impl<'a> Widget for Checkbox<'a> {
|
||||||
);
|
);
|
||||||
let (small_icon_rect, big_icon_rect) = ui.style().spacing.icon_rectangles(rect);
|
let (small_icon_rect, big_icon_rect) = ui.style().spacing.icon_rectangles(rect);
|
||||||
ui.painter().add(Shape::Rect {
|
ui.painter().add(Shape::Rect {
|
||||||
rect: big_icon_rect,
|
rect: big_icon_rect.expand(visuals.expansion),
|
||||||
corner_radius: visuals.corner_radius,
|
corner_radius: visuals.corner_radius,
|
||||||
fill: visuals.bg_fill,
|
fill: visuals.bg_fill,
|
||||||
stroke: visuals.bg_stroke,
|
stroke: visuals.bg_stroke,
|
||||||
|
@ -292,7 +296,7 @@ impl Widget for RadioButton {
|
||||||
|
|
||||||
painter.add(Shape::Circle {
|
painter.add(Shape::Circle {
|
||||||
center: big_icon_rect.center(),
|
center: big_icon_rect.center(),
|
||||||
radius: big_icon_rect.width() / 2.0,
|
radius: big_icon_rect.width() / 2.0 + visuals.expansion,
|
||||||
fill: visuals.bg_fill,
|
fill: visuals.bg_fill,
|
||||||
stroke: visuals.bg_stroke,
|
stroke: visuals.bg_stroke,
|
||||||
});
|
});
|
||||||
|
@ -392,7 +396,7 @@ impl Widget for ImageButton {
|
||||||
.rect(rect, 0.0, selection.bg_fill, selection.stroke);
|
.rect(rect, 0.0, selection.bg_fill, selection.stroke);
|
||||||
} else if frame {
|
} else if frame {
|
||||||
ui.painter().rect(
|
ui.painter().rect(
|
||||||
rect,
|
rect.expand(visuals.expansion),
|
||||||
visuals.corner_radius,
|
visuals.corner_radius,
|
||||||
visuals.bg_fill,
|
visuals.bg_fill,
|
||||||
visuals.bg_stroke,
|
visuals.bg_stroke,
|
||||||
|
|
|
@ -60,6 +60,7 @@ fn color_button(ui: &mut Ui, color: Color32) -> Response {
|
||||||
let desired_size = ui.style().spacing.interact_size;
|
let desired_size = ui.style().spacing.interact_size;
|
||||||
let (rect, response) = ui.allocate_at_least(desired_size, Sense::click());
|
let (rect, response) = ui.allocate_at_least(desired_size, Sense::click());
|
||||||
let visuals = ui.style().interact(&response);
|
let visuals = ui.style().interact(&response);
|
||||||
|
let rect = rect.expand(visuals.expansion);
|
||||||
background_checkers(ui.painter(), rect);
|
background_checkers(ui.painter(), rect);
|
||||||
ui.painter().add(Shape::Rect {
|
ui.painter().add(Shape::Rect {
|
||||||
rect,
|
rect,
|
||||||
|
|
|
@ -43,6 +43,7 @@ impl Widget for SelectableLabel {
|
||||||
let visuals = ui.style().interact(&response);
|
let visuals = ui.style().interact(&response);
|
||||||
|
|
||||||
if selected || response.hovered {
|
if selected || response.hovered {
|
||||||
|
let rect = rect.expand(visuals.expansion);
|
||||||
let bg_fill = if selected {
|
let bg_fill = if selected {
|
||||||
ui.style().visuals.selection.bg_fill
|
ui.style().visuals.selection.bg_fill
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -278,18 +278,21 @@ impl<'a> Slider<'a> {
|
||||||
);
|
);
|
||||||
let marker_center_x = self.x_from_value(value, x_range);
|
let marker_center_x = self.x_from_value(value, x_range);
|
||||||
|
|
||||||
|
let visuals = ui.style().interact(response);
|
||||||
ui.painter().add(Shape::Rect {
|
ui.painter().add(Shape::Rect {
|
||||||
rect: rail_rect,
|
rect: rail_rect,
|
||||||
corner_radius: rail_radius,
|
corner_radius: rail_radius,
|
||||||
|
// fill: visuals.bg_fill,
|
||||||
fill: ui.style().visuals.widgets.inactive.bg_fill,
|
fill: ui.style().visuals.widgets.inactive.bg_fill,
|
||||||
|
// stroke: visuals.bg_stroke,
|
||||||
stroke: ui.style().visuals.widgets.inactive.bg_stroke,
|
stroke: ui.style().visuals.widgets.inactive.bg_stroke,
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.painter().add(Shape::Circle {
|
ui.painter().add(Shape::Circle {
|
||||||
center: pos2(marker_center_x, rail_rect.center().y),
|
center: pos2(marker_center_x, rail_rect.center().y),
|
||||||
radius: handle_radius(rect),
|
radius: handle_radius(rect) + visuals.expansion,
|
||||||
fill: ui.style().interact(response).fg_fill,
|
fill: visuals.fg_fill,
|
||||||
stroke: ui.style().interact(response).fg_stroke,
|
stroke: visuals.fg_stroke,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,7 +228,7 @@ impl<'t> Widget for TextEdit<'t> {
|
||||||
let response = response | ui.allocate_response(frame_rect.size(), Sense::click());
|
let response = response | ui.allocate_response(frame_rect.size(), Sense::click());
|
||||||
|
|
||||||
let visuals = ui.style().interact(&response);
|
let visuals = ui.style().interact(&response);
|
||||||
let frame_rect = response.rect;
|
let frame_rect = response.rect.expand(visuals.expansion);
|
||||||
ui.painter().set(
|
ui.painter().set(
|
||||||
where_to_put_background,
|
where_to_put_background,
|
||||||
Shape::Rect {
|
Shape::Rect {
|
||||||
|
|
|
@ -44,6 +44,7 @@ pub fn toggle(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
|
||||||
let on_bg_fill = egui::Rgba::from_rgb(0.0, 0.5, 0.25);
|
let on_bg_fill = egui::Rgba::from_rgb(0.0, 0.5, 0.25);
|
||||||
let bg_fill = egui::lerp(off_bg_fill..=on_bg_fill, how_on);
|
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 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, 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`:
|
||||||
|
@ -69,6 +70,7 @@ fn toggle_compact(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
|
||||||
let off_bg_fill = egui::Rgba::TRANSPARENT;
|
let off_bg_fill = egui::Rgba::TRANSPARENT;
|
||||||
let on_bg_fill = egui::Rgba::from_rgb(0.0, 0.5, 0.25);
|
let on_bg_fill = egui::Rgba::from_rgb(0.0, 0.5, 0.25);
|
||||||
let bg_fill = egui::lerp(off_bg_fill..=on_bg_fill, how_on);
|
let bg_fill = egui::lerp(off_bg_fill..=on_bg_fill, how_on);
|
||||||
|
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, 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);
|
||||||
|
|
Loading…
Reference in a new issue