1#[derive(Clone, Debug, Default, PartialEq)]
20pub struct TextAreaResponse {
21 pub changed: bool,
23 pub text: String,
25 pub supported: bool,
27 pub focused: bool,
29 pub cursor_pos: (usize, usize),
31}
32
33impl TextAreaResponse {
34 pub fn unsupported() -> Self {
37 Self {
38 changed: false,
39 text: String::new(),
40 supported: false,
41 focused: false,
42 cursor_pos: (0, 0),
43 }
44 }
45
46 pub fn supported(text: impl Into<String>, changed: bool, cursor_pos: (usize, usize)) -> Self {
53 Self {
54 changed,
55 text: text.into(),
56 supported: true,
57 focused: false,
58 cursor_pos,
59 }
60 }
61
62 pub fn supported_focused(
64 text: impl Into<String>,
65 changed: bool,
66 cursor_pos: (usize, usize),
67 focused: bool,
68 ) -> Self {
69 Self {
70 changed,
71 text: text.into(),
72 supported: true,
73 focused,
74 cursor_pos,
75 }
76 }
77}
78
79#[derive(Clone, Debug, Default, PartialEq)]
81pub struct TextInputResponse {
82 pub changed: bool,
84 pub text: String,
86 pub supported: bool,
88 pub focused: bool,
97}
98
99impl TextInputResponse {
100 pub fn unsupported() -> Self {
103 Self {
104 changed: false,
105 text: String::new(),
106 supported: false,
107 focused: false,
108 }
109 }
110
111 pub fn supported(text: impl Into<String>, changed: bool) -> Self {
116 Self {
117 changed,
118 text: text.into(),
119 supported: true,
120 focused: false,
121 }
122 }
123
124 pub fn supported_focused(text: impl Into<String>, changed: bool, focused: bool) -> Self {
126 Self {
127 changed,
128 text: text.into(),
129 supported: true,
130 focused,
131 }
132 }
133}
134
135#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
137pub struct CheckboxResponse {
138 pub changed: bool,
140 pub checked: bool,
142 pub supported: bool,
144}
145
146impl CheckboxResponse {
147 pub fn unsupported() -> Self {
149 Self {
150 changed: false,
151 checked: false,
152 supported: false,
153 }
154 }
155
156 pub fn supported(checked: bool, changed: bool) -> Self {
158 Self {
159 changed,
160 checked,
161 supported: true,
162 }
163 }
164}
165
166#[derive(Clone, Copy, Debug, Default, PartialEq)]
168pub struct SliderResponse {
169 pub changed: bool,
171 pub value: f64,
173 pub supported: bool,
175}
176
177impl SliderResponse {
178 pub fn unsupported() -> Self {
180 Self {
181 changed: false,
182 value: 0.0,
183 supported: false,
184 }
185 }
186
187 pub fn supported(value: f64, changed: bool) -> Self {
189 Self {
190 changed,
191 value,
192 supported: true,
193 }
194 }
195}
196
197#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
199pub struct DropdownResponse {
200 pub changed: bool,
202 pub selected: usize,
204 pub supported: bool,
206}
207
208impl DropdownResponse {
209 pub fn unsupported() -> Self {
211 Self {
212 changed: false,
213 selected: 0,
214 supported: false,
215 }
216 }
217
218 pub fn supported(selected: usize, changed: bool) -> Self {
220 Self {
221 changed,
222 selected,
223 supported: true,
224 }
225 }
226}
227
228#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
233pub struct WidgetResponse {
234 pub supported: bool,
236}
237
238impl WidgetResponse {
239 pub fn unsupported() -> Self {
241 Self { supported: false }
242 }
243
244 pub fn supported() -> Self {
246 Self { supported: true }
247 }
248}
249
250#[cfg(test)]
251mod tests {
252 use super::*;
253
254 #[test]
255 fn unsupported_constructors_set_flag_false() {
256 assert!(!TextInputResponse::unsupported().supported);
257 assert!(!TextAreaResponse::unsupported().supported);
258 assert!(!CheckboxResponse::unsupported().supported);
259 assert!(!SliderResponse::unsupported().supported);
260 assert!(!DropdownResponse::unsupported().supported);
261 assert!(!WidgetResponse::unsupported().supported);
262 }
263
264 #[test]
265 fn unsupported_payloads_are_zeroed() {
266 assert_eq!(TextInputResponse::unsupported().text, "");
267 assert!(!TextInputResponse::unsupported().changed);
268 let ta = TextAreaResponse::unsupported();
269 assert_eq!(ta.text, "");
270 assert!(!ta.changed);
271 assert_eq!(ta.cursor_pos, (0, 0));
272 assert!(!CheckboxResponse::unsupported().checked);
273 assert_eq!(SliderResponse::unsupported().value, 0.0);
274 assert_eq!(DropdownResponse::unsupported().selected, 0);
275 }
276
277 #[test]
278 fn supported_constructors_carry_payload() {
279 let t = TextInputResponse::supported("hi", true);
280 assert!(t.supported && t.changed && t.text == "hi");
281 let ta = TextAreaResponse::supported("hello\nworld", true, (1, 3));
282 assert!(ta.supported && ta.changed);
283 assert_eq!(ta.text, "hello\nworld");
284 assert_eq!(ta.cursor_pos, (1, 3));
285 let taf = TextAreaResponse::supported_focused("txt", false, (0, 1), true);
286 assert!(taf.supported && taf.focused);
287 let c = CheckboxResponse::supported(true, true);
288 assert!(c.supported && c.checked && c.changed);
289 let s = SliderResponse::supported(0.5, false);
290 assert!(s.supported && !s.changed && (s.value - 0.5).abs() < 1e-9);
291 let d = DropdownResponse::supported(3, true);
292 assert!(d.supported && d.changed && d.selected == 3);
293 assert!(WidgetResponse::supported().supported);
294 }
295
296 #[test]
297 fn defaults_match_unsupported_for_flag() {
298 assert_eq!(
300 CheckboxResponse::default().supported,
301 CheckboxResponse::unsupported().supported
302 );
303 assert_eq!(WidgetResponse::default(), WidgetResponse::unsupported());
304 }
305
306 #[test]
308 fn text_area_response_supported_false_by_default() {
309 let r = TextAreaResponse::default();
310 assert!(!r.supported);
311 assert_eq!(r.cursor_pos, (0, 0));
312 }
313
314 #[test]
315 fn text_area_response_cursor_pos_preserved() {
316 let r = TextAreaResponse::supported("line1\nline2", false, (1, 4));
317 assert_eq!(r.cursor_pos, (1, 4));
318 }
319
320 #[test]
321 fn text_area_response_focused_flag() {
322 let unfocused = TextAreaResponse::supported("x", false, (0, 0));
323 assert!(!unfocused.focused);
324 let focused = TextAreaResponse::supported_focused("x", false, (0, 0), true);
325 assert!(focused.focused);
326 }
327}