Style tweaks (#2406)

* Note the namechange of egui::color to egui::ecolor

* Use a solid triangle for collapsing headers and windows

* Add Shadow::NONE

* Add Visuals::panel_fill, window_fill and window_stroke

* Bug fix: ComboBox::width sets the outer width of the ComboBox

* egui_extras::Table: add functions to access the `Ui` for the header/body

* ComboBox: use solid triangle

* Tweak default menu margin

* Nudge panel separator lines so they stay visible

* Update changelogs
This commit is contained in:
Emil Ernerfeldt 2022-12-08 10:55:13 +01:00 committed by GitHub
parent 5effc68ba4
commit da0a178701
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 164 additions and 92 deletions

View file

@ -25,6 +25,7 @@ NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG
* Added `Area::pivot` and `Window::pivot` which controls what part of the window to position ([#2303](https://github.com/emilk/egui/pull/2303)). * Added `Area::pivot` and `Window::pivot` which controls what part of the window to position ([#2303](https://github.com/emilk/egui/pull/2303)).
* Added support for [thin space](https://en.wikipedia.org/wiki/Thin_space). * Added support for [thin space](https://en.wikipedia.org/wiki/Thin_space).
* Added optional integration with [AccessKit](https://accesskit.dev/) for implementing platform accessibility APIs ([#2294](https://github.com/emilk/egui/pull/2294)). * Added optional integration with [AccessKit](https://accesskit.dev/) for implementing platform accessibility APIs ([#2294](https://github.com/emilk/egui/pull/2294)).
* Added `panel_fill`, `window_fill` and `window_stroke` to `Visuals` for your theming pleasure ([#2406](https://github.com/emilk/egui/pull/2406)).
* Plots: * Plots:
* Allow linking plot cursors ([#1722](https://github.com/emilk/egui/pull/1722)). * Allow linking plot cursors ([#1722](https://github.com/emilk/egui/pull/1722)).
* Added `Plot::auto_bounds_x/y` and `Plot::reset` ([#2029](https://github.com/emilk/egui/pull/2029)). * Added `Plot::auto_bounds_x/y` and `Plot::reset` ([#2029](https://github.com/emilk/egui/pull/2029)).
@ -36,6 +37,7 @@ NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG
* Panels always have a separator line, but no stroke on other sides. Their spacing has also changed slightly ([#2261](https://github.com/emilk/egui/pull/2261)). * Panels always have a separator line, but no stroke on other sides. Their spacing has also changed slightly ([#2261](https://github.com/emilk/egui/pull/2261)).
* Tooltips are only shown when mouse pointer is still ([#2263](https://github.com/emilk/egui/pull/2263)). * Tooltips are only shown when mouse pointer is still ([#2263](https://github.com/emilk/egui/pull/2263)).
* Make it slightly easier to click buttons ([#2304](https://github.com/emilk/egui/pull/2304)). * Make it slightly easier to click buttons ([#2304](https://github.com/emilk/egui/pull/2304)).
* `egui::color` has been renamed `egui::ecolor` ([#2399](https://github.com/emilk/egui/pull/2399)).
### Fixed 🐛 ### Fixed 🐛
* ⚠️ BREAKING: Fix text being too small ([#2069](https://github.com/emilk/egui/pull/2069)). * ⚠️ BREAKING: Fix text being too small ([#2069](https://github.com/emilk/egui/pull/2069)).
@ -52,6 +54,7 @@ NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG
* Fix bug in `plot::Line::fill` ([#2275](https://github.com/emilk/egui/pull/2275)). * Fix bug in `plot::Line::fill` ([#2275](https://github.com/emilk/egui/pull/2275)).
* Only emit `changed` events in `radio_value` and `selectable_value` if the value actually changed ([#2343](https://github.com/emilk/egui/pull/2343)). * Only emit `changed` events in `radio_value` and `selectable_value` if the value actually changed ([#2343](https://github.com/emilk/egui/pull/2343)).
* Fixed sizing bug in `Grid` ([#2384](https://github.com/emilk/egui/pull/2384)). * Fixed sizing bug in `Grid` ([#2384](https://github.com/emilk/egui/pull/2384)).
* `ComboBox::width` now correctly sets the outer width ([#2406](https://github.com/emilk/egui/pull/2406)).
## 0.19.0 - 2022-08-20 ## 0.19.0 - 2022-08-20

View file

@ -311,7 +311,6 @@ impl<'ui, HeaderRet> HeaderResponse<'ui, HeaderRet> {
/// Paint the arrow icon that indicated if the region is open or not /// Paint the arrow icon that indicated if the region is open or not
pub fn paint_default_icon(ui: &mut Ui, openness: f32, response: &Response) { pub fn paint_default_icon(ui: &mut Ui, openness: f32, response: &Response) {
let visuals = ui.style().interact(response); let visuals = ui.style().interact(response);
let stroke = visuals.fg_stroke;
let rect = response.rect; let rect = response.rect;
@ -325,7 +324,11 @@ pub fn paint_default_icon(ui: &mut Ui, openness: f32, response: &Response) {
*p = rect.center() + rotation * (*p - rect.center()); *p = rect.center() + rotation * (*p - rect.center());
} }
ui.painter().add(Shape::closed_line(points, stroke)); ui.painter().add(Shape::convex_polygon(
points,
visuals.fg_stroke.color,
Stroke::NONE,
));
} }
/// A function that paints an icon indicating if the region is open or not /// A function that paints an icon indicating if the region is open or not

View file

@ -77,7 +77,7 @@ impl ComboBox {
} }
} }
/// Set the width of the button and menu /// Set the outer width of the button and menu.
pub fn width(mut self, width: f32) -> Self { pub fn width(mut self, width: f32) -> Self {
self.width = Some(width); self.width = Some(width);
self self
@ -261,15 +261,20 @@ fn combo_box_dyn<'c, R>(
AboveOrBelow::Above AboveOrBelow::Above
}; };
let margin = ui.spacing().button_padding;
let button_response = button_frame(ui, button_id, is_popup_open, Sense::click(), |ui| { let button_response = button_frame(ui, button_id, is_popup_open, Sense::click(), |ui| {
// We don't want to change width when user selects something new // We don't want to change width when user selects something new
let full_minimum_width = wrap_enabled let full_minimum_width = if wrap_enabled {
.then(|| ui.available_width() - ui.spacing().item_spacing.x * 2.0) ui.available_width() - ui.spacing().item_spacing.x * 2.0
.unwrap_or_else(|| ui.spacing().slider_width); } else {
ui.spacing().slider_width - 2.0 * margin.x
};
let icon_size = Vec2::splat(ui.spacing().icon_width); let icon_size = Vec2::splat(ui.spacing().icon_width);
let wrap_width = wrap_enabled let wrap_width = if wrap_enabled {
.then(|| ui.available_width() - ui.spacing().item_spacing.x - icon_size.x) ui.available_width() - ui.spacing().item_spacing.x - icon_size.x
.unwrap_or(f32::INFINITY); } else {
f32::INFINITY
};
let galley = let galley =
selected_text.into_galley(ui, Some(wrap_enabled), wrap_width, TextStyle::Button); selected_text.into_galley(ui, Some(wrap_enabled), wrap_width, TextStyle::Button);
@ -396,16 +401,18 @@ fn paint_default_icon(
match above_or_below { match above_or_below {
AboveOrBelow::Above => { AboveOrBelow::Above => {
// Upward pointing triangle // Upward pointing triangle
painter.add(Shape::closed_line( painter.add(Shape::convex_polygon(
vec![rect.left_bottom(), rect.right_bottom(), rect.center_top()], vec![rect.left_bottom(), rect.right_bottom(), rect.center_top()],
visuals.fg_stroke, visuals.fg_stroke.color,
Stroke::NONE,
)); ));
} }
AboveOrBelow::Below => { AboveOrBelow::Below => {
// Downward pointing triangle // Downward pointing triangle
painter.add(Shape::closed_line( painter.add(Shape::convex_polygon(
vec![rect.left_top(), rect.right_top(), rect.center_bottom()], vec![rect.left_top(), rect.right_top(), rect.center_bottom()],
visuals.fg_stroke, visuals.fg_stroke.color,
Stroke::NONE,
)); ));
} }
} }

View file

@ -45,7 +45,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.0, 2.0),
fill: style.visuals.window_fill(), fill: style.visuals.panel_fill,
..Default::default() ..Default::default()
} }
} }
@ -53,7 +53,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.0),
fill: style.visuals.window_fill(), fill: style.visuals.panel_fill,
..Default::default() ..Default::default()
} }
} }

View file

@ -306,7 +306,10 @@ impl SidePanel {
Stroke::NONE Stroke::NONE
}; };
// TODO(emilk): draw line on top of all panels in this ui when https://github.com/emilk/egui/issues/1516 is done // TODO(emilk): draw line on top of all panels in this ui when https://github.com/emilk/egui/issues/1516 is done
let resize_x = side.opposite().side_x(rect); // In the meantime: nudge the line so its inside the panel, so it won't be covered by neighboring panel
// (hence the shrink).
let resize_x = side.opposite().side_x(rect.shrink(1.0));
let resize_x = ui.painter().round_to_pixel(resize_x);
ui.painter().vline(resize_x, rect.y_range(), stroke); ui.painter().vline(resize_x, rect.y_range(), stroke);
} }
@ -755,7 +758,10 @@ impl TopBottomPanel {
Stroke::NONE Stroke::NONE
}; };
// TODO(emilk): draw line on top of all panels in this ui when https://github.com/emilk/egui/issues/1516 is done // TODO(emilk): draw line on top of all panels in this ui when https://github.com/emilk/egui/issues/1516 is done
let resize_y = side.opposite().side_y(rect); // In the meantime: nudge the line so its inside the panel, so it won't be covered by neighboring panel
// (hence the shrink).
let resize_y = side.opposite().side_y(rect.shrink(1.0));
let resize_y = ui.painter().round_to_pixel(resize_y);
ui.painter().hline(rect.x_range(), resize_y, stroke); ui.painter().hline(rect.x_range(), resize_y, stroke);
} }

View file

@ -360,6 +360,10 @@ impl Margin {
pub fn right_bottom(&self) -> Vec2 { pub fn right_bottom(&self) -> Vec2 {
vec2(self.right, self.bottom) vec2(self.right, self.bottom)
} }
pub fn is_same(&self) -> bool {
self.left == self.right && self.left == self.top && self.left == self.bottom
}
} }
impl From<f32> for Margin { impl From<f32> for Margin {
@ -464,6 +468,11 @@ pub struct Visuals {
pub window_rounding: Rounding, pub window_rounding: Rounding,
pub window_shadow: Shadow, pub window_shadow: Shadow,
pub window_fill: Color32,
pub window_stroke: Stroke,
/// Panel background color
pub panel_fill: Color32,
pub popup_shadow: Shadow, pub popup_shadow: Shadow,
@ -495,7 +504,7 @@ impl Visuals {
} }
pub fn weak_text_color(&self) -> Color32 { pub fn weak_text_color(&self) -> Color32 {
crate::ecolor::tint_color_towards(self.text_color(), self.window_fill()) self.gray_out(self.text_color())
} }
#[inline(always)] #[inline(always)]
@ -506,12 +515,25 @@ impl Visuals {
/// Window background color. /// Window background color.
#[inline(always)] #[inline(always)]
pub fn window_fill(&self) -> Color32 { pub fn window_fill(&self) -> Color32 {
self.widgets.noninteractive.bg_fill self.window_fill
} }
#[inline(always)] #[inline(always)]
pub fn window_stroke(&self) -> Stroke { pub fn window_stroke(&self) -> Stroke {
self.widgets.noninteractive.bg_stroke self.window_stroke
}
/// When fading out things, we fade the colors towards this.
// TODO(emilk): replace with an alpha
#[inline(always)]
pub fn fade_out_to_color(&self) -> Color32 {
self.widgets.noninteractive.bg_fill
}
/// Returned a "grayed out" version of the given color.
#[inline(always)]
pub fn gray_out(&self, color: Color32) -> Color32 {
crate::ecolor::tint_color_towards(color, self.fade_out_to_color())
} }
} }
@ -651,7 +673,7 @@ impl Default for Spacing {
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.0),
menu_margin: Margin::same(1.0), menu_margin: Margin::same(6.0),
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),
@ -694,8 +716,14 @@ impl Visuals {
code_bg_color: Color32::from_gray(64), code_bg_color: Color32::from_gray(64),
warn_fg_color: Color32::from_rgb(255, 143, 0), // orange warn_fg_color: Color32::from_rgb(255, 143, 0), // orange
error_fg_color: Color32::from_rgb(255, 0, 0), // red error_fg_color: Color32::from_rgb(255, 0, 0), // red
window_rounding: Rounding::same(6.0), window_rounding: Rounding::same(6.0),
window_shadow: Shadow::big_dark(), window_shadow: Shadow::big_dark(),
window_fill: Color32::from_gray(27),
window_stroke: Stroke::new(1.0, Color32::from_gray(60)),
panel_fill: Color32::from_gray(27),
popup_shadow: Shadow::small_dark(), popup_shadow: Shadow::small_dark(),
resize_corner_size: 12.0, resize_corner_size: 12.0,
text_cursor_width: 2.0, text_cursor_width: 2.0,
@ -718,7 +746,13 @@ impl Visuals {
code_bg_color: Color32::from_gray(230), code_bg_color: Color32::from_gray(230),
warn_fg_color: Color32::from_rgb(255, 100, 0), // slightly orange red. it's difficult to find a warning color that pops on bright background. warn_fg_color: Color32::from_rgb(255, 100, 0), // slightly orange red. it's difficult to find a warning color that pops on bright background.
error_fg_color: Color32::from_rgb(255, 0, 0), // red error_fg_color: Color32::from_rgb(255, 0, 0), // red
window_shadow: Shadow::big_light(), window_shadow: Shadow::big_light(),
window_fill: Color32::from_gray(248),
window_stroke: Stroke::new(1.0, Color32::from_gray(190)),
panel_fill: Color32::from_gray(248),
popup_shadow: Shadow::small_light(), popup_shadow: Shadow::small_light(),
..Self::dark() ..Self::dark()
} }
@ -757,8 +791,8 @@ impl Widgets {
pub fn dark() -> Self { pub fn dark() -> Self {
Self { Self {
noninteractive: WidgetVisuals { noninteractive: WidgetVisuals {
bg_fill: Color32::from_gray(27), // window background bg_fill: Color32::from_gray(27),
bg_stroke: Stroke::new(1.0, Color32::from_gray(60)), // separators, indentation lines, windows outlines bg_stroke: Stroke::new(1.0, Color32::from_gray(60)), // separators, indentation lines
fg_stroke: Stroke::new(1.0, Color32::from_gray(140)), // normal text color fg_stroke: Stroke::new(1.0, Color32::from_gray(140)), // normal text color
rounding: Rounding::same(2.0), rounding: Rounding::same(2.0),
expansion: 0.0, expansion: 0.0,
@ -797,8 +831,8 @@ impl Widgets {
pub fn light() -> Self { pub fn light() -> Self {
Self { Self {
noninteractive: WidgetVisuals { noninteractive: WidgetVisuals {
bg_fill: Color32::from_gray(248), // window background - should be distinct from TextEdit background bg_fill: Color32::from_gray(248),
bg_stroke: Stroke::new(1.0, Color32::from_gray(190)), // separators, indentation lines, windows outlines bg_stroke: Stroke::new(1.0, Color32::from_gray(190)), // separators, indentation lines
fg_stroke: Stroke::new(1.0, Color32::from_gray(80)), // normal text color fg_stroke: Stroke::new(1.0, Color32::from_gray(80)), // normal text color
rounding: Rounding::same(2.0), rounding: Rounding::same(2.0),
expansion: 0.0, expansion: 0.0,
@ -954,64 +988,8 @@ impl Spacing {
ui.add(slider_vec2(item_spacing, 0.0..=20.0, "Item spacing")); ui.add(slider_vec2(item_spacing, 0.0..=20.0, "Item spacing"));
let margin_range = 0.0..=20.0; margin_ui(ui, "Window margin:", window_margin);
ui.horizontal(|ui| { margin_ui(ui, "Menu margin:", menu_margin);
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.clone())
.prefix("bottom: "),
);
ui.label("Window margins y");
});
ui.horizontal(|ui| {
ui.add(
DragValue::new(&mut menu_margin.left)
.clamp_range(margin_range.clone())
.prefix("left: "),
);
ui.add(
DragValue::new(&mut menu_margin.right)
.clamp_range(margin_range.clone())
.prefix("right: "),
);
ui.label("Menu margins x");
});
ui.horizontal(|ui| {
ui.add(
DragValue::new(&mut menu_margin.top)
.clamp_range(margin_range.clone())
.prefix("top: "),
);
ui.add(
DragValue::new(&mut menu_margin.bottom)
.clamp_range(margin_range)
.prefix("bottom: "),
);
ui.label("Menu margins y");
});
ui.add(slider_vec2(button_padding, 0.0..=20.0, "Button padding")); ui.add(slider_vec2(button_padding, 0.0..=20.0, "Button padding"));
ui.add(slider_vec2(interact_size, 4.0..=60.0, "Interact size")) ui.add(slider_vec2(interact_size, 4.0..=60.0, "Interact size"))
@ -1079,6 +1057,55 @@ impl Spacing {
} }
} }
fn margin_ui(ui: &mut Ui, text: &str, margin: &mut Margin) {
let margin_range = 0.0..=20.0;
ui.horizontal(|ui| {
ui.label(text);
let mut same = margin.is_same();
ui.checkbox(&mut same, "Same");
if same {
let mut value = margin.left;
ui.add(DragValue::new(&mut value).clamp_range(margin_range.clone()));
*margin = Margin::same(value);
} else {
if margin.is_same() {
// HACK: prevent collapse:
margin.right = margin.left + 1.0;
margin.bottom = margin.left + 2.0;
margin.top = margin.left + 3.0;
}
ui.add(
DragValue::new(&mut margin.left)
.clamp_range(margin_range.clone())
.prefix("L: "),
)
.on_hover_text("Left margin");
ui.add(
DragValue::new(&mut margin.right)
.clamp_range(margin_range.clone())
.prefix("R: "),
)
.on_hover_text("Right margin");
ui.add(
DragValue::new(&mut margin.top)
.clamp_range(margin_range.clone())
.prefix("T: "),
)
.on_hover_text("Top margin");
ui.add(
DragValue::new(&mut margin.bottom)
.clamp_range(margin_range)
.prefix("B: "),
)
.on_hover_text("Bottom margin");
}
});
}
impl Interaction { impl Interaction {
pub fn ui(&mut self, ui: &mut crate::Ui) { pub fn ui(&mut self, ui: &mut crate::Ui) {
let Self { let Self {
@ -1210,9 +1237,16 @@ impl Visuals {
code_bg_color, code_bg_color,
warn_fg_color, warn_fg_color,
error_fg_color, error_fg_color,
window_rounding, window_rounding,
window_shadow, window_shadow,
window_fill,
window_stroke,
panel_fill,
popup_shadow, popup_shadow,
resize_corner_size, resize_corner_size,
text_cursor_width, text_cursor_width,
text_cursor_preview, text_cursor_preview,
@ -1223,7 +1257,8 @@ impl Visuals {
ui.collapsing("Background Colors", |ui| { ui.collapsing("Background Colors", |ui| {
ui_color(ui, &mut widgets.inactive.bg_fill, "Buttons"); ui_color(ui, &mut widgets.inactive.bg_fill, "Buttons");
ui_color(ui, &mut widgets.noninteractive.bg_fill, "Windows"); ui_color(ui, window_fill, "Windows");
ui_color(ui, panel_fill, "Panels");
ui_color(ui, faint_bg_color, "Faint accent").on_hover_text( ui_color(ui, faint_bg_color, "Faint accent").on_hover_text(
"Used for faint accentuation of interactive things, like striped grids.", "Used for faint accentuation of interactive things, like striped grids.",
); );
@ -1233,8 +1268,8 @@ impl Visuals {
ui.collapsing("Window", |ui| { ui.collapsing("Window", |ui| {
// Common shortcuts // Common shortcuts
ui_color(ui, &mut widgets.noninteractive.bg_fill, "Fill"); ui_color(ui, window_fill, "Fill");
stroke_ui(ui, &mut widgets.noninteractive.bg_stroke, "Outline"); stroke_ui(ui, window_stroke, "Outline");
rounding_ui(ui, window_rounding); rounding_ui(ui, window_rounding);

View file

@ -239,7 +239,7 @@ impl Ui {
self.enabled &= enabled; self.enabled &= enabled;
if !self.enabled && self.is_visible() { if !self.enabled && self.is_visible() {
self.painter self.painter
.set_fade_to_color(Some(self.visuals().window_fill())); .set_fade_to_color(Some(self.visuals().fade_out_to_color()));
} }
} }

View file

@ -239,7 +239,7 @@ impl Widget for &mut LegendWidget {
let background_frame = Frame { let background_frame = Frame {
inner_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::NONE,
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() ..Default::default()

View file

@ -176,7 +176,7 @@ impl eframe::App for WrapApp {
} }
fn clear_color(&self, visuals: &egui::Visuals) -> egui::Rgba { fn clear_color(&self, visuals: &egui::Visuals) -> egui::Rgba {
visuals.window_fill().into() visuals.panel_fill.into()
} }
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {

View file

@ -58,9 +58,8 @@ pub fn drop_target<R>(
let mut fill = style.bg_fill; let mut fill = style.bg_fill;
let mut stroke = style.bg_stroke; let mut stroke = style.bg_stroke;
if is_being_dragged && !can_accept_what_is_being_dragged { if is_being_dragged && !can_accept_what_is_being_dragged {
// gray out: fill = ui.visuals().gray_out(fill);
fill = ecolor::tint_color_towards(fill, ui.visuals().window_fill()); stroke.color = ui.visuals().gray_out(stroke.color);
stroke.color = ecolor::tint_color_towards(stroke.color, ui.visuals().window_fill());
} }
ui.painter().set( ui.painter().set(

View file

@ -516,6 +516,13 @@ pub struct Table<'a> {
} }
impl<'a> Table<'a> { impl<'a> Table<'a> {
/// Access the contained [`egui::Ui`].
///
/// You can use this to e.g. modify the [`egui::Style`] with [`egui::Ui::style_mut`].
pub fn ui_mut(&mut self) -> &mut egui::Ui {
self.ui
}
/// Create table body after adding a header row /// Create table body after adding a header row
pub fn body<F>(self, add_body_contents: F) pub fn body<F>(self, add_body_contents: F)
where where
@ -724,6 +731,13 @@ pub struct TableBody<'a> {
} }
impl<'a> TableBody<'a> { impl<'a> TableBody<'a> {
/// Access the contained [`egui::Ui`].
///
/// You can use this to e.g. modify the [`egui::Style`] with [`egui::Ui::style_mut`].
pub fn ui_mut(&mut self) -> &mut egui::Ui {
self.layout.ui
}
/// Where in screen-space is the table body? /// Where in screen-space is the table body?
pub fn max_rect(&self) -> Rect { pub fn max_rect(&self) -> Rect {
self.layout self.layout

View file

@ -14,6 +14,11 @@ pub struct Shadow {
} }
impl Shadow { impl Shadow {
pub const NONE: Self = Self {
extrusion: 0.0,
color: Color32::TRANSPARENT,
};
/// Tooltips, menus, …, for dark mode. /// Tooltips, menus, …, for dark mode.
pub fn small_dark() -> Self { pub fn small_dark() -> Self {
Self { Self {