1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-31 22:00:03 -04:00

⚠️ Frame now includes stroke width as part of padding (#5575)

* Part of https://github.com/emilk/egui/issues/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.
This commit is contained in:
Emil Ernerfeldt
2025-01-04 10:29:22 +01:00
committed by GitHub
parent 938d8b0d2e
commit 6607cd95f9
42 changed files with 680 additions and 508 deletions

View File

@@ -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)),
}
}
}

View File

@@ -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
@@ -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));
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,
);
}
});
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.");
}