Add Frame::outer_margin, and rename Frame::margin to Frame::inner_margin

This commit is contained in:
Emil Ernerfeldt 2022-03-21 21:44:36 +01:00
parent fda8189cba
commit 339b28b470
7 changed files with 78 additions and 26 deletions

View File

@ -11,9 +11,11 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w
* Added `Frame::canvas` ([#1362](https://github.com/emilk/egui/pull/1362)). * Added `Frame::canvas` ([#1362](https://github.com/emilk/egui/pull/1362)).
* `Context::request_repaint` will wake up UI thread, if integrations has called `Context::set_request_repaint_callback` ([#1366](https://github.com/emilk/egui/pull/1366)). * `Context::request_repaint` will wake up UI thread, if integrations has called `Context::set_request_repaint_callback` ([#1366](https://github.com/emilk/egui/pull/1366)).
* Added `Ui::push_id` ([#1374](https://github.com/emilk/egui/pull/1374)). * Added `Ui::push_id` ([#1374](https://github.com/emilk/egui/pull/1374)).
* Added `Frame::outer_margin`.
### Changed 🔧 ### Changed 🔧
* `ClippedMesh` has been replaced with `ClippedPrimitive` ([#1351](https://github.com/emilk/egui/pull/1351)). * `ClippedMesh` has been replaced with `ClippedPrimitive` ([#1351](https://github.com/emilk/egui/pull/1351)).
* Renamed `Frame::margin` to `Frame::inner_margin`.
### Fixed 🐛 ### Fixed 🐛
* Fixed ComboBoxes always being rendered left-aligned ([#1304](https://github.com/emilk/egui/pull/1304)). * Fixed ComboBoxes always being rendered left-aligned ([#1304](https://github.com/emilk/egui/pull/1304)).

View File

@ -7,8 +7,10 @@ use epaint::*;
#[derive(Clone, Copy, Debug, Default, PartialEq)] #[derive(Clone, Copy, Debug, Default, PartialEq)]
#[must_use = "You should call .show()"] #[must_use = "You should call .show()"]
pub struct Frame { pub struct Frame {
/// On each side /// Margin within the painted frame.
pub margin: Margin, pub inner_margin: Margin,
/// Margin outside the painted frame.
pub outer_margin: Margin,
pub rounding: Rounding, pub rounding: Rounding,
pub shadow: Shadow, pub shadow: Shadow,
pub fill: Color32, pub fill: Color32,
@ -23,7 +25,7 @@ impl Frame {
/// For when you want to group a few widgets together within a frame. /// For when you want to group a few widgets together within a frame.
pub fn group(style: &Style) -> Self { pub fn group(style: &Style) -> Self {
Self { Self {
margin: Margin::same(6.0), // symmetric looks best in corners when nesting inner_margin: Margin::same(6.0), // symmetric looks best in corners when nesting
rounding: style.visuals.widgets.noninteractive.rounding, rounding: style.visuals.widgets.noninteractive.rounding,
stroke: style.visuals.widgets.noninteractive.bg_stroke, stroke: style.visuals.widgets.noninteractive.bg_stroke,
..Default::default() ..Default::default()
@ -32,7 +34,7 @@ impl Frame {
pub(crate) fn side_top_panel(style: &Style) -> Self { pub(crate) fn side_top_panel(style: &Style) -> Self {
Self { Self {
margin: Margin::symmetric(8.0, 2.0), inner_margin: Margin::symmetric(8.0, 2.0),
rounding: Rounding::none(), rounding: Rounding::none(),
fill: style.visuals.window_fill(), fill: style.visuals.window_fill(),
stroke: style.visuals.window_stroke(), stroke: style.visuals.window_stroke(),
@ -42,7 +44,7 @@ impl Frame {
pub(crate) fn central_panel(style: &Style) -> Self { pub(crate) fn central_panel(style: &Style) -> Self {
Self { Self {
margin: Margin::symmetric(8.0, 8.0), inner_margin: Margin::symmetric(8.0, 8.0),
rounding: Rounding::none(), rounding: Rounding::none(),
fill: style.visuals.window_fill(), fill: style.visuals.window_fill(),
stroke: Default::default(), stroke: Default::default(),
@ -52,31 +54,34 @@ impl Frame {
pub fn window(style: &Style) -> Self { pub fn window(style: &Style) -> Self {
Self { Self {
margin: style.spacing.window_margin, inner_margin: style.spacing.window_margin,
rounding: style.visuals.window_rounding, rounding: style.visuals.window_rounding,
shadow: style.visuals.window_shadow, shadow: style.visuals.window_shadow,
fill: style.visuals.window_fill(), fill: style.visuals.window_fill(),
stroke: style.visuals.window_stroke(), stroke: style.visuals.window_stroke(),
..Default::default()
} }
} }
pub fn menu(style: &Style) -> Self { pub fn menu(style: &Style) -> Self {
Self { Self {
margin: Margin::same(1.0), inner_margin: Margin::same(1.0),
rounding: style.visuals.widgets.noninteractive.rounding, rounding: style.visuals.widgets.noninteractive.rounding,
shadow: style.visuals.popup_shadow, shadow: style.visuals.popup_shadow,
fill: style.visuals.window_fill(), fill: style.visuals.window_fill(),
stroke: style.visuals.window_stroke(), stroke: style.visuals.window_stroke(),
..Default::default()
} }
} }
pub fn popup(style: &Style) -> Self { pub fn popup(style: &Style) -> Self {
Self { Self {
margin: style.spacing.window_margin, inner_margin: style.spacing.window_margin,
rounding: style.visuals.widgets.noninteractive.rounding, rounding: style.visuals.widgets.noninteractive.rounding,
shadow: style.visuals.popup_shadow, shadow: style.visuals.popup_shadow,
fill: style.visuals.window_fill(), fill: style.visuals.window_fill(),
stroke: style.visuals.window_stroke(), stroke: style.visuals.window_stroke(),
..Default::default()
} }
} }
@ -86,7 +91,7 @@ impl Frame {
/// and in dark mode this will be very dark. /// and in dark mode this will be very dark.
pub fn canvas(style: &Style) -> Self { pub fn canvas(style: &Style) -> Self {
Self { Self {
margin: Margin::symmetric(10.0, 10.0), inner_margin: Margin::symmetric(10.0, 10.0),
rounding: style.visuals.widgets.noninteractive.rounding, rounding: style.visuals.widgets.noninteractive.rounding,
fill: style.visuals.extreme_bg_color, fill: style.visuals.extreme_bg_color,
stroke: style.visuals.window_stroke(), stroke: style.visuals.window_stroke(),
@ -119,12 +124,23 @@ impl Frame {
self self
} }
/// Margin on each side of the frame. /// Margin within the painted frame.
pub fn margin(mut self, margin: impl Into<Margin>) -> Self { pub fn inner_margin(mut self, inner_margin: impl Into<Margin>) -> Self {
self.margin = margin.into(); self.inner_margin = inner_margin.into();
self self
} }
/// Margin outside the painted frame.
pub fn outer_margin(mut self, outer_margin: impl Into<Margin>) -> Self {
self.outer_margin = outer_margin.into();
self
}
#[deprecated = "Renamed inner_margin in egui 0.18"]
pub fn margin(self, margin: impl Into<Margin>) -> Self {
self.inner_margin(margin)
}
pub fn shadow(mut self, shadow: Shadow) -> Self { pub fn shadow(mut self, shadow: Shadow) -> Self {
self.shadow = shadow; self.shadow = shadow;
self self
@ -150,8 +166,8 @@ impl Frame {
let outer_rect_bounds = ui.available_rect_before_wrap(); let outer_rect_bounds = ui.available_rect_before_wrap();
let mut inner_rect = outer_rect_bounds; let mut inner_rect = outer_rect_bounds;
inner_rect.min += Vec2::new(self.margin.left, self.margin.top); inner_rect.min += self.outer_margin.left_top() + self.inner_margin.left_top();
inner_rect.max -= Vec2::new(self.margin.right, self.margin.bottom); inner_rect.max -= self.outer_margin.right_bottom() + self.inner_margin.right_bottom();
// Make sure we don't shrink to the negative: // Make sure we don't shrink to the negative:
inner_rect.max.x = inner_rect.max.x.max(inner_rect.min.x); inner_rect.max.x = inner_rect.max.x.max(inner_rect.min.x);
@ -185,7 +201,8 @@ impl Frame {
pub fn paint(&self, outer_rect: Rect) -> Shape { pub fn paint(&self, outer_rect: Rect) -> Shape {
let Self { let Self {
margin: _, inner_margin: _,
outer_margin: _,
rounding, rounding,
shadow, shadow,
fill, fill,
@ -210,15 +227,15 @@ impl Frame {
} }
impl Prepared { impl Prepared {
pub fn outer_rect(&self) -> Rect { fn paint_rect(&self) -> Rect {
let mut rect = self.content_ui.min_rect(); let mut rect = self.content_ui.min_rect();
rect.min -= Vec2::new(self.frame.margin.left, self.frame.margin.top); rect.min -= self.frame.inner_margin.left_top();
rect.max += Vec2::new(self.frame.margin.right, self.frame.margin.bottom); rect.max += self.frame.inner_margin.right_bottom();
rect rect
} }
pub fn end(self, ui: &mut Ui) -> Response { pub fn end(self, ui: &mut Ui) -> Response {
let outer_rect = self.outer_rect(); let paint_rect = self.paint_rect();
let Prepared { let Prepared {
frame, frame,
@ -226,11 +243,11 @@ impl Prepared {
.. ..
} = self; } = self;
if ui.is_rect_visible(outer_rect) { if ui.is_rect_visible(paint_rect) {
let shape = frame.paint(outer_rect); let shape = frame.paint(paint_rect);
ui.painter().set(where_to_put_background, shape); ui.painter().set(where_to_put_background, shape);
} }
ui.allocate_rect(outer_rect, Sense::hover()) ui.allocate_rect(paint_rect, Sense::hover())
} }
} }

View File

@ -298,7 +298,7 @@ pub fn popup_below_widget<R>(
// Note: we use a separate clip-rect for this area, so the popup can be outside the parent. // Note: we use a separate clip-rect for this area, so the popup can be outside the parent.
// See https://github.com/emilk/egui/issues/825 // See https://github.com/emilk/egui/issues/825
let frame = Frame::popup(ui.style()); let frame = Frame::popup(ui.style());
let frame_margin = frame.margin; let frame_margin = frame.inner_margin + frame.outer_margin;
frame frame
.show(ui, |ui| { .show(ui, |ui| {
ui.with_layout(Layout::top_down_justified(Align::LEFT), |ui| { ui.with_layout(Layout::top_down_justified(Align::LEFT), |ui| {

View File

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

View File

@ -277,6 +277,8 @@ impl Spacing {
} }
} }
// ----------------------------------------------------------------------------
#[derive(Clone, Copy, Debug, Default, PartialEq)] #[derive(Clone, Copy, Debug, Default, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Margin { pub struct Margin {
@ -312,6 +314,20 @@ impl Margin {
pub fn sum(&self) -> Vec2 { pub fn sum(&self) -> Vec2 {
Vec2::new(self.left + self.right, self.top + self.bottom) Vec2::new(self.left + self.right, self.top + self.bottom)
} }
pub fn left_top(&self) -> Vec2 {
Vec2::new(self.left, self.top)
}
pub fn right_bottom(&self) -> Vec2 {
Vec2::new(self.right, self.bottom)
}
}
impl From<f32> for Margin {
fn from(v: f32) -> Self {
Self::same(v)
}
} }
impl From<Vec2> for Margin { impl From<Vec2> for Margin {
@ -320,6 +336,20 @@ impl From<Vec2> for Margin {
} }
} }
impl std::ops::Add for Margin {
type Output = Self;
fn add(self, other: Self) -> Self {
Self {
left: self.left + other.left,
right: self.right + other.right,
top: self.top + other.top,
bottom: self.bottom + other.bottom,
}
}
}
// ----------------------------------------------------------------------------
/// How and when interaction happens. /// How and when interaction happens.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]

View File

@ -239,11 +239,12 @@ impl Widget for &mut LegendWidget {
legend_ui legend_ui
.scope(|ui| { .scope(|ui| {
let background_frame = Frame { let background_frame = Frame {
margin: vec2(8.0, 4.0).into(), inner_margin: vec2(8.0, 4.0).into(),
rounding: ui.style().visuals.window_rounding, rounding: ui.style().visuals.window_rounding,
shadow: epaint::Shadow::default(), shadow: epaint::Shadow::default(),
fill: ui.style().visuals.extreme_bg_color, fill: ui.style().visuals.extreme_bg_color,
stroke: ui.style().visuals.window_stroke(), stroke: ui.style().visuals.window_stroke(),
..Default::default()
} }
.multiply_with_opacity(config.background_alpha); .multiply_with_opacity(config.background_alpha);
background_frame background_frame

View File

@ -277,7 +277,7 @@ impl CodeTheme {
ui.data().insert_persisted(selected_id, selected_tt); ui.data().insert_persisted(selected_id, selected_tt);
egui::Frame::group(ui.style()) egui::Frame::group(ui.style())
.margin(egui::Vec2::splat(2.0)) .inner_margin(egui::Vec2::splat(2.0))
.show(ui, |ui| { .show(ui, |ui| {
// ui.group(|ui| { // ui.group(|ui| {
ui.style_mut().override_text_style = Some(egui::TextStyle::Small); ui.style_mut().override_text_style = Some(egui::TextStyle::Small);