Skip to content

Commit

Permalink
⚠️ Frame now includes stroke width as part of padding (#5575)
Browse files Browse the repository at this point in the history
* Part of #4019

`Frame` now includes the width of the stroke as part of its size. From
the new docs:

### `Frame` docs
The total (outer) size of a frame is `content_size + inner_margin +
2*stroke.width + outer_margin`.

Everything within the stroke is filled with the fill color (if any).

```text
+-----------------^-------------------------------------- -+
|                 | outer_margin                           |
|    +------------v----^------------------------------+    |
|    |                 | stroke width                 |    |
|    |    +------------v---^---------------------+    |    |
|    |    |                | inner_margin        |    |    |
|    |    |    +-----------v----------------+    |    |    |
|    |    |    |             ^              |    |    |    |
|    |    |    |             |              |    |    |    |
|    |    |    |<------ content_size ------>|    |    |    |
|    |    |    |             |              |    |    |    |
|    |    |    |             v              |    |    |    |
|    |    |    +------- content_rect -------+    |    |    |
|    |    |                                      |    |    |
|    |    +-------------fill_rect ---------------+    |    |
|    |                                                |    |
|    +----------------- widget_rect ------------------+    |
|                                                          |
+---------------------- outer_rect ------------------------+
```

The four rectangles, from inside to outside, are:
* `content_rect`: the rectangle that is made available to the inner
[`Ui`] or widget.
* `fill_rect`: the rectangle that is filled with the fill color (inside
the stroke, if any).
* `widget_rect`: is the interactive part of the widget (what sense
clicks etc).
* `outer_rect`: what is allocated in the outer [`Ui`], and is what is
returned by [`Response::rect`].

### Notes
This required rewriting a lot of the layout code for `egui::Window`,
which was a massive pain. But now the window margin and stroke width is
properly accounted for everywhere.
  • Loading branch information
emilk authored Jan 4, 2025
1 parent 938d8b0 commit 6607cd9
Show file tree
Hide file tree
Showing 42 changed files with 671 additions and 499 deletions.
298 changes: 209 additions & 89 deletions crates/egui/src/containers/frame.rs

Large diffs are not rendered by default.

359 changes: 209 additions & 150 deletions crates/egui/src/containers/window.rs

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions crates/egui/src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1771,12 +1771,14 @@ impl Ui {
/// Add extra space before the next widget.
///
/// The direction is dependent on the layout.
/// This will be in addition to the [`crate::style::Spacing::item_spacing`].
///
/// This will be in addition to the [`crate::style::Spacing::item_spacing`]
/// that is always added, but `item_spacing` won't be added _again_ by `add_space`.
///
/// [`Self::min_rect`] will expand to contain the space.
#[inline]
pub fn add_space(&mut self, amount: f32) {
self.placer.advance_cursor(amount);
self.placer.advance_cursor(amount.round_ui());
}

/// Show some text.
Expand Down
8 changes: 6 additions & 2 deletions crates/egui_demo_app/src/wrap_app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ pub struct FractalClockApp {
impl eframe::App for FractalClockApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::CentralPanel::default()
.frame(egui::Frame::dark_canvas(&ctx.style()))
.frame(
egui::Frame::dark_canvas(&ctx.style())
.stroke(egui::Stroke::NONE)
.rounding(0),
)
.show(ctx, |ui| {
self.fractal_clock
.ui(ui, self.mock_time.or(Some(crate::seconds_since_midnight())));
Expand Down Expand Up @@ -293,7 +297,7 @@ impl eframe::App for WrapApp {

let mut cmd = Command::Nothing;
egui::TopBottomPanel::top("wrap_app_top_bar")
.frame(egui::Frame::none().inner_margin(4.0))
.frame(egui::Frame::new().inner_margin(4))
.show(ctx, |ui| {
ui.horizontal_wrapped(|ui| {
ui.visuals_mut().button_frame = false;
Expand Down
4 changes: 2 additions & 2 deletions crates/egui_demo_app/tests/snapshots/clock.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_app/tests/snapshots/custom3d.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 8 additions & 9 deletions crates/egui_demo_lib/src/demo/frame_demo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,18 @@ pub struct FrameDemo {
impl Default for FrameDemo {
fn default() -> Self {
Self {
frame: egui::Frame {
inner_margin: 12.0.into(),
outer_margin: 24.0.into(),
rounding: 14.0.into(),
shadow: egui::Shadow {
frame: egui::Frame::new()
.inner_margin(12)
.outer_margin(24)
.rounding(14)
.shadow(egui::Shadow {
offset: [8, 12],
blur: 16,
spread: 0,
color: egui::Color32::from_black_alpha(180),
},
fill: egui::Color32::from_rgba_unmultiplied(97, 0, 255, 128),
stroke: egui::Stroke::new(1.0, egui::Color32::GRAY),
},
})
.fill(egui::Color32::from_rgba_unmultiplied(97, 0, 255, 128))
.stroke(egui::Stroke::new(1.0, egui::Color32::GRAY)),
}
}
}
Expand Down
92 changes: 45 additions & 47 deletions crates/egui_demo_lib/src/demo/misc_demo_window.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::{Demo, View};

use egui::{
vec2, Align, Checkbox, CollapsingHeader, Color32, Context, FontId, Frame, Resize, RichText,
Sense, Slider, Stroke, TextFormat, TextStyle, Ui, Vec2, Window,
vec2, Align, Checkbox, CollapsingHeader, Color32, Context, FontId, Resize, RichText, Sense,
Slider, Stroke, TextFormat, TextStyle, Ui, Vec2, Window,
};

/// Showcase some ui code
Expand Down Expand Up @@ -512,54 +512,52 @@ fn ui_stack_demo(ui: &mut Ui) {
);
});
let stack = ui.stack().clone();
Frame {
inner_margin: ui.spacing().menu_margin,
stroke: ui.visuals().widgets.noninteractive.bg_stroke,
..Default::default()
}
.show(ui, |ui| {
egui_extras::TableBuilder::new(ui)
.column(egui_extras::Column::auto())
.column(egui_extras::Column::auto())
.header(18.0, |mut header| {
header.col(|ui| {
ui.strong("id");
});
header.col(|ui| {
ui.strong("kind");
});
})
.body(|mut body| {
for node in stack.iter() {
body.row(18.0, |mut row| {
row.col(|ui| {
let response = ui.label(format!("{:?}", node.id));

if response.hovered() {
ui.ctx().debug_painter().debug_rect(
node.max_rect,
Color32::GREEN,
"max_rect",
);
ui.ctx().debug_painter().circle_filled(
node.min_rect.min,
2.0,
Color32::RED,
);
}
});
egui::Frame::new()
.inner_margin(ui.spacing().menu_margin)
.stroke(ui.visuals().widgets.noninteractive.bg_stroke)
.show(ui, |ui| {
egui_extras::TableBuilder::new(ui)
.column(egui_extras::Column::auto())
.column(egui_extras::Column::auto())
.header(18.0, |mut header| {
header.col(|ui| {
ui.strong("id");
});
header.col(|ui| {
ui.strong("kind");
});
})
.body(|mut body| {
for node in stack.iter() {
body.row(18.0, |mut row| {
row.col(|ui| {
let response = ui.label(format!("{:?}", node.id));

if response.hovered() {
ui.ctx().debug_painter().debug_rect(
node.max_rect,
Color32::GREEN,
"max_rect",
);
ui.ctx().debug_painter().circle_filled(
node.min_rect.min,
2.0,
Color32::RED,
);
}
});

row.col(|ui| {
ui.label(if let Some(kind) = node.kind() {
format!("{kind:?}")
} else {
"-".to_owned()
row.col(|ui| {
ui.label(if let Some(kind) = node.kind() {
format!("{kind:?}")
} else {
"-".to_owned()
});
});
});
});
}
});
});
}
});
});

ui.small("Hover on UI's ids to display their origin and max rect.");
}
Expand Down
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Bézier Curve.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Code Editor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Code Example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Context Menus.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Drag and Drop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Extra Viewport.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Font Book.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Frame.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Highlighting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Misc Demos.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Modals.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Multi Touch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Painting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Pan Zoom.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Panels.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Scrolling.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Sliders.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Strip.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Table.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Text Layout.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/TextEdit.png
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Tooltips.png
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Undo Redo.png
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/demos/Window Options.png
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/modals_1.png
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/modals_2.png
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/tests/snapshots/modals_3.png
2 changes: 1 addition & 1 deletion crates/egui_kittest/src/app_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl<'a, State> AppKind<'a, State> {
sizing_pass: bool,
) -> egui::Response {
egui::CentralPanel::default()
.frame(Frame::none())
.frame(Frame::NONE)
.show(ctx, |ui| {
let mut builder = egui::UiBuilder::new();
if sizing_pass {
Expand Down
Loading

0 comments on commit 6607cd9

Please sign in to comment.