diff --git a/Cargo.lock b/Cargo.lock index d131126e1..800618e4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4248,14 +4248,6 @@ dependencies = [ "float-cmp", ] -[[package]] -name = "styling_engine" -version = "0.1.0" -dependencies = [ - "eframe", - "env_logger", -] - [[package]] name = "subtle" version = "2.6.1" diff --git a/crates/egui/src/ui.rs b/crates/egui/src/ui.rs index 096e558bf..2c10f199b 100644 --- a/crates/egui/src/ui.rs +++ b/crates/egui/src/ui.rs @@ -140,7 +140,7 @@ impl Ui { let disabled = disabled || invisible; let style = style.unwrap_or_else(|| ctx.global_style()); let sense = sense.unwrap_or_else(Sense::hover); - let classes = classes.unwrap_or_default().with_class(ROOT_CLASS); + let classes = classes.with_class(ROOT_CLASS); let placer = Placer::new(max_rect, layout); let ui_stack = UiStack { @@ -284,7 +284,6 @@ impl Ui { let sizing_pass = self.sizing_pass || sizing_pass; let style = style.unwrap_or_else(|| Arc::clone(&self.style)); let sense = sense.unwrap_or_else(Sense::hover); - let classes = classes.unwrap_or_default(); if sizing_pass { // During the sizing pass we want widgets to use up as little space as possible, diff --git a/crates/egui/src/ui_builder.rs b/crates/egui/src/ui_builder.rs index 0618fb8cc..a8121e235 100644 --- a/crates/egui/src/ui_builder.rs +++ b/crates/egui/src/ui_builder.rs @@ -2,6 +2,7 @@ use std::{hash::Hash, sync::Arc}; #[expect(unused_imports)] // Used for doclinks use crate::Ui; +use crate::widget_style::HasClasses; use crate::{ClosableTag, widget_style::Classes}; use crate::{Id, LayerId, Layout, Rect, Sense, Style, UiStackInfo}; @@ -25,7 +26,7 @@ pub struct UiBuilder { pub style: Option>, pub sense: Option, pub accessibility_parent: Option, - pub classes: Option, + pub classes: Classes, } impl UiBuilder { @@ -192,11 +193,14 @@ impl UiBuilder { self.accessibility_parent = Some(parent_id); self } +} - /// Set classes for this [`Ui`]. - #[inline] - pub fn classes(mut self, classes: Classes) -> Self { - self.classes = Some(classes); - self +impl HasClasses for UiBuilder { + fn classes(&self) -> &Classes { + &self.classes + } + + fn classes_mut(&mut self) -> &mut Classes { + &mut self.classes } } diff --git a/crates/egui/src/ui_stack.rs b/crates/egui/src/ui_stack.rs index 15adb8e30..4263e9e3e 100644 --- a/crates/egui/src/ui_stack.rs +++ b/crates/egui/src/ui_stack.rs @@ -202,7 +202,7 @@ impl UiTags { /// Note: since [`UiStack`] contains a reference to its parent, it is both a stack, and a node within /// that stack. Most of its methods are about the specific node, but some methods walk up the /// hierarchy to provide information about the entire stack. -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct UiStack { // stuff that `Ui::child_ui` can deal with directly pub id: Id, diff --git a/crates/egui/src/widget_style.rs b/crates/egui/src/widget_style.rs index 300cb3761..80e88cda6 100644 --- a/crates/egui/src/widget_style.rs +++ b/crates/egui/src/widget_style.rs @@ -2,6 +2,7 @@ use std::{borrow::Cow, fmt}; use emath::Vec2; use epaint::{Color32, FontId, Shadow, Stroke, text::TextWrapMode}; +use smallvec::SmallVec; use crate::{ Frame, Response, Style, TextBuffer as _, TextStyle, @@ -219,13 +220,14 @@ impl Style { /// The root class is present on every top-level ui pub const ROOT_CLASS: &str = "root"; +pub const SELECTED_CLASS: &str = "selected"; pub type ClassName = Cow<'static, str>; /// The classes assigned to a widget #[derive(Debug, Default, Clone)] pub struct Classes { - classes: Vec, + classes: SmallVec<[ClassName; 5]>, } impl Classes { diff --git a/crates/egui/src/widgets/button.rs b/crates/egui/src/widgets/button.rs index 107bcd82c..48dbb98ff 100644 --- a/crates/egui/src/widgets/button.rs +++ b/crates/egui/src/widgets/button.rs @@ -4,7 +4,7 @@ use crate::{ Atom, AtomExt as _, AtomKind, AtomLayout, AtomLayoutResponse, Color32, CornerRadius, Frame, Image, IntoAtoms, NumExt as _, Response, Sense, Stroke, TextStyle, TextWrapMode, Ui, Vec2, Widget, WidgetInfo, WidgetText, WidgetType, - widget_style::{ButtonStyle, Classes, HasClasses, WidgetState}, + widget_style::{ButtonStyle, Classes, HasClasses, SELECTED_CLASS, WidgetState}, }; /// Clickable button with text. @@ -308,7 +308,7 @@ impl<'a> Button<'a> { let response: Option = ui.ctx().read_response(id); let state = response.map(|r| r.widget_state()).unwrap_or_default(); - classes.add_class_if("selected", selected); + classes.add_class_if(SELECTED_CLASS, selected); let ButtonStyle { frame, text_style } = ui.style().button_style(&classes, state); diff --git a/examples/styling_engine/Cargo.toml b/examples/styling_engine/Cargo.toml deleted file mode 100644 index 19cec8ae9..000000000 --- a/examples/styling_engine/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "styling_engine" -version = "0.1.0" -authors = ["Emil Ernerfeldt "] -license = "MIT OR Apache-2.0" -edition = "2024" -rust-version = "1.92" -publish = false - -[lints] -workspace = true - - -[dependencies] -eframe = { workspace = true, features = [ - "default", - "__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO -] } -env_logger = { workspace = true, features = ["auto-color", "humantime"] } diff --git a/examples/styling_engine/README.md b/examples/styling_engine/README.md deleted file mode 100644 index d066d3960..000000000 --- a/examples/styling_engine/README.md +++ /dev/null @@ -1,7 +0,0 @@ -Example showing how the style engine work. - -```sh -cargo run -p styling_engine -``` - -![](screenshot.png) diff --git a/examples/styling_engine/screenshot.png b/examples/styling_engine/screenshot.png deleted file mode 100644 index 0d27bc056..000000000 --- a/examples/styling_engine/screenshot.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7cde6a351fbcf5a5d3b5474353c627a9c93801563880b7ff41dfa025da3c6d37 -size 8587 diff --git a/examples/styling_engine/src/main.rs b/examples/styling_engine/src/main.rs deleted file mode 100644 index 4a2ee6dc7..000000000 --- a/examples/styling_engine/src/main.rs +++ /dev/null @@ -1,75 +0,0 @@ -#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release -#![expect(rustdoc::missing_crate_level_docs)] // it's an example - -use eframe::egui::{ - self, Frame, Grid, Margin, Panel, UiBuilder, - widget_style::{Classes, HasClasses as _}, -}; - -fn main() -> eframe::Result { - env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`). - - let options = eframe::NativeOptions { - viewport: egui::ViewportBuilder::default().with_inner_size([600.0, 400.0]), - ..Default::default() - }; - - let mut style_code = "// future style code live editor".to_owned(); - - eframe::run_ui_native("My egui App", options, move |ui, _frame| { - ui.scope_builder( - UiBuilder::new().classes(Classes::default().with_class("body")), - |ui| { - ui.label("body"); - ui.label("central panel"); - - Panel::left("style_code").show_inside(ui, |ui| { - ui.scope_builder( - UiBuilder::new().classes(Classes::default().with_class("panel_left")), - |ui| { - ui.label("style code editor"); - - ui.text_edit_multiline(&mut style_code); - }, - ); - }); - - Grid::new("grid").show(ui, |ui| { - ui.scope_builder( - UiBuilder::new().classes(Classes::default().with_class("grid")), - |ui| { - Frame::new().inner_margin(Margin::same(10)).show(ui, |ui| { - ui.scope_builder( - UiBuilder::new() - .classes(Classes::default().with_class("frame1")), - |ui| { - let mut parent = Some(ui.stack()); - let mut text = vec![]; - let mut i: i32 = 0; - while let Some(p) = parent { - text.push(format!( - "{}{}class : '{}', kind : {:?}", - " ".repeat( - (2 * 0_i32.max(i - 1) + 1.min(i)) as usize - ), - if i > 0 { "\\- " } else { "" }, - p.classes, - p.kind() - )); - i += 1; - parent = p.parent.as_ref(); - } - ui.label(format!( - "Current hierarchy (child to root):\n{}", - text.join("\n") - )); - }, - ) - }) - }, - ); - }); - }, - ); - }) -}