The expansion/stroke correction on a widget's margins was written out by
hand. Move it into `Frame::expand_in_place`, which knows the frame's own
stroke width, so a caller states the intent instead of the arithmetic.
`Frame::invisible` goes with it: a frame that keeps its layout but drops
its paint.
Two fixes fall out of it in the button style:
* A small button zeroed its vertical padding after the correction, which
left the frame a `stroke.width - expansion` tall. Zeroing before the
correction makes it exactly zero in every state, which is what "must
not add any height" means.
* The invisible frame of a button that hides its frame when inactive
dropped the outer margin and the stroke width, so it was not, in fact,
as big as the painted one. It now keeps the whole frame and only drops
the paint.
Also give `TextVisuals` a `new` and a `from_widget_visuals`, replacing the
local `text_visuals` helper, and add `HasClasses::add_classes` and
`HasClasses::with_classes`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/main/CONTRIBUTING.md)
before opening a Pull Request!
* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.
Please be patient! I will review your PR, but my time is limited!
-->
# What it does
Addition of a new system of theme plugins which allow the user to use
different rules engine to compute the style for the available
specialised widget style.
# How to use
Create a engine implementing the trait `ThemePlugin` and `ThemeStyle<S:
StyleStruct>` and implement the necessary methods, then register this
way (example for `ButtonStyle`):
```ui.add_theme::<ButtonStyle>(&mycustomengine);```
Now all button will call the `ThemeStyle<ButtonStyle>` method to compute the correct style and later use the cached value to avoid the costly computation.
If no valid `ThemeStyle<S>` or engine is available then it fallback to the default style.
* Closes part of <https://github.com/emilk/egui/issues/3284>
* [x] I have followed the instructions in the PR template
---------
Co-authored-by: adrien <221212@umons.ac.be>
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Lucas Meurer <hi@lucasmerlin.me>