1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-01 14:20:04 -04:00

remove style in parameter + cleanup

This commit is contained in:
adrien
2026-06-21 21:53:31 +02:00
parent b742e230a0
commit 8762c7dba7
5 changed files with 73 additions and 52 deletions

View File

@@ -2061,9 +2061,8 @@ impl Context {
&self, &self,
classes: &Classes, classes: &Classes,
state: WidgetState, state: WidgetState,
base: &Style,
) -> Option<S> { ) -> Option<S> {
self.write(move |ctx| ctx.themes.get::<S>(classes, state, base)) self.write(move |ctx| ctx.themes.get::<S>(classes, state))
} }
} }

View File

@@ -3,7 +3,7 @@ use std::sync::Arc;
use epaint::mutex::Mutex; use epaint::mutex::Mutex;
use crate::{ use crate::{
Id, Style, Ui, Id, Ui,
util::IdTypeMap, util::IdTypeMap,
widget_style::{Classes, StyleStruct, WidgetState}, widget_style::{Classes, StyleStruct, WidgetState},
}; };
@@ -40,7 +40,7 @@ impl ThemeCache {
/// A Theme plugin that implement a style computation for a defined `StyleStruct` /// A Theme plugin that implement a style computation for a defined `StyleStruct`
pub trait ThemeStyle<S> { pub trait ThemeStyle<S> {
/// The style according to the classes and state of the widget /// The style according to the classes and state of the widget
fn style(&mut self, classes: &Classes, state: WidgetState, base: &Style) -> S; fn style(&mut self, classes: &Classes, state: WidgetState) -> S;
} }
impl Ui { impl Ui {
@@ -53,9 +53,6 @@ impl Ui {
id: crate::Id, id: crate::Id,
classes: &Classes, classes: &Classes,
) -> S { ) -> S {
// If the requested `StyleStruct` is cached, return it without computing.
// Otherwise proceed to compute the style from the widget information.
// Fetch the current state of the widget // Fetch the current state of the widget
let state = self let state = self
.ctx() .ctx()
@@ -63,10 +60,10 @@ impl Ui {
.map(|r| r.widget_state()) .map(|r| r.widget_state())
.unwrap_or_default(); .unwrap_or_default();
if let Some(style) = self.get_style::<S>(classes, state, self.style()) { if let Some(style) = self.get_style::<S>(classes, state) {
style style
} else { } else {
S::default_style(classes, state, self.style()) S::default_style(classes, state)
} }
} }
} }
@@ -103,11 +100,10 @@ impl Themes {
&self, &self,
classes: &Classes, classes: &Classes,
state: WidgetState, state: WidgetState,
base: &Style,
) -> Option<S> { ) -> Option<S> {
let v = self let v = self
.themes .themes
.get_temp::<Arc<Mutex<Box<dyn ThemeStyle<S> + Send + Sync>>>>(Id::NULL); .get_temp::<Arc<Mutex<Box<dyn ThemeStyle<S> + Send + Sync>>>>(Id::NULL);
v.map(|engine| engine.lock().style(classes, state, base)) v.map(|engine| engine.lock().style(classes, state))
} }
} }

View File

