1use gpui::{Refineable as _, StyleRefinement, Styled, prelude::FluentBuilder};
2
3#[derive(Default)]
9pub struct StateStyle {
10 refinement: StyleRefinement,
11}
12
13impl StateStyle {
14 pub(crate) fn into_refinement(self) -> StyleRefinement {
15 self.refinement
16 }
17}
18
19impl Styled for StateStyle {
20 fn style(&mut self) -> &mut StyleRefinement {
21 &mut self.refinement
22 }
23}
24
25impl FluentBuilder for StateStyle {}
26
27pub(crate) fn resolve_style<'a>(
44 instance: &StyleRefinement,
45 active_states: impl IntoIterator<Item = &'a StyleRefinement>,
46) -> StyleRefinement {
47 let mut style = StyleRefinement::default();
48 style.refine(instance);
49 for state in active_states {
50 style.refine(state);
51 }
52 style
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 fn state(build: impl FnOnce(StateStyle) -> StateStyle) -> StyleRefinement {
60 build(StateStyle::default()).into_refinement()
61 }
62
63 #[test]
64 fn instance_style_is_the_baseline_when_no_state_is_active() {
65 let instance = state(|style| style.opacity(0.9));
66
67 let resolved = resolve_style(&instance, []);
68
69 assert_eq!(resolved.opacity, Some(0.9));
70 }
71
72 #[test]
73 fn an_active_state_overrides_the_instance_style() {
74 let instance = state(|style| style.opacity(0.9));
75 let checked = state(|style| style.opacity(0.8));
76
77 let resolved = resolve_style(&instance, [&checked]);
78
79 assert_eq!(resolved.opacity, Some(0.8));
80 }
81
82 #[test]
83 fn later_states_override_earlier_states() {
84 let instance = state(|style| style.opacity(0.9));
85 let checked = state(|style| style.opacity(0.8));
86 let disabled = state(|style| style.opacity(0.5));
87
88 let resolved = resolve_style(&instance, [&checked, &disabled]);
89
90 assert_eq!(resolved.opacity, Some(0.5));
91 }
92
93 #[test]
94 fn states_only_override_the_fields_they_set() {
95 let instance = state(|style| style.opacity(0.9).border_1());
96 let disabled = state(|style| style.opacity(0.5));
97
98 let resolved = resolve_style(&instance, [&disabled]);
99
100 assert_eq!(resolved.opacity, Some(0.5));
101 assert_eq!(instance.border_widths, resolved.border_widths);
102 }
103}