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}