@@ -8,13 +8,14 @@ use epaint::{Color32, FontId, Shadow, Stroke, text::TextWrapMode};
use smallvec::SmallVec; use smallvec::SmallVec;
use crate::{ use crate::{
Frame, Response, Style, TextBuffer as _, TextStyle, Frame, Response, Spacing, Style, TextBuffer as _, TextStyle, Visuals,
style::{WidgetVisuals, Widgets}, style::{WidgetVisuals, Widgets},
}; };
/// Each dedicated style must implement this trait to be used in the theme plugin system /// Each dedicated style must implement this trait to be used in the theme plugin system
pub trait StyleStruct: Debug + Clone + Send + Sync + std::any::Any + 'static { pub trait StyleStruct: Debug + Clone + Send + Sync + std::any::Any + 'static {
fn default_style(classes: &Classes, state: WidgetState, base: &Style) -> Self /// The default style for this struct based on classes and state of the widget.
fn default_style(classes: &Classes, state: WidgetState) -> Self
where where
Self: Sized; Self: Sized;
} }
@@ -44,24 +45,29 @@ pub struct WidgetStyle {
} }
impl StyleStruct for WidgetStyle { impl StyleStruct for WidgetStyle {
fn default_style(_classes: &Classes, state: WidgetState, base: &Style) -> Self { fn default_style(_classes: &Classes, state: WidgetState) -> Self {
let visuals = base.visuals.widgets.state(state); let visuals = Widgets::dark();
let font_id = base.override_font_id.clone(); let spacing = Spacing::default();
let visuals = match state {
WidgetState::Noninteractive => visuals.noninteractive,
WidgetState::Inactive => visuals.inactive,
WidgetState::Hovered => visuals.hovered,
WidgetState::Active => visuals.active,
};
Self { Self {
frame: Frame { frame: Frame {
fill: visuals.bg_fill, fill: visuals.bg_fill,
stroke: visuals.bg_stroke, stroke: visuals.bg_stroke,
corner_radius: visuals.corner_radius, corner_radius: visuals.corner_radius,
inner_margin: base.spacing.button_padding.into(), inner_margin: spacing.button_padding.into(),
..Default::default() ..Default::default()
}, },
stroke: visuals.fg_stroke, stroke: visuals.fg_stroke,
text: TextVisuals { text: TextVisuals {
color: base color: visuals.text_color(),
.visuals font_id: TextStyle::Button.resolve(&Style::default()),
.override_text_color
.unwrap_or_else(|| visuals.text_color()),
font_id: font_id.unwrap_or_else(|| TextStyle::Body.resolve(base)),
strikethrough: Stroke::NONE, strikethrough: Stroke::NONE,
underline: Stroke::NONE, underline: Stroke::NONE,
}, },
@@ -77,25 +83,35 @@ pub struct ButtonStyle {
} }
impl StyleStruct for ButtonStyle { impl StyleStruct for ButtonStyle {
fn default_style(classes: &Classes, state: WidgetState, base: &Style) -> Self { fn default_style(classes: &Classes, state: WidgetState) -> Self {
let mut visuals = *base.visuals.widgets.state(state); let widget_visuals = Widgets::dark();
let mut ws = WidgetStyle::default_style(classes, state, base); let spacing = Spacing::default();
let mut widget_visuals = match state {
WidgetState::Noninteractive => widget_visuals.noninteractive,
WidgetState::Inactive => widget_visuals.inactive,
WidgetState::Hovered => widget_visuals.hovered,
WidgetState::Active => widget_visuals.active,
};
let mut ws = WidgetStyle::default_style(classes, state);
if classes.has(SELECTED_CLASS) { if classes.has(SELECTED_CLASS) {
visuals.weak_bg_fill = base.visuals.selection.bg_fill; let visuals = Visuals::default();
visuals.bg_fill = base.visuals.selection.bg_fill; widget_visuals.weak_bg_fill = visuals.selection.bg_fill;
visuals.fg_stroke = base.visuals.selection.stroke; widget_visuals.bg_fill = visuals.selection.bg_fill;
ws.text.color = base.visuals.selection.stroke.color; widget_visuals.fg_stroke = visuals.selection.stroke;
ws.text.color = visuals.selection.stroke.color;
} }
Self { Self {
frame: Frame { frame: Frame {
fill: visuals.weak_bg_fill, fill: widget_visuals.weak_bg_fill,
stroke: visuals.bg_stroke, stroke: widget_visuals.bg_stroke,
corner_radius: visuals.corner_radius, corner_radius: widget_visuals.corner_radius,
outer_margin: (-Vec2::splat(visuals.expansion)).into(), outer_margin: (-Vec2::splat(widget_visuals.expansion)).into(),
inner_margin: (base.spacing.button_padding + Vec2::splat(visuals.expansion) inner_margin: (spacing.button_padding + Vec2::splat(widget_visuals.expansion)
- Vec2::splat(visuals.bg_stroke.width)) - Vec2::splat(widget_visuals.bg_stroke.width))
.into(), .into(),
..Default::default() ..Default::default()
}, },
@@ -127,17 +143,27 @@ pub struct CheckboxStyle {
} }
impl StyleStruct for CheckboxStyle { impl StyleStruct for CheckboxStyle {
fn default_style(classes: &Classes, state: WidgetState, base: &Style) -> Self { fn default_style(classes: &Classes, state: WidgetState) -> Self {
let visuals = base.visuals.widgets.state(state); let widget_visuals = Widgets::dark();
let ws = WidgetStyle::default_style(classes, state, base); let spacing = Spacing::default();
let widget_visuals = match state {
WidgetState::Noninteractive => widget_visuals.noninteractive,
WidgetState::Inactive => widget_visuals.inactive,
WidgetState::Hovered => widget_visuals.hovered,
WidgetState::Active => widget_visuals.active,
};
let ws = WidgetStyle::default_style(classes, state);
Self { Self {
frame: Frame::new(), frame: Frame::new(),
checkbox_size: base.spacing.icon_width, checkbox_size: spacing.icon_width,
check_size: base.spacing.icon_width_inner, check_size: spacing.icon_width_inner,
checkbox_frame: Frame { checkbox_frame: Frame {
fill: visuals.bg_fill, fill: widget_visuals.bg_fill,
corner_radius: visuals.corner_radius, corner_radius: widget_visuals.corner_radius,
stroke: visuals.bg_stroke, stroke: widget_visuals.bg_stroke,
..Default::default() ..Default::default()
}, },
text_style: ws.text, text_style: ws.text,

View File

@@ -1,7 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use eframe::egui::{ use eframe::egui::{
Color32, Style, Color32,
theme_plugin::{ThemeCache, ThemeStyle}, theme_plugin::{ThemeCache, ThemeStyle},
widget_style::{ widget_style::{
ButtonStyle, Classes, HasClasses as _, StyleStruct as _, WidgetState, WidgetStyle, ButtonStyle, Classes, HasClasses as _, StyleStruct as _, WidgetState, WidgetStyle,
@@ -78,17 +78,19 @@ impl ESSEngine {
} }
} }
/// This implementation basically do nothing. This is only the minimum requirement with caching.
impl ThemeStyle<WidgetStyle> for ESSEngine { impl ThemeStyle<WidgetStyle> for ESSEngine {
fn style(&mut self, classes: &Classes, state: WidgetState, base: &Style) -> WidgetStyle { fn style(&mut self, classes: &Classes, state: WidgetState) -> WidgetStyle {
self.cache self.cache.get(classes, state, || {
.get(classes, state, || base.widget_style(classes, state)) WidgetStyle::default_style(classes, state)
})
} }
} }
impl ThemeStyle<ButtonStyle> for ESSEngine { impl ThemeStyle<ButtonStyle> for ESSEngine {
fn style(&mut self, classes: &Classes, state: WidgetState, base: &Style) -> ButtonStyle { fn style(&mut self, classes: &Classes, state: WidgetState) -> ButtonStyle {
self.cache.get(classes, state, || { self.cache.get(classes, state, || {
let mut default = ButtonStyle::default_style(classes, state, base); let mut default = ButtonStyle::default_style(classes, state);
for classe in classes.list() { for classe in classes.list() {
if let Some(properties) = self.info.get(&classe.to_string()) { if let Some(properties) = self.info.get(&classe.to_string()) {
for (property, value) in properties { for (property, value) in properties {

View File

@@ -53,12 +53,10 @@ fn main() -> eframe::Result {
if ui.text_edit_multiline(&mut style_code).changed() if ui.text_edit_multiline(&mut style_code).changed()
&& let Ok(engine) = ESSEngine::try_parse(&style_code) && let Ok(engine) = ESSEngine::try_parse(&style_code)
{ {
// Overwrite the current theme with the new one.clear
ui.replace_theme::<WidgetStyle>(engine.clone()); ui.replace_theme::<WidgetStyle>(engine.clone());
ui.replace_theme::<ButtonStyle>(engine); ui.replace_theme::<ButtonStyle>(engine);
} }
// Should find a way to detect if a change is made on a plugin
// Maybe by saving the plugin in the system instead and invalidating the cache when it's pulled as mut ?
}); });
}); });