mirror of
https://github.com/emilk/egui.git
synced 2026-09-01 14:20:04 -04:00
Add a PopupStyle, so the theme frames popups and menus
A `Popup` framed itself with `Frame::popup` and left item spacing to the ambient style. Both now come from a `PopupStyle`, which is what lets a theme give a menu its own padding and its own item rhythm. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@ use crate::{
|
|||||||
Sense, Ui, UiKind, UiStackInfo,
|
Sense, Ui, UiKind, UiStackInfo,
|
||||||
containers::menu::{MenuConfig, MenuState, menu_style},
|
containers::menu::{MenuConfig, MenuState, menu_style},
|
||||||
style::StyleModifier,
|
style::StyleModifier,
|
||||||
widget_style::HasClasses as _,
|
widget_style::{ClassName, Classes, HasClasses as _, PopupStyle},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// What should we anchor the popup to?
|
/// What should we anchor the popup to?
|
||||||
@@ -193,7 +193,7 @@ impl<'a> Popup<'a> {
|
|||||||
///
|
///
|
||||||
/// A menu lays its items out itself, so a widget in one is generally styled to fit that
|
/// A menu lays its items out itself, so a widget in one is generally styled to fit that
|
||||||
/// layout rather than to stand on its own.
|
/// layout rather than to stand on its own.
|
||||||
pub const CLASS_MENU: &'static str = "egui::popup::menu";
|
pub const CLASS_MENU: ClassName = ClassName::from_static("egui::popup::menu");
|
||||||
|
|
||||||
/// Create a new popup
|
/// Create a new popup
|
||||||
pub fn new(id: Id, ctx: Context, anchor: impl Into<PopupAnchor>, layer_id: LayerId) -> Self {
|
pub fn new(id: Id, ctx: Context, anchor: impl Into<PopupAnchor>, layer_id: LayerId) -> Self {
|
||||||
@@ -600,8 +600,10 @@ impl<'a> Popup<'a> {
|
|||||||
|
|
||||||
let (pivot, anchor) = best_align.pivot_pos(&anchor_rect, gap);
|
let (pivot, anchor) = best_align.pivot_pos(&anchor_rect, gap);
|
||||||
|
|
||||||
|
let classes = Classes::default().with_class_if(Self::CLASS_MENU, kind == PopupKind::Menu);
|
||||||
|
|
||||||
let mut area = Area::new(id)
|
let mut area = Area::new(id)
|
||||||
.with_class_if(Self::CLASS_MENU, kind == PopupKind::Menu)
|
.with_classes(classes.clone())
|
||||||
.order(kind.order())
|
.order(kind.order())
|
||||||
.pivot(pivot)
|
.pivot(pivot)
|
||||||
.fixed_pos(anchor)
|
.fixed_pos(anchor)
|
||||||
@@ -624,7 +626,12 @@ impl<'a> Popup<'a> {
|
|||||||
|
|
||||||
let mut response = area.show(&ctx, |ui| {
|
let mut response = area.show(&ctx, |ui| {
|
||||||
style.apply(ui.style_mut());
|
style.apply(ui.style_mut());
|
||||||
let frame = frame.unwrap_or_else(|| Frame::popup(ui.style()));
|
|
||||||
|
// The theme decides how the popup is framed and how tightly its items sit together.
|
||||||
|
let popup_style: PopupStyle = ui.widget_style(id, &classes);
|
||||||
|
ui.spacing_mut().item_spacing = popup_style.item_spacing;
|
||||||
|
|
||||||
|
let frame = frame.unwrap_or(popup_style.frame);
|
||||||
frame.show(ui, content).inner
|
frame.show(ui, content).inner
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ use crate::{
|
|||||||
class::HasClasses as _,
|
class::HasClasses as _,
|
||||||
theme::StyleProvider,
|
theme::StyleProvider,
|
||||||
widget_style::{
|
widget_style::{
|
||||||
AtomLayoutStyle, ButtonStyle, CheckboxStyle, SeparatorStyle, StyleArgs, TextEditStyle,
|
AtomLayoutStyle, ButtonStyle, CheckboxStyle, PopupStyle, SeparatorStyle, StyleArgs,
|
||||||
TextVisuals, WidgetState,
|
TextEditStyle, TextVisuals, WidgetState,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -26,6 +26,7 @@ impl DefaultStyle {
|
|||||||
ctx.add_widget_theme::<SeparatorStyle>(Self);
|
ctx.add_widget_theme::<SeparatorStyle>(Self);
|
||||||
ctx.add_widget_theme::<CheckboxStyle>(Self);
|
ctx.add_widget_theme::<CheckboxStyle>(Self);
|
||||||
ctx.add_widget_theme::<TextEditStyle>(Self);
|
ctx.add_widget_theme::<TextEditStyle>(Self);
|
||||||
|
ctx.add_widget_theme::<PopupStyle>(Self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,6 +107,17 @@ impl StyleProvider<ButtonStyle> for DefaultStyle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl StyleProvider<PopupStyle> for DefaultStyle {
|
||||||
|
fn style(&mut self, modifiers: &StyleArgs<'_>) -> PopupStyle {
|
||||||
|
let StyleArgs { style, .. } = modifiers;
|
||||||
|
|
||||||
|
PopupStyle {
|
||||||
|
frame: Frame::popup(style),
|
||||||
|
item_spacing: style.spacing.item_spacing,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl StyleProvider<TextEditStyle> for DefaultStyle {
|
impl StyleProvider<TextEditStyle> for DefaultStyle {
|
||||||
fn style(&mut self, modifiers: &StyleArgs<'_>) -> TextEditStyle {
|
fn style(&mut self, modifiers: &StyleArgs<'_>) -> TextEditStyle {
|
||||||
let StyleArgs {
|
let StyleArgs {
|
||||||
|
|||||||
@@ -127,6 +127,21 @@ pub struct ButtonStyle {
|
|||||||
|
|
||||||
impl WidgetStyle for ButtonStyle {}
|
impl WidgetStyle for ButtonStyle {}
|
||||||
|
|
||||||
|
/// Dedicated style for a [`crate::Popup`], including menus and tooltips
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PopupStyle {
|
||||||
|
/// Frame around the popup's contents, including its padding.
|
||||||
|
pub frame: Frame,
|
||||||
|
|
||||||
|
/// Spacing between the items inside the popup.
|
||||||
|
///
|
||||||
|
/// A menu wants its items flush against each other, while a tooltip wants them spaced out
|
||||||
|
/// like any other content.
|
||||||
|
pub item_spacing: Vec2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WidgetStyle for PopupStyle {}
|
||||||
|
|
||||||
/// Dedicated text edit style
|
/// Dedicated text edit style
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TextEditStyle {
|
pub struct TextEditStyle {
|
||||||
|
|||||||
Reference in New Issue
Block a user