#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct StateOverlay {
pub hovered: bool,
pub pressed: bool,
pub focused: bool,
pub checked: bool,
}
impl StateOverlay {
pub fn from_base(hovered: bool, pressed: bool, focused: bool) -> Self {
Self { hovered, pressed, focused, checked: false }
}
pub fn is_empty(&self) -> bool {
!(self.hovered || self.pressed || self.focused || self.checked)
}
pub fn fill_blend(&self) -> f32 {
if self.pressed {
0.12
} else if self.hovered {
0.08
} else {
0.0
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, PartialOrd, Ord)]
pub enum SemanticState {
#[default]
None,
Error,
Warning,
Success,
}
impl SemanticState {
pub fn state_suffix(self) -> Option<&'static str> {
match self {
Self::None => None,
Self::Error => Some("error"),
Self::Warning => Some("warning"),
Self::Success => Some("success"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, PartialOrd, Ord)]
pub enum WidgetState {
#[default]
Normal,
Hover,
Pressed,
Focused,
Disabled,
Checked,
Selected,
Active,
Inactive,
Error,
Warning,
Success,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ThemeMode {
#[default]
Light,
Dark,
Auto,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_default_semantic_state_is_no_meaning() {
assert_eq!(SemanticState::default(), SemanticState::None);
}
#[test]
fn each_meaning_addresses_a_theme_key() {
assert_eq!(SemanticState::None.state_suffix(), None);
assert_eq!(SemanticState::Error.state_suffix(), Some("error"));
assert_eq!(SemanticState::Warning.state_suffix(), Some("warning"));
assert_eq!(SemanticState::Success.state_suffix(), Some("success"));
}
#[test]
fn the_semantic_widget_states_are_still_present() {
let _ = [WidgetState::Error, WidgetState::Warning, WidgetState::Success];
}
#[test]
fn overlay_carries_simultaneous_states() {
let overlay = StateOverlay::from_base(true, false, true);
assert!(overlay.hovered && overlay.focused, "focused and hovered at once");
assert!(!overlay.is_empty());
assert_eq!(overlay.fill_blend(), 0.08, "a hover is the lighter step");
}
#[test]
fn overlay_fill_blend_follows_press_over_hover() {
let pressed = StateOverlay { pressed: true, hovered: true, ..StateOverlay::default() };
assert_eq!(pressed.fill_blend(), 0.12, "a press is the firmer step");
assert_eq!(StateOverlay::default().fill_blend(), 0.0);
assert!(StateOverlay::default().is_empty());
}
}