mirror of
https://github.com/emilk/egui.git
synced 2026-08-29 04:40:03 -04:00
Add some more helpers
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
use core::{any::Any, iter::FusedIterator};
|
use core::{any::Any, iter::FusedIterator};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::widget_style::Classes;
|
use crate::widget_style::{ClassName, Classes, HasClasses as _};
|
||||||
use epaint::Color32;
|
use epaint::Color32;
|
||||||
|
|
||||||
use crate::{Direction, Frame, Id, Rect};
|
use crate::{Direction, Frame, Id, Rect};
|
||||||
@@ -290,6 +290,21 @@ impl UiStack {
|
|||||||
pub fn contained_in(&self, kind: UiKind) -> bool {
|
pub fn contained_in(&self, kind: UiKind) -> bool {
|
||||||
self.iter().any(|frame| frame.kind() == Some(kind))
|
self.iter().any(|frame| frame.kind() == Some(kind))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Does this node, or any [`crate::Ui`] up the stack, carry this class?
|
||||||
|
pub fn has_class(&self, class: impl Into<ClassName>) -> bool {
|
||||||
|
let class = class.into();
|
||||||
|
self.iter().any(|node| node.classes.has(class.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read a value from the classes up the stack, nearest node first.
|
||||||
|
///
|
||||||
|
/// This is how an inherited property works in a stylesheet: a container states it once, and
|
||||||
|
/// everything inside picks it up. The nearest [`crate::Ui`] wins, so an inner container can
|
||||||
|
/// override an outer one.
|
||||||
|
pub fn inherited<T>(&self, from_classes: impl Fn(&Classes) -> Option<T>) -> Option<T> {
|
||||||
|
self.iter().find_map(|node| from_classes(&node.classes))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -121,4 +121,15 @@ pub trait HasClasses {
|
|||||||
fn as_slice(&self) -> &[ClassName] {
|
fn as_slice(&self) -> &[ClassName] {
|
||||||
&self.classes().classes
|
&self.classes().classes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The last class that names a `T`, if any.
|
||||||
|
///
|
||||||
|
/// Scanning backwards is what makes the last class win, so a widget given two classes of the
|
||||||
|
/// same kind takes the one set last — the way a later stylesheet rule overrides an earlier one.
|
||||||
|
fn last_class<T>(&self, from_class_name: impl Fn(&str) -> Option<T>) -> Option<T> {
|
||||||
|
self.as_slice()
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.find_map(|class| from_class_name(class))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use emath::Vec2;
|
|||||||
use epaint::{Color32, FontId, Stroke, text::TextWrapMode};
|
use epaint::{Color32, FontId, Stroke, text::TextWrapMode};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Context, Frame, Response, Style, UiStack,
|
Context, Frame, Response, Style, TextStyle, UiStack,
|
||||||
style::{WidgetVisuals, Widgets},
|
style::{WidgetVisuals, Widgets},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -35,6 +35,24 @@ pub struct TextVisuals {
|
|||||||
pub strikethrough: Stroke,
|
pub strikethrough: Stroke,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TextVisuals {
|
||||||
|
/// The undecorated body text of a [`Style`], as a starting point for a widget's own text.
|
||||||
|
///
|
||||||
|
/// The color is the style's ordinary text color; a widget that paints its text in a color of
|
||||||
|
/// its own overrides it.
|
||||||
|
pub fn from_style(style: &Style) -> Self {
|
||||||
|
Self {
|
||||||
|
color: style.visuals.text_color(),
|
||||||
|
font_id: style
|
||||||
|
.override_font_id
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| TextStyle::Body.resolve(style)),
|
||||||
|
underline: Stroke::NONE,
|
||||||
|
strikethrough: Stroke::NONE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// General widget style
|
/// General widget style
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct BaseStyle {
|
pub struct BaseStyle {
|
||||||
@@ -176,3 +194,22 @@ pub struct StyleArgs<'a> {
|
|||||||
pub style: &'a Style,
|
pub style: &'a Style,
|
||||||
pub ctx: &'a Context,
|
pub ctx: &'a Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl StyleArgs<'_> {
|
||||||
|
/// Does the widget, or any [`crate::Ui`] it sits in, carry this class?
|
||||||
|
///
|
||||||
|
/// This is the equivalent of a descendant selector (`.parent .child`): it lets a container
|
||||||
|
/// style everything inside it without having to touch each widget. Use
|
||||||
|
/// [`HasClasses::has`] on [`Self::classes`] instead for a class only ever set on a widget.
|
||||||
|
pub fn has_class(&self, class: impl Into<ClassName>) -> bool {
|
||||||
|
let class = class.into();
|
||||||
|
self.classes.has(class.clone()) || self.stack.has_class(class)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read a value from the widget's own classes, falling back to the [`crate::Ui`]s it sits in.
|
||||||
|
///
|
||||||
|
/// See [`UiStack::inherited`] for how the fallback resolves.
|
||||||
|
pub fn inherited<T>(&self, from_classes: impl Fn(&Classes) -> Option<T>) -> Option<T> {
|
||||||
|
from_classes(self.classes).or_else(|| self.stack.inherited(from_classes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user