Store `Margin` using `i8` to reduce its size (#5567)
Adds `Marginf` to fill the previous niche. This is all in a pursuit to shrink the sizes of often-used structs, to improve performance (less cache misses, less memcpy:s, etc). * On the path towards https://github.com/emilk/egui/issues/4019
This commit is contained in:
parent
aeea70d9e7
commit
d58d13781d
|
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
epaint, layers::ShapeIdx, InnerResponse, Response, Sense, Style, Ui, UiBuilder, UiKind,
|
epaint, layers::ShapeIdx, InnerResponse, Response, Sense, Style, Ui, UiBuilder, UiKind,
|
||||||
UiStackInfo,
|
UiStackInfo,
|
||||||
};
|
};
|
||||||
use epaint::{Color32, Margin, Rect, Rounding, Shadow, Shape, Stroke};
|
use epaint::{Color32, Margin, Marginf, Rect, Rounding, Shadow, Shape, Stroke};
|
||||||
|
|
||||||
/// Add a background, frame and/or margin to a rectangular background of a [`Ui`].
|
/// Add a background, frame and/or margin to a rectangular background of a [`Ui`].
|
||||||
///
|
///
|
||||||
|
|
@ -73,6 +73,18 @@ pub struct Frame {
|
||||||
pub stroke: Stroke,
|
pub stroke: Stroke,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn frame_size() {
|
||||||
|
assert_eq!(
|
||||||
|
std::mem::size_of::<Frame>(), 44,
|
||||||
|
"Frame changed size! If it shrank - good! Update this test. If it grew - bad! Try to find a way to avoid it."
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
std::mem::size_of::<Frame>() <= 64,
|
||||||
|
"Frame is getting way too big!"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
impl Frame {
|
impl Frame {
|
||||||
pub fn none() -> Self {
|
pub fn none() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
|
|
@ -81,7 +93,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 {
|
||||||
inner_margin: Margin::same(6.0), // same and symmetric looks best in corners when nesting groups
|
inner_margin: Margin::same(6), // same and symmetric looks best in corners when nesting groups
|
||||||
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()
|
||||||
|
|
@ -90,7 +102,7 @@ impl Frame {
|
||||||
|
|
||||||
pub fn side_top_panel(style: &Style) -> Self {
|
pub fn side_top_panel(style: &Style) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner_margin: Margin::symmetric(8.0, 2.0),
|
inner_margin: Margin::symmetric(8, 2),
|
||||||
fill: style.visuals.panel_fill,
|
fill: style.visuals.panel_fill,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
|
|
@ -98,7 +110,7 @@ impl Frame {
|
||||||
|
|
||||||
pub fn central_panel(style: &Style) -> Self {
|
pub fn central_panel(style: &Style) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner_margin: Margin::same(8.0),
|
inner_margin: Margin::same(8),
|
||||||
fill: style.visuals.panel_fill,
|
fill: style.visuals.panel_fill,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
|
|
@ -143,7 +155,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 {
|
||||||
inner_margin: Margin::same(2.0),
|
inner_margin: Margin::same(2),
|
||||||
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(),
|
||||||
|
|
@ -213,10 +225,10 @@ impl Frame {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Frame {
|
impl Frame {
|
||||||
/// inner margin plus outer margin.
|
/// Inner margin plus outer margin.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn total_margin(&self) -> Margin {
|
pub fn total_margin(&self) -> Marginf {
|
||||||
self.inner_margin + self.outer_margin
|
Marginf::from(self.inner_margin) + Marginf::from(self.outer_margin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -486,7 +486,7 @@ impl<'open> Window<'open> {
|
||||||
// Calculate roughly how much larger the window size is compared to the inner rect
|
// Calculate roughly how much larger the window size is compared to the inner rect
|
||||||
let (title_bar_height, title_content_spacing) = if with_title_bar {
|
let (title_bar_height, title_content_spacing) = if with_title_bar {
|
||||||
let style = ctx.style();
|
let style = ctx.style();
|
||||||
let spacing = window_margin.top + window_margin.bottom;
|
let spacing = window_margin.sum().y;
|
||||||
let height = ctx.fonts(|f| title.font_height(f, &style)) + spacing;
|
let height = ctx.fonts(|f| title.font_height(f, &style)) + spacing;
|
||||||
let half_height = (height / 2.0).round() as _;
|
let half_height = (height / 2.0).round() as _;
|
||||||
window_frame.rounding.ne = window_frame.rounding.ne.clamp(0, half_height);
|
window_frame.rounding.ne = window_frame.rounding.ne.clamp(0, half_height);
|
||||||
|
|
|
||||||
|
|
@ -1238,8 +1238,8 @@ impl Default for Spacing {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
item_spacing: vec2(8.0, 3.0),
|
item_spacing: vec2(8.0, 3.0),
|
||||||
window_margin: Margin::same(6.0),
|
window_margin: Margin::same(6),
|
||||||
menu_margin: Margin::same(6.0),
|
menu_margin: Margin::same(6),
|
||||||
button_padding: vec2(4.0, 1.0),
|
button_padding: vec2(4.0, 1.0),
|
||||||
indent: 18.0, // match checkbox/radio-button with `button_padding.x + icon_width + icon_spacing`
|
indent: 18.0, // match checkbox/radio-button with `button_padding.x + icon_width + icon_spacing`
|
||||||
interact_size: vec2(40.0, 18.0),
|
interact_size: vec2(40.0, 18.0),
|
||||||
|
|
@ -2371,9 +2371,17 @@ impl Widget for &mut Margin {
|
||||||
|
|
||||||
// Apply the checkbox:
|
// Apply the checkbox:
|
||||||
if same {
|
if same {
|
||||||
*self = Margin::same((self.left + self.right + self.top + self.bottom) / 4.0);
|
*self =
|
||||||
} else if self.is_same() {
|
Margin::from((self.leftf() + self.rightf() + self.topf() + self.bottomf()) / 4.0);
|
||||||
self.right *= 1.00001; // prevent collapsing into sameness
|
} else {
|
||||||
|
// Make sure it is not same:
|
||||||
|
if self.is_same() {
|
||||||
|
if self.right == i8::MAX {
|
||||||
|
self.right = i8::MAX - 1;
|
||||||
|
} else {
|
||||||
|
self.right += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response
|
response
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ impl<'t> TextEdit<'t> {
|
||||||
layouter: None,
|
layouter: None,
|
||||||
password: false,
|
password: false,
|
||||||
frame: true,
|
frame: true,
|
||||||
margin: Margin::symmetric(4.0, 2.0),
|
margin: Margin::symmetric(4, 2),
|
||||||
multiline: true,
|
multiline: true,
|
||||||
interactive: true,
|
interactive: true,
|
||||||
desired_width: None,
|
desired_width: None,
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ impl crate::View for PanZoom {
|
||||||
ui.set_clip_rect(transform.inverse() * rect);
|
ui.set_clip_rect(transform.inverse() * rect);
|
||||||
egui::Frame::default()
|
egui::Frame::default()
|
||||||
.rounding(egui::Rounding::same(4))
|
.rounding(egui::Rounding::same(4))
|
||||||
.inner_margin(egui::Margin::same(8.0))
|
.inner_margin(egui::Margin::same(8))
|
||||||
.stroke(ui.ctx().style().visuals.window_stroke)
|
.stroke(ui.ctx().style().visuals.window_stroke)
|
||||||
.fill(ui.style().visuals.panel_fill)
|
.fill(ui.style().visuals.panel_fill)
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
|
|
|
||||||
|
|
@ -134,14 +134,14 @@ impl<'a> Widget for DatePickerButton<'a> {
|
||||||
let mut pos = button_response.rect.left_bottom();
|
let mut pos = button_response.rect.left_bottom();
|
||||||
let width_with_padding = width
|
let width_with_padding = width
|
||||||
+ ui.style().spacing.item_spacing.x
|
+ ui.style().spacing.item_spacing.x
|
||||||
+ ui.style().spacing.window_margin.left
|
+ ui.style().spacing.window_margin.leftf()
|
||||||
+ ui.style().spacing.window_margin.right;
|
+ ui.style().spacing.window_margin.rightf();
|
||||||
if pos.x + width_with_padding > ui.clip_rect().right() {
|
if pos.x + width_with_padding > ui.clip_rect().right() {
|
||||||
pos.x = button_response.rect.right() - width_with_padding;
|
pos.x = button_response.rect.right() - width_with_padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to make sure the calendar never is displayed out of window
|
// Check to make sure the calendar never is displayed out of window
|
||||||
pos.x = pos.x.max(ui.style().spacing.window_margin.left);
|
pos.x = pos.x.max(ui.style().spacing.window_margin.leftf());
|
||||||
|
|
||||||
//TODO(elwerene): Better positioning
|
//TODO(elwerene): Better positioning
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ mod brush;
|
||||||
pub mod color;
|
pub mod color;
|
||||||
pub mod image;
|
pub mod image;
|
||||||
mod margin;
|
mod margin;
|
||||||
|
mod marginf;
|
||||||
mod mesh;
|
mod mesh;
|
||||||
pub mod mutex;
|
pub mod mutex;
|
||||||
mod rounding;
|
mod rounding;
|
||||||
|
|
@ -49,6 +50,7 @@ pub use self::{
|
||||||
color::ColorMode,
|
color::ColorMode,
|
||||||
image::{ColorImage, FontImage, ImageData, ImageDelta},
|
image::{ColorImage, FontImage, ImageData, ImageDelta},
|
||||||
margin::Margin,
|
margin::Margin,
|
||||||
|
marginf::Marginf,
|
||||||
mesh::{Mesh, Mesh16, Vertex},
|
mesh::{Mesh, Mesh16, Vertex},
|
||||||
rounding::Rounding,
|
rounding::Rounding,
|
||||||
roundingf::Roundingf,
|
roundingf::Roundingf,
|
||||||
|
|
|
||||||
|
|
@ -4,27 +4,33 @@ use emath::{vec2, Rect, Vec2};
|
||||||
/// often used to express padding or spacing.
|
/// often used to express padding or spacing.
|
||||||
///
|
///
|
||||||
/// Can be added and subtracted to/from [`Rect`]s.
|
/// Can be added and subtracted to/from [`Rect`]s.
|
||||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
///
|
||||||
|
/// Negative margins are possible, but may produce weird behavior.
|
||||||
|
/// Use with care.
|
||||||
|
///
|
||||||
|
/// All values are stored as [`i8`] to keep the size of [`Margin`] small.
|
||||||
|
/// If you want floats, use [`crate::Marginf`] instead.
|
||||||
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct Margin {
|
pub struct Margin {
|
||||||
pub left: f32,
|
pub left: i8,
|
||||||
pub right: f32,
|
pub right: i8,
|
||||||
pub top: f32,
|
pub top: i8,
|
||||||
pub bottom: f32,
|
pub bottom: i8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Margin {
|
impl Margin {
|
||||||
pub const ZERO: Self = Self {
|
pub const ZERO: Self = Self {
|
||||||
left: 0.0,
|
left: 0,
|
||||||
right: 0.0,
|
right: 0,
|
||||||
top: 0.0,
|
top: 0,
|
||||||
bottom: 0.0,
|
bottom: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The same margin on every side.
|
/// The same margin on every side.
|
||||||
#[doc(alias = "symmetric")]
|
#[doc(alias = "symmetric")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn same(margin: f32) -> Self {
|
pub const fn same(margin: i8) -> Self {
|
||||||
Self {
|
Self {
|
||||||
left: margin,
|
left: margin,
|
||||||
right: margin,
|
right: margin,
|
||||||
|
|
@ -35,7 +41,7 @@ impl Margin {
|
||||||
|
|
||||||
/// Margins with the same size on opposing sides
|
/// Margins with the same size on opposing sides
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn symmetric(x: f32, y: f32) -> Self {
|
pub const fn symmetric(x: i8, y: i8) -> Self {
|
||||||
Self {
|
Self {
|
||||||
left: x,
|
left: x,
|
||||||
right: x,
|
right: x,
|
||||||
|
|
@ -44,53 +50,84 @@ impl Margin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Left margin, as `f32`
|
||||||
|
#[inline]
|
||||||
|
pub const fn leftf(self) -> f32 {
|
||||||
|
self.left as _
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Right margin, as `f32`
|
||||||
|
#[inline]
|
||||||
|
pub const fn rightf(self) -> f32 {
|
||||||
|
self.right as _
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Top margin, as `f32`
|
||||||
|
#[inline]
|
||||||
|
pub const fn topf(self) -> f32 {
|
||||||
|
self.top as _
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bottom margin, as `f32`
|
||||||
|
#[inline]
|
||||||
|
pub const fn bottomf(self) -> f32 {
|
||||||
|
self.bottom as _
|
||||||
|
}
|
||||||
|
|
||||||
/// Total margins on both sides
|
/// Total margins on both sides
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn sum(&self) -> Vec2 {
|
pub fn sum(self) -> Vec2 {
|
||||||
vec2(self.left + self.right, self.top + self.bottom)
|
vec2(self.leftf() + self.rightf(), self.topf() + self.bottomf())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn left_top(&self) -> Vec2 {
|
pub const fn left_top(self) -> Vec2 {
|
||||||
vec2(self.left, self.top)
|
vec2(self.leftf(), self.topf())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn right_bottom(&self) -> Vec2 {
|
pub const fn right_bottom(self) -> Vec2 {
|
||||||
vec2(self.right, self.bottom)
|
vec2(self.rightf(), self.bottomf())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Are the margin on every side the same?
|
/// Are the margin on every side the same?
|
||||||
#[doc(alias = "symmetric")]
|
#[doc(alias = "symmetric")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_same(&self) -> bool {
|
pub const fn is_same(self) -> bool {
|
||||||
self.left == self.right && self.left == self.top && self.left == self.bottom
|
self.left == self.right && self.left == self.top && self.left == self.bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated = "Use `rect + margin` instead"]
|
#[deprecated = "Use `rect + margin` instead"]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn expand_rect(&self, rect: Rect) -> Rect {
|
pub fn expand_rect(self, rect: Rect) -> Rect {
|
||||||
Rect::from_min_max(rect.min - self.left_top(), rect.max + self.right_bottom())
|
Rect::from_min_max(rect.min - self.left_top(), rect.max + self.right_bottom())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated = "Use `rect - margin` instead"]
|
#[deprecated = "Use `rect - margin` instead"]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn shrink_rect(&self, rect: Rect) -> Rect {
|
pub fn shrink_rect(self, rect: Rect) -> Rect {
|
||||||
Rect::from_min_max(rect.min + self.left_top(), rect.max - self.right_bottom())
|
Rect::from_min_max(rect.min + self.left_top(), rect.max - self.right_bottom())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<i8> for Margin {
|
||||||
|
#[inline]
|
||||||
|
fn from(v: i8) -> Self {
|
||||||
|
Self::same(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<f32> for Margin {
|
impl From<f32> for Margin {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(v: f32) -> Self {
|
fn from(v: f32) -> Self {
|
||||||
Self::same(v)
|
Self::same(v.round() as _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec2> for Margin {
|
impl From<Vec2> for Margin {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(v: Vec2) -> Self {
|
fn from(v: Vec2) -> Self {
|
||||||
Self::symmetric(v.x, v.y)
|
Self::symmetric(v.x.round() as _, v.y.round() as _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,37 +138,34 @@ impl std::ops::Add for Margin {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add(self, other: Self) -> Self {
|
fn add(self, other: Self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
left: self.left + other.left,
|
left: self.left.saturating_add(other.left),
|
||||||
right: self.right + other.right,
|
right: self.right.saturating_add(other.right),
|
||||||
top: self.top + other.top,
|
top: self.top.saturating_add(other.top),
|
||||||
bottom: self.bottom + other.bottom,
|
bottom: self.bottom.saturating_add(other.bottom),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Margin + f32`
|
/// `Margin + i8`
|
||||||
impl std::ops::Add<f32> for Margin {
|
impl std::ops::Add<i8> for Margin {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add(self, v: f32) -> Self {
|
fn add(self, v: i8) -> Self {
|
||||||
Self {
|
Self {
|
||||||
left: self.left + v,
|
left: self.left.saturating_add(v),
|
||||||
right: self.right + v,
|
right: self.right.saturating_add(v),
|
||||||
top: self.top + v,
|
top: self.top.saturating_add(v),
|
||||||
bottom: self.bottom + v,
|
bottom: self.bottom.saturating_add(v),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Margind += f32`
|
/// `Margin += i8`
|
||||||
impl std::ops::AddAssign<f32> for Margin {
|
impl std::ops::AddAssign<i8> for Margin {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add_assign(&mut self, v: f32) {
|
fn add_assign(&mut self, v: i8) {
|
||||||
self.left += v;
|
*self = *self + v;
|
||||||
self.right += v;
|
|
||||||
self.top += v;
|
|
||||||
self.bottom += v;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -142,10 +176,10 @@ impl std::ops::Mul<f32> for Margin {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul(self, v: f32) -> Self {
|
fn mul(self, v: f32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
left: self.left * v,
|
left: (self.leftf() * v).round() as _,
|
||||||
right: self.right * v,
|
right: (self.rightf() * v).round() as _,
|
||||||
top: self.top * v,
|
top: (self.topf() * v).round() as _,
|
||||||
bottom: self.bottom * v,
|
bottom: (self.bottomf() * v).round() as _,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -154,10 +188,7 @@ impl std::ops::Mul<f32> for Margin {
|
||||||
impl std::ops::MulAssign<f32> for Margin {
|
impl std::ops::MulAssign<f32> for Margin {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul_assign(&mut self, v: f32) {
|
fn mul_assign(&mut self, v: f32) {
|
||||||
self.left *= v;
|
*self = *self * v;
|
||||||
self.right *= v;
|
|
||||||
self.top *= v;
|
|
||||||
self.bottom *= v;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,12 +198,8 @@ impl std::ops::Div<f32> for Margin {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn div(self, v: f32) -> Self {
|
fn div(self, v: f32) -> Self {
|
||||||
Self {
|
#![allow(clippy::suspicious_arithmetic_impl)]
|
||||||
left: self.left / v,
|
self * v.recip()
|
||||||
right: self.right / v,
|
|
||||||
top: self.top / v,
|
|
||||||
bottom: self.bottom / v,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,10 +207,7 @@ impl std::ops::Div<f32> for Margin {
|
||||||
impl std::ops::DivAssign<f32> for Margin {
|
impl std::ops::DivAssign<f32> for Margin {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn div_assign(&mut self, v: f32) {
|
fn div_assign(&mut self, v: f32) {
|
||||||
self.left /= v;
|
*self = *self / v;
|
||||||
self.right /= v;
|
|
||||||
self.top /= v;
|
|
||||||
self.bottom /= v;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,37 +218,34 @@ impl std::ops::Sub for Margin {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub(self, other: Self) -> Self {
|
fn sub(self, other: Self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
left: self.left - other.left,
|
left: self.left.saturating_sub(other.left),
|
||||||
right: self.right - other.right,
|
right: self.right.saturating_sub(other.right),
|
||||||
top: self.top - other.top,
|
top: self.top.saturating_sub(other.top),
|
||||||
bottom: self.bottom - other.bottom,
|
bottom: self.bottom.saturating_sub(other.bottom),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Margin - f32`
|
/// `Margin - i8`
|
||||||
impl std::ops::Sub<f32> for Margin {
|
impl std::ops::Sub<i8> for Margin {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub(self, v: f32) -> Self {
|
fn sub(self, v: i8) -> Self {
|
||||||
Self {
|
Self {
|
||||||
left: self.left - v,
|
left: self.left.saturating_sub(v),
|
||||||
right: self.right - v,
|
right: self.right.saturating_sub(v),
|
||||||
top: self.top - v,
|
top: self.top.saturating_sub(v),
|
||||||
bottom: self.bottom - v,
|
bottom: self.bottom.saturating_sub(v),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Margin -= f32`
|
/// `Margin -= i8`
|
||||||
impl std::ops::SubAssign<f32> for Margin {
|
impl std::ops::SubAssign<i8> for Margin {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub_assign(&mut self, v: f32) {
|
fn sub_assign(&mut self, v: i8) {
|
||||||
self.left -= v;
|
*self = *self - v;
|
||||||
self.right -= v;
|
|
||||||
self.top -= v;
|
|
||||||
self.bottom -= v;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,299 @@
|
||||||
|
use emath::{vec2, Rect, Vec2};
|
||||||
|
|
||||||
|
use crate::Margin;
|
||||||
|
|
||||||
|
/// A value for all four sides of a rectangle,
|
||||||
|
/// often used to express padding or spacing.
|
||||||
|
///
|
||||||
|
/// Can be added and subtracted to/from [`Rect`]s.
|
||||||
|
///
|
||||||
|
/// For storage, use [`crate::Margin`] instead.
|
||||||
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
|
pub struct Marginf {
|
||||||
|
pub left: f32,
|
||||||
|
pub right: f32,
|
||||||
|
pub top: f32,
|
||||||
|
pub bottom: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Margin> for Marginf {
|
||||||
|
#[inline]
|
||||||
|
fn from(margin: Margin) -> Self {
|
||||||
|
Self {
|
||||||
|
left: margin.left as _,
|
||||||
|
right: margin.right as _,
|
||||||
|
top: margin.top as _,
|
||||||
|
bottom: margin.bottom as _,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Marginf> for Margin {
|
||||||
|
#[inline]
|
||||||
|
fn from(marginf: Marginf) -> Self {
|
||||||
|
Self {
|
||||||
|
left: marginf.left as _,
|
||||||
|
right: marginf.right as _,
|
||||||
|
top: marginf.top as _,
|
||||||
|
bottom: marginf.bottom as _,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Marginf {
|
||||||
|
pub const ZERO: Self = Self {
|
||||||
|
left: 0.0,
|
||||||
|
right: 0.0,
|
||||||
|
top: 0.0,
|
||||||
|
bottom: 0.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The same margin on every side.
|
||||||
|
#[doc(alias = "symmetric")]
|
||||||
|
#[inline]
|
||||||
|
pub const fn same(margin: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
left: margin,
|
||||||
|
right: margin,
|
||||||
|
top: margin,
|
||||||
|
bottom: margin,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Margins with the same size on opposing sides
|
||||||
|
#[inline]
|
||||||
|
pub const fn symmetric(x: f32, y: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
left: x,
|
||||||
|
right: x,
|
||||||
|
top: y,
|
||||||
|
bottom: y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Total margins on both sides
|
||||||
|
#[inline]
|
||||||
|
pub fn sum(&self) -> Vec2 {
|
||||||
|
vec2(self.left + self.right, self.top + self.bottom)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub const fn left_top(&self) -> Vec2 {
|
||||||
|
vec2(self.left, self.top)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub const fn right_bottom(&self) -> Vec2 {
|
||||||
|
vec2(self.right, self.bottom)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Are the margin on every side the same?
|
||||||
|
#[doc(alias = "symmetric")]
|
||||||
|
#[inline]
|
||||||
|
pub fn is_same(&self) -> bool {
|
||||||
|
self.left == self.right && self.left == self.top && self.left == self.bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated = "Use `rect + margin` instead"]
|
||||||
|
#[inline]
|
||||||
|
pub fn expand_rect(&self, rect: Rect) -> Rect {
|
||||||
|
Rect::from_min_max(rect.min - self.left_top(), rect.max + self.right_bottom())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated = "Use `rect - margin` instead"]
|
||||||
|
#[inline]
|
||||||
|
pub fn shrink_rect(&self, rect: Rect) -> Rect {
|
||||||
|
Rect::from_min_max(rect.min + self.left_top(), rect.max - self.right_bottom())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<f32> for Marginf {
|
||||||
|
#[inline]
|
||||||
|
fn from(v: f32) -> Self {
|
||||||
|
Self::same(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec2> for Marginf {
|
||||||
|
#[inline]
|
||||||
|
fn from(v: Vec2) -> Self {
|
||||||
|
Self::symmetric(v.x, v.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Marginf + Marginf`
|
||||||
|
impl std::ops::Add for Marginf {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Marginf + f32`
|
||||||
|
impl std::ops::Add<f32> for Marginf {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn add(self, v: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
left: self.left + v,
|
||||||
|
right: self.right + v,
|
||||||
|
top: self.top + v,
|
||||||
|
bottom: self.bottom + v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Margind += f32`
|
||||||
|
impl std::ops::AddAssign<f32> for Marginf {
|
||||||
|
#[inline]
|
||||||
|
fn add_assign(&mut self, v: f32) {
|
||||||
|
self.left += v;
|
||||||
|
self.right += v;
|
||||||
|
self.top += v;
|
||||||
|
self.bottom += v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Marginf * f32`
|
||||||
|
impl std::ops::Mul<f32> for Marginf {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, v: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
left: self.left * v,
|
||||||
|
right: self.right * v,
|
||||||
|
top: self.top * v,
|
||||||
|
bottom: self.bottom * v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Marginf *= f32`
|
||||||
|
impl std::ops::MulAssign<f32> for Marginf {
|
||||||
|
#[inline]
|
||||||
|
fn mul_assign(&mut self, v: f32) {
|
||||||
|
self.left *= v;
|
||||||
|
self.right *= v;
|
||||||
|
self.top *= v;
|
||||||
|
self.bottom *= v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Marginf / f32`
|
||||||
|
impl std::ops::Div<f32> for Marginf {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn div(self, v: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
left: self.left / v,
|
||||||
|
right: self.right / v,
|
||||||
|
top: self.top / v,
|
||||||
|
bottom: self.bottom / v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Marginf /= f32`
|
||||||
|
impl std::ops::DivAssign<f32> for Marginf {
|
||||||
|
#[inline]
|
||||||
|
fn div_assign(&mut self, v: f32) {
|
||||||
|
self.left /= v;
|
||||||
|
self.right /= v;
|
||||||
|
self.top /= v;
|
||||||
|
self.bottom /= v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Marginf - Marginf`
|
||||||
|
impl std::ops::Sub for Marginf {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sub(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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Marginf - f32`
|
||||||
|
impl std::ops::Sub<f32> for Marginf {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sub(self, v: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
left: self.left - v,
|
||||||
|
right: self.right - v,
|
||||||
|
top: self.top - v,
|
||||||
|
bottom: self.bottom - v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Marginf -= f32`
|
||||||
|
impl std::ops::SubAssign<f32> for Marginf {
|
||||||
|
#[inline]
|
||||||
|
fn sub_assign(&mut self, v: f32) {
|
||||||
|
self.left -= v;
|
||||||
|
self.right -= v;
|
||||||
|
self.top -= v;
|
||||||
|
self.bottom -= v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Rect + Marginf`
|
||||||
|
impl std::ops::Add<Marginf> for Rect {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn add(self, margin: Marginf) -> Self {
|
||||||
|
Self::from_min_max(
|
||||||
|
self.min - margin.left_top(),
|
||||||
|
self.max + margin.right_bottom(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Rect += Marginf`
|
||||||
|
impl std::ops::AddAssign<Marginf> for Rect {
|
||||||
|
#[inline]
|
||||||
|
fn add_assign(&mut self, margin: Marginf) {
|
||||||
|
*self = *self + margin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Rect - Marginf`
|
||||||
|
impl std::ops::Sub<Marginf> for Rect {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sub(self, margin: Marginf) -> Self {
|
||||||
|
Self::from_min_max(
|
||||||
|
self.min + margin.left_top(),
|
||||||
|
self.max - margin.right_bottom(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Rect -= Marginf`
|
||||||
|
impl std::ops::SubAssign<Marginf> for Rect {
|
||||||
|
#[inline]
|
||||||
|
fn sub_assign(&mut self, margin: Marginf) {
|
||||||
|
*self = *self - margin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{Color32, Margin, Rect, RectShape, Rounding, Vec2};
|
use crate::{Color32, Marginf, Rect, RectShape, Rounding, Vec2};
|
||||||
|
|
||||||
/// The color and fuzziness of a fuzzy shape.
|
/// The color and fuzziness of a fuzzy shape.
|
||||||
///
|
///
|
||||||
|
|
@ -53,14 +53,14 @@ impl Shadow {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// How much larger than the parent rect are we in each direction?
|
/// How much larger than the parent rect are we in each direction?
|
||||||
pub fn margin(&self) -> Margin {
|
pub fn margin(&self) -> Marginf {
|
||||||
let Self {
|
let Self {
|
||||||
offset,
|
offset,
|
||||||
blur,
|
blur,
|
||||||
spread,
|
spread,
|
||||||
color: _,
|
color: _,
|
||||||
} = *self;
|
} = *self;
|
||||||
Margin {
|
Marginf {
|
||||||
left: spread + 0.5 * blur - offset.x,
|
left: spread + 0.5 * blur - offset.x,
|
||||||
right: spread + 0.5 * blur + offset.x,
|
right: spread + 0.5 * blur + offset.x,
|
||||||
top: spread + 0.5 * blur - offset.y,
|
top: spread + 0.5 * blur - offset.y,
|
||||||
|
|
|
||||||
|
|
@ -92,10 +92,10 @@ impl Keypad {
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
let window_margin = ui.spacing().window_margin;
|
let window_margin = ui.spacing().window_margin;
|
||||||
let size_1x1 = vec2(32.0, 26.0);
|
let size_1x1 = vec2(32.0, 26.0);
|
||||||
let _size_1x2 = vec2(32.0, 52.0 + window_margin.top);
|
let _size_1x2 = vec2(32.0, 52.0 + window_margin.topf());
|
||||||
let _size_2x1 = vec2(64.0 + window_margin.left, 26.0);
|
let _size_2x1 = vec2(64.0 + window_margin.leftf(), 26.0);
|
||||||
|
|
||||||
ui.spacing_mut().item_spacing = Vec2::splat(window_margin.left);
|
ui.spacing_mut().item_spacing = Vec2::splat(window_margin.leftf());
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
if ui.add_sized(size_1x1, Button::new("1")).clicked() {
|
if ui.add_sized(size_1x1, Button::new("1")).clicked() {
|
||||||
|
|
|
||||||
|
|
@ -64,8 +64,8 @@ impl eframe::App for MyApp {
|
||||||
ui.add_space(20.0);
|
ui.add_space(20.0);
|
||||||
egui::Frame {
|
egui::Frame {
|
||||||
stroke: ui.visuals().noninteractive().bg_stroke,
|
stroke: ui.visuals().noninteractive().bg_stroke,
|
||||||
inner_margin: egui::Margin::same(4.0),
|
inner_margin: egui::Margin::same(4),
|
||||||
outer_margin: egui::Margin::same(4.0),
|
outer_margin: egui::Margin::same(4),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
|
|
@ -74,8 +74,8 @@ impl eframe::App for MyApp {
|
||||||
|
|
||||||
egui::Frame {
|
egui::Frame {
|
||||||
stroke: ui.visuals().noninteractive().bg_stroke,
|
stroke: ui.visuals().noninteractive().bg_stroke,
|
||||||
inner_margin: egui::Margin::same(8.0),
|
inner_margin: egui::Margin::same(8),
|
||||||
outer_margin: egui::Margin::same(6.0),
|
outer_margin: egui::Margin::same(6),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
|
|
@ -128,7 +128,7 @@ impl eframe::App for MyApp {
|
||||||
ui.label("UI nesting test:");
|
ui.label("UI nesting test:");
|
||||||
egui::Frame {
|
egui::Frame {
|
||||||
stroke: ui.visuals().noninteractive().bg_stroke,
|
stroke: ui.visuals().noninteractive().bg_stroke,
|
||||||
inner_margin: egui::Margin::same(4.0),
|
inner_margin: egui::Margin::same(4),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
|
|
@ -267,7 +267,7 @@ fn stack_ui(ui: &mut egui::Ui) {
|
||||||
fn stack_ui_impl(ui: &mut egui::Ui, stack: &egui::UiStack) {
|
fn stack_ui_impl(ui: &mut egui::Ui, stack: &egui::UiStack) {
|
||||||
egui::Frame {
|
egui::Frame {
|
||||||
stroke: ui.style().noninteractive().fg_stroke,
|
stroke: ui.style().noninteractive().fg_stroke,
|
||||||
inner_margin: egui::Margin::same(4.0),
|
inner_margin: egui::Margin::same(4),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue