Per-side margins with new struct Margin (#1219)

This commit is contained in:
Erlend Walstad 2022-02-07 11:29:16 +01:00 committed by GitHub
parent 603ec82a5e
commit 2802e03526
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 102 additions and 22 deletions

View file

@ -39,6 +39,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w
* `TextStyle` is no longer `Copy` ([#1154](https://github.com/emilk/egui/pull/1154)).
* Replaced `TextEdit::text_style` with `TextEdit::font` ([#1154](https://github.com/emilk/egui/pull/1154)).
* Replaced `corner_radius: f32` with `rounding: Rounding`, allowing per-corner rounding settings ([#1206](https://github.com/emilk/egui/pull/1206)).
* Replaced Frame's `margin: Vec2` with `margin: Margin`, allowing for different margins on opposing sides ([#1219](https://github.com/emilk/egui/pull/1219)).
* `Plot::highlight` now takes a `bool` argument ([#1159](https://github.com/emilk/egui/pull/1159)).
* `ScrollArea::show` now returns a `ScrollAreaOutput`, so you might need to add `.inner` after the call to it ([#1166](https://github.com/emilk/egui/pull/1166)).

View file

@ -3,12 +3,55 @@
use crate::{layers::ShapeIdx, *};
use epaint::*;
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Margin {
pub left: f32,
pub right: f32,
pub top: f32,
pub bottom: f32,
}
impl Margin {
#[inline]
pub fn same(margin: f32) -> Self {
Self {
left: margin,
right: margin,
top: margin,
bottom: margin,
}
}
/// Margins with the same size on opposing sides
#[inline]
pub fn symmetric(x: f32, y: f32) -> Self {
Self {
left: x,
right: x,
top: y,
bottom: y,
}
}
/// Total margins on both sides
pub fn sum(&self) -> Vec2 {
Vec2::new(self.left + self.right, self.top + self.bottom)
}
}
impl From<Vec2> for Margin {
fn from(v: Vec2) -> Self {
Self::symmetric(v.x, v.y)
}
}
/// Color and margin of a rectangular background of a [`Ui`].
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[must_use = "You should call .show()"]
pub struct Frame {
/// On each side
pub margin: Vec2,
pub margin: Margin,
pub rounding: Rounding,
pub shadow: Shadow,
pub fill: Color32,
@ -23,7 +66,7 @@ impl Frame {
/// For when you want to group a few widgets together within a frame.
pub fn group(style: &Style) -> Self {
Self {
margin: Vec2::splat(6.0), // symmetric looks best in corners when nesting
margin: Margin::same(6.0), // symmetric looks best in corners when nesting
rounding: style.visuals.widgets.noninteractive.rounding,
stroke: style.visuals.widgets.noninteractive.bg_stroke,
..Default::default()
@ -32,7 +75,7 @@ impl Frame {
pub(crate) fn side_top_panel(style: &Style) -> Self {
Self {
margin: Vec2::new(8.0, 2.0),
margin: Margin::symmetric(8.0, 2.0),
rounding: Rounding::none(),
fill: style.visuals.window_fill(),
stroke: style.visuals.window_stroke(),
@ -42,7 +85,7 @@ impl Frame {
pub(crate) fn central_panel(style: &Style) -> Self {
Self {
margin: Vec2::new(8.0, 8.0),
margin: Margin::symmetric(8.0, 8.0),
rounding: Rounding::none(),
fill: style.visuals.window_fill(),
stroke: Default::default(),
@ -52,7 +95,7 @@ impl Frame {
pub fn window(style: &Style) -> Self {
Self {
margin: style.spacing.window_padding,
margin: style.spacing.window_margin,
rounding: style.visuals.window_rounding,
shadow: style.visuals.window_shadow,
fill: style.visuals.window_fill(),
@ -62,7 +105,7 @@ impl Frame {
pub fn menu(style: &Style) -> Self {
Self {
margin: Vec2::splat(1.0),
margin: Margin::same(1.0),
rounding: style.visuals.widgets.noninteractive.rounding,
shadow: style.visuals.popup_shadow,
fill: style.visuals.window_fill(),
@ -72,7 +115,7 @@ impl Frame {
pub fn popup(style: &Style) -> Self {
Self {
margin: style.spacing.window_padding,
margin: style.spacing.window_margin,
rounding: style.visuals.widgets.noninteractive.rounding,
shadow: style.visuals.popup_shadow,
fill: style.visuals.window_fill(),
@ -83,7 +126,7 @@ impl Frame {
/// dark canvas to draw on
pub fn dark_canvas(style: &Style) -> Self {
Self {
margin: Vec2::new(10.0, 10.0),
margin: Margin::symmetric(10.0, 10.0),
rounding: style.visuals.widgets.noninteractive.rounding,
fill: Color32::from_black_alpha(250),
stroke: style.visuals.window_stroke(),
@ -109,7 +152,7 @@ impl Frame {
}
/// Margin on each side of the frame.
pub fn margin(mut self, margin: impl Into<Vec2>) -> Self {
pub fn margin(mut self, margin: impl Into<Margin>) -> Self {
self.margin = margin.into();
self
}
@ -137,7 +180,10 @@ impl Frame {
pub fn begin(self, ui: &mut Ui) -> Prepared {
let where_to_put_background = ui.painter().add(Shape::Noop);
let outer_rect_bounds = ui.available_rect_before_wrap();
let mut inner_rect = outer_rect_bounds.shrink2(self.margin);
let mut inner_rect = outer_rect_bounds;
inner_rect.min += Vec2::new(self.margin.left, self.margin.top);
inner_rect.max -= Vec2::new(self.margin.right, self.margin.bottom);
// Make sure we don't shrink to the negative:
inner_rect.max.x = inner_rect.max.x.max(inner_rect.min.x);
@ -197,7 +243,10 @@ impl Frame {
impl Prepared {
pub fn outer_rect(&self) -> Rect {
self.content_ui.min_rect().expand2(self.frame.margin)
let mut rect = self.content_ui.min_rect();
rect.min -= Vec2::new(self.frame.margin.left, self.frame.margin.top);
rect.max += Vec2::new(self.frame.margin.right, self.frame.margin.bottom);
rect
}
pub fn end(self, ui: &mut Ui) -> Response {

View file

@ -16,7 +16,7 @@ pub use {
area::Area,
collapsing_header::{CollapsingHeader, CollapsingResponse},
combo_box::*,
frame::Frame,
frame::{Frame, Margin},
panel::{CentralPanel, SidePanel, TopBottomPanel},
popup::*,
resize::Resize,

View file

@ -302,7 +302,7 @@ pub fn popup_below_widget<R>(
frame
.show(ui, |ui| {
ui.with_layout(Layout::top_down_justified(Align::LEFT), |ui| {
ui.set_width(widget_response.rect.width() - 2.0 * frame_margin.x);
ui.set_width(widget_response.rect.width() - frame_margin.sum().x);
add_contents(ui)
})
.inner

View file

@ -178,7 +178,7 @@ impl Resize {
.at_least(self.min_size)
.at_most(self.max_size)
.at_most(
ui.input().screen_rect().size() - 2.0 * ui.spacing().window_padding, // hack for windows
ui.input().screen_rect().size() - ui.spacing().window_margin.sum(), // hack for windows
);
State {

View file

@ -301,7 +301,7 @@ impl<'open> Window<'open> {
} else {
0.0
};
let margins = 2.0 * frame.margin + vec2(0.0, title_bar_height);
let margins = frame.margin.sum() + vec2(0.0, title_bar_height);
interact(
window_interaction,

View file

@ -2,7 +2,7 @@
#![allow(clippy::if_same_then_else)]
use crate::{color::*, emath::*, FontFamily, FontId, Response, RichText, WidgetText};
use crate::{color::*, emath::*, FontFamily, FontId, Margin, Response, RichText, WidgetText};
use epaint::{mutex::Arc, Rounding, Shadow, Stroke};
use std::collections::BTreeMap;
@ -220,8 +220,8 @@ pub struct Spacing {
/// widgets `A` and `B` you need to change `item_spacing` before adding `A`.
pub item_spacing: Vec2,
/// Horizontal and vertical padding within a window frame.
pub window_padding: Vec2,
/// Horizontal and vertical margins within a window frame.
pub window_margin: Margin,
/// Button size is text size plus this on each side
pub button_padding: Vec2,
@ -528,7 +528,7 @@ impl Default for Spacing {
fn default() -> Self {
Self {
item_spacing: vec2(8.0, 3.0),
window_padding: Vec2::splat(6.0),
window_margin: Margin::same(6.0),
button_padding: vec2(4.0, 1.0),
indent: 18.0, // match checkbox/radio-button with `button_padding.x + icon_width + icon_spacing`
interact_size: vec2(40.0, 18.0),
@ -803,7 +803,7 @@ impl Spacing {
pub fn ui(&mut self, ui: &mut crate::Ui) {
let Self {
item_spacing,
window_padding,
window_margin,
button_padding,
indent,
interact_size,
@ -818,7 +818,37 @@ impl Spacing {
} = self;
ui.add(slider_vec2(item_spacing, 0.0..=20.0, "Item spacing"));
ui.add(slider_vec2(window_padding, 0.0..=20.0, "Window padding"));
let margin_range = 0.0..=20.0;
ui.horizontal(|ui| {
ui.add(
DragValue::new(&mut window_margin.left)
.clamp_range(margin_range.clone())
.prefix("left: "),
);
ui.add(
DragValue::new(&mut window_margin.right)
.clamp_range(margin_range.clone())
.prefix("right: "),
);
ui.label("Window margins x");
});
ui.horizontal(|ui| {
ui.add(
DragValue::new(&mut window_margin.top)
.clamp_range(margin_range.clone())
.prefix("top: "),
);
ui.add(
DragValue::new(&mut window_margin.bottom)
.clamp_range(margin_range)
.prefix("bottom: "),
);
ui.label("Window margins y");
});
ui.add(slider_vec2(button_padding, 0.0..=20.0, "Button padding"));
ui.add(slider_vec2(interact_size, 4.0..=60.0, "Interact size"))
.on_hover_text("Minimum size of an interactive widget");

View file

@ -239,7 +239,7 @@ impl Widget for &mut LegendWidget {
legend_ui
.scope(|ui| {
let background_frame = Frame {
margin: vec2(8.0, 4.0),
margin: vec2(8.0, 4.0).into(),
rounding: ui.style().visuals.window_rounding,
shadow: epaint::Shadow::default(),
fill: ui.style().visuals.extreme_bg_color,