Skip to content

Commit 2802e03

Browse files
authored
Per-side margins with new struct Margin (#1219)
1 parent 603ec82 commit 2802e03

File tree

8 files changed

+102
-22
lines changed

8 files changed

+102
-22
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w
3939
* `TextStyle` is no longer `Copy` ([#1154](https://github.com/emilk/egui/pull/1154)).
4040
* Replaced `TextEdit::text_style` with `TextEdit::font` ([#1154](https://github.com/emilk/egui/pull/1154)).
4141
* Replaced `corner_radius: f32` with `rounding: Rounding`, allowing per-corner rounding settings ([#1206](https://github.com/emilk/egui/pull/1206)).
42+
* Replaced Frame's `margin: Vec2` with `margin: Margin`, allowing for different margins on opposing sides ([#1219](https://github.com/emilk/egui/pull/1219)).
4243
* `Plot::highlight` now takes a `bool` argument ([#1159](https://github.com/emilk/egui/pull/1159)).
4344
* `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)).
4445

egui/src/containers/frame.rs

+60-11
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,55 @@
33
use crate::{layers::ShapeIdx, *};
44
use epaint::*;
55

6+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
7+
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
8+
pub struct Margin {
9+
pub left: f32,
10+
pub right: f32,
11+
pub top: f32,
12+
pub bottom: f32,
13+
}
14+
15+
impl Margin {
16+
#[inline]
17+
pub fn same(margin: f32) -> Self {
18+
Self {
19+
left: margin,
20+
right: margin,
21+
top: margin,
22+
bottom: margin,
23+
}
24+
}
25+
26+
/// Margins with the same size on opposing sides
27+
#[inline]
28+
pub fn symmetric(x: f32, y: f32) -> Self {
29+
Self {
30+
left: x,
31+
right: x,
32+
top: y,
33+
bottom: y,
34+
}
35+
}
36+
37+
/// Total margins on both sides
38+
pub fn sum(&self) -> Vec2 {
39+
Vec2::new(self.left + self.right, self.top + self.bottom)
40+
}
41+
}
42+
43+
impl From<Vec2> for Margin {
44+
fn from(v: Vec2) -> Self {
45+
Self::symmetric(v.x, v.y)
46+
}
47+
}
48+
649
/// Color and margin of a rectangular background of a [`Ui`].
750
#[derive(Clone, Copy, Debug, Default, PartialEq)]
851
#[must_use = "You should call .show()"]
952
pub struct Frame {
1053
/// On each side
11-
pub margin: Vec2,
54+
pub margin: Margin,
1255
pub rounding: Rounding,
1356
pub shadow: Shadow,
1457
pub fill: Color32,
@@ -23,7 +66,7 @@ impl Frame {
2366
/// For when you want to group a few widgets together within a frame.
2467
pub fn group(style: &Style) -> Self {
2568
Self {
26-
margin: Vec2::splat(6.0), // symmetric looks best in corners when nesting
69+
margin: Margin::same(6.0), // symmetric looks best in corners when nesting
2770
rounding: style.visuals.widgets.noninteractive.rounding,
2871
stroke: style.visuals.widgets.noninteractive.bg_stroke,
2972
..Default::default()
@@ -32,7 +75,7 @@ impl Frame {
3275

3376
pub(crate) fn side_top_panel(style: &Style) -> Self {
3477
Self {
35-
margin: Vec2::new(8.0, 2.0),
78+
margin: Margin::symmetric(8.0, 2.0),
3679
rounding: Rounding::none(),
3780
fill: style.visuals.window_fill(),
3881
stroke: style.visuals.window_stroke(),
@@ -42,7 +85,7 @@ impl Frame {
4285

4386
pub(crate) fn central_panel(style: &Style) -> Self {
4487
Self {
45-
margin: Vec2::new(8.0, 8.0),
88+
margin: Margin::symmetric(8.0, 8.0),
4689
rounding: Rounding::none(),
4790
fill: style.visuals.window_fill(),
4891
stroke: Default::default(),
@@ -52,7 +95,7 @@ impl Frame {
5295

5396
pub fn window(style: &Style) -> Self {
5497
Self {
55-
margin: style.spacing.window_padding,
98+
margin: style.spacing.window_margin,
5699
rounding: style.visuals.window_rounding,
57100
shadow: style.visuals.window_shadow,
58101
fill: style.visuals.window_fill(),
@@ -62,7 +105,7 @@ impl Frame {
62105

63106
pub fn menu(style: &Style) -> Self {
64107
Self {
65-
margin: Vec2::splat(1.0),
108+
margin: Margin::same(1.0),
66109
rounding: style.visuals.widgets.noninteractive.rounding,
67110
shadow: style.visuals.popup_shadow,
68111
fill: style.visuals.window_fill(),
@@ -72,7 +115,7 @@ impl Frame {
72115

73116
pub fn popup(style: &Style) -> Self {
74117
Self {
75-
margin: style.spacing.window_padding,
118+
margin: style.spacing.window_margin,
76119
rounding: style.visuals.widgets.noninteractive.rounding,
77120
shadow: style.visuals.popup_shadow,
78121
fill: style.visuals.window_fill(),
@@ -83,7 +126,7 @@ impl Frame {
83126
/// dark canvas to draw on
84127
pub fn dark_canvas(style: &Style) -> Self {
85128
Self {
86-
margin: Vec2::new(10.0, 10.0),
129+
margin: Margin::symmetric(10.0, 10.0),
87130
rounding: style.visuals.widgets.noninteractive.rounding,
88131
fill: Color32::from_black_alpha(250),
89132
stroke: style.visuals.window_stroke(),
@@ -109,7 +152,7 @@ impl Frame {
109152
}
110153

111154
/// Margin on each side of the frame.
112-
pub fn margin(mut self, margin: impl Into<Vec2>) -> Self {
155+
pub fn margin(mut self, margin: impl Into<Margin>) -> Self {
113156
self.margin = margin.into();
114157
self
115158
}
@@ -137,7 +180,10 @@ impl Frame {
137180
pub fn begin(self, ui: &mut Ui) -> Prepared {
138181
let where_to_put_background = ui.painter().add(Shape::Noop);
139182
let outer_rect_bounds = ui.available_rect_before_wrap();
140-
let mut inner_rect = outer_rect_bounds.shrink2(self.margin);
183+
184+
let mut inner_rect = outer_rect_bounds;
185+
inner_rect.min += Vec2::new(self.margin.left, self.margin.top);
186+
inner_rect.max -= Vec2::new(self.margin.right, self.margin.bottom);
141187

142188
// Make sure we don't shrink to the negative:
143189
inner_rect.max.x = inner_rect.max.x.max(inner_rect.min.x);
@@ -197,7 +243,10 @@ impl Frame {
197243

198244
impl Prepared {
199245
pub fn outer_rect(&self) -> Rect {
200-
self.content_ui.min_rect().expand2(self.frame.margin)
246+
let mut rect = self.content_ui.min_rect();
247+
rect.min -= Vec2::new(self.frame.margin.left, self.frame.margin.top);
248+
rect.max += Vec2::new(self.frame.margin.right, self.frame.margin.bottom);
249+
rect
201250
}
202251

203252
pub fn end(self, ui: &mut Ui) -> Response {

egui/src/containers/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub use {
1616
area::Area,
1717
collapsing_header::{CollapsingHeader, CollapsingResponse},
1818
combo_box::*,
19-
frame::Frame,
19+
frame::{Frame, Margin},
2020
panel::{CentralPanel, SidePanel, TopBottomPanel},
2121
popup::*,
2222
resize::Resize,

egui/src/containers/popup.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ pub fn popup_below_widget<R>(
302302
frame
303303
.show(ui, |ui| {
304304
ui.with_layout(Layout::top_down_justified(Align::LEFT), |ui| {
305-
ui.set_width(widget_response.rect.width() - 2.0 * frame_margin.x);
305+
ui.set_width(widget_response.rect.width() - frame_margin.sum().x);
306306
add_contents(ui)
307307
})
308308
.inner

egui/src/containers/resize.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ impl Resize {
178178
.at_least(self.min_size)
179179
.at_most(self.max_size)
180180
.at_most(
181-
ui.input().screen_rect().size() - 2.0 * ui.spacing().window_padding, // hack for windows
181+
ui.input().screen_rect().size() - ui.spacing().window_margin.sum(), // hack for windows
182182
);
183183

184184
State {

egui/src/containers/window.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ impl<'open> Window<'open> {
301301
} else {
302302
0.0
303303
};
304-
let margins = 2.0 * frame.margin + vec2(0.0, title_bar_height);
304+
let margins = frame.margin.sum() + vec2(0.0, title_bar_height);
305305

306306
interact(
307307
window_interaction,

egui/src/style.rs

+36-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
#![allow(clippy::if_same_then_else)]
44

5-
use crate::{color::*, emath::*, FontFamily, FontId, Response, RichText, WidgetText};
5+
use crate::{color::*, emath::*, FontFamily, FontId, Margin, Response, RichText, WidgetText};
66
use epaint::{mutex::Arc, Rounding, Shadow, Stroke};
77
use std::collections::BTreeMap;
88

@@ -220,8 +220,8 @@ pub struct Spacing {
220220
/// widgets `A` and `B` you need to change `item_spacing` before adding `A`.
221221
pub item_spacing: Vec2,
222222

223-
/// Horizontal and vertical padding within a window frame.
224-
pub window_padding: Vec2,
223+
/// Horizontal and vertical margins within a window frame.
224+
pub window_margin: Margin,
225225

226226
/// Button size is text size plus this on each side
227227
pub button_padding: Vec2,
@@ -528,7 +528,7 @@ impl Default for Spacing {
528528
fn default() -> Self {
529529
Self {
530530
item_spacing: vec2(8.0, 3.0),
531-
window_padding: Vec2::splat(6.0),
531+
window_margin: Margin::same(6.0),
532532
button_padding: vec2(4.0, 1.0),
533533
indent: 18.0, // match checkbox/radio-button with `button_padding.x + icon_width + icon_spacing`
534534
interact_size: vec2(40.0, 18.0),
@@ -803,7 +803,7 @@ impl Spacing {
803803
pub fn ui(&mut self, ui: &mut crate::Ui) {
804804
let Self {
805805
item_spacing,
806-
window_padding,
806+
window_margin,
807807
button_padding,
808808
indent,
809809
interact_size,
@@ -818,7 +818,37 @@ impl Spacing {
818818
} = self;
819819

820820
ui.add(slider_vec2(item_spacing, 0.0..=20.0, "Item spacing"));
821-
ui.add(slider_vec2(window_padding, 0.0..=20.0, "Window padding"));
821+
822+
let margin_range = 0.0..=20.0;
823+
ui.horizontal(|ui| {
824+
ui.add(
825+
DragValue::new(&mut window_margin.left)
826+
.clamp_range(margin_range.clone())
827+
.prefix("left: "),
828+
);
829+
ui.add(
830+
DragValue::new(&mut window_margin.right)
831+
.clamp_range(margin_range.clone())
832+
.prefix("right: "),
833+
);
834+
835+
ui.label("Window margins x");
836+
});
837+
838+
ui.horizontal(|ui| {
839+
ui.add(
840+
DragValue::new(&mut window_margin.top)
841+
.clamp_range(margin_range.clone())
842+
.prefix("top: "),
843+
);
844+
ui.add(
845+
DragValue::new(&mut window_margin.bottom)
846+
.clamp_range(margin_range)
847+
.prefix("bottom: "),
848+
);
849+
ui.label("Window margins y");
850+
});
851+
822852
ui.add(slider_vec2(button_padding, 0.0..=20.0, "Button padding"));
823853
ui.add(slider_vec2(interact_size, 4.0..=60.0, "Interact size"))
824854
.on_hover_text("Minimum size of an interactive widget");

egui/src/widgets/plot/legend.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ impl Widget for &mut LegendWidget {
239239
legend_ui
240240
.scope(|ui| {
241241
let background_frame = Frame {
242-
margin: vec2(8.0, 4.0),
242+
margin: vec2(8.0, 4.0).into(),
243243
rounding: ui.style().visuals.window_rounding,
244244
shadow: epaint::Shadow::default(),
245245
fill: ui.style().visuals.extreme_bg_color,

0 commit comments

Comments
 (0)