Per-side margins with new struct Margin (#1219)
This commit is contained in:
parent
603ec82a5e
commit
2802e03526
8 changed files with 102 additions and 22 deletions
|
@ -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)).
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue