Skip to main content

cloudiful_bevy_settings/
schema.rs

1#[derive(Debug, Clone)]
2pub struct SettingFieldSpec<AppAction, FieldKey, TextKey> {
3    pub label: String,
4    pub label_key: Option<TextKey>,
5    pub control: SettingControlSpec<AppAction, FieldKey>,
6}
7
8#[derive(Debug, Clone)]
9pub struct SettingSelectOption<Action> {
10    pub text: String,
11    pub action: Action,
12    pub disabled: bool,
13}
14
15#[derive(Debug, Clone)]
16pub struct SettingSliderSpec<Action> {
17    pub value: f32,
18    pub min: f32,
19    pub max: f32,
20    pub step: f32,
21    pub precision: i32,
22    pub suffix: String,
23    pub action: fn(f32) -> Action,
24}
25
26impl<Action> SettingSliderSpec<Action> {
27    pub fn new(
28        value: f32,
29        min: f32,
30        max: f32,
31        step: f32,
32        precision: i32,
33        suffix: impl Into<String>,
34        action: fn(f32) -> Action,
35    ) -> Self {
36        Self {
37            value,
38            min,
39            max,
40            step,
41            precision,
42            suffix: suffix.into(),
43            action,
44        }
45    }
46}
47
48#[derive(Debug, Clone)]
49pub enum SettingControlSpec<Action, FieldKey> {
50    Toggle {
51        text: String,
52        action: Action,
53    },
54    Stepper {
55        key: FieldKey,
56        value: String,
57        decrease_action: Option<Action>,
58        increase_action: Option<Action>,
59        slider: Option<SettingSliderSpec<Action>>,
60    },
61    Select {
62        key: FieldKey,
63        value: String,
64        options: Vec<SettingSelectOption<Action>>,
65    },
66}
67
68impl<Action, FieldKey, TextKey> SettingFieldSpec<Action, FieldKey, TextKey> {
69    pub fn toggle(label: impl Into<String>, text: String, action: Action) -> Self {
70        Self {
71            label: label.into(),
72            label_key: None,
73            control: SettingControlSpec::Toggle { text, action },
74        }
75    }
76
77    pub fn stepper(
78        label: impl Into<String>,
79        key: FieldKey,
80        value: String,
81        decrease_action: Option<Action>,
82        increase_action: Option<Action>,
83    ) -> Self {
84        Self {
85            label: label.into(),
86            label_key: None,
87            control: SettingControlSpec::Stepper {
88                key,
89                value,
90                decrease_action,
91                increase_action,
92                slider: None,
93            },
94        }
95    }
96
97    pub fn select(
98        label: impl Into<String>,
99        key: FieldKey,
100        value: String,
101        options: Vec<SettingSelectOption<Action>>,
102    ) -> Self {
103        Self {
104            label: label.into(),
105            label_key: None,
106            control: SettingControlSpec::Select {
107                key,
108                value,
109                options,
110            },
111        }
112    }
113
114    pub fn with_label_key(mut self, label_key: TextKey) -> Self {
115        self.label_key = Some(label_key);
116        self
117    }
118
119    pub fn with_slider(mut self, slider: SettingSliderSpec<Action>) -> Self {
120        if let SettingControlSpec::Stepper {
121            slider: slider_slot,
122            ..
123        } = &mut self.control
124        {
125            *slider_slot = Some(slider);
126        }
127        self
128    }
129}
130
131pub trait SettingFieldSource<AppAction, Context, FieldKey, TextKey> {
132    fn field_specs(&self, context: &Context)
133    -> Vec<SettingFieldSpec<AppAction, FieldKey, TextKey>>;
134}
135
136#[cfg(test)]
137mod tests {
138    use super::SettingSliderSpec;
139
140    fn slider_action(value: f32) -> u32 {
141        value.round() as u32
142    }
143
144    #[test]
145    fn slider_spec_new_preserves_fields() {
146        let spec = SettingSliderSpec::new(42.0, 0.0, 100.0, 5.0, 1, "%", slider_action);
147
148        assert_eq!(spec.value, 42.0);
149        assert_eq!(spec.min, 0.0);
150        assert_eq!(spec.max, 100.0);
151        assert_eq!(spec.step, 5.0);
152        assert_eq!(spec.precision, 1);
153        assert_eq!(spec.suffix, "%");
154        assert_eq!((spec.action)(12.4), 12);
155    }
156}