tuix_widgets/inputs/
vector_edit.rs

1use crate::common::*;
2use crate::{Dropdown, DropdownEvent, Textbox, TextboxEvent};
3use crate::AnimationState;
4
5#[derive(Debug, Clone, PartialEq)]
6pub enum VectorEditEvent<T> {
7    ValueChanged(T, T, T, T),
8    Dim1(T),
9    Dim2(T, T),
10    Dim3(T, T, T),
11    Dim4(T, T, T, T),
12}
13
14pub struct Dimension {
15    text: String,
16    pressed: bool,
17}
18
19impl Dimension {
20    pub fn new(text: &str) -> Self {
21        Dimension {
22            text: text.to_string(),
23            pressed: false,
24        }
25    }
26}
27
28impl Widget for Dimension {
29    type Ret = Entity;
30    type Data = ();
31    fn on_build(&mut self, state: &mut State, entity: Entity) -> Self::Ret {
32        entity
33            .set_text(state, &self.text)
34            .set_child_space(state, Stretch(1.0))
35    }
36
37    fn on_event(&mut self, state: &mut State, entity: Entity, event: &mut Event) {
38        if let Some(window_event) = event.message.downcast::<WindowEvent>() {
39            match window_event {
40                WindowEvent::MouseDown(button) => {
41                    if *button == MouseButton::Left {
42                        if entity == event.target {
43                            self.pressed = true;
44                            // println!("Send Change Event");
45                            // state.insert_event(
46                            //     Event::new(DropdownEvent::SetText(self.text.clone()))
47                            //         .target(entity)
48                            //         .propagate(Propagation::Up),
49                            // );
50                        }
51                    }
52                }
53
54                WindowEvent::MouseUp(button) => {
55                    if *button == MouseButton::Left {
56                        if self.pressed {
57                            self.pressed = false;
58                            //self.checkbox.set_checked(state, true);
59                            // println!("Send Change Event");
60                            state.insert_event(
61                                Event::new(DropdownEvent::SetText(self.text.clone()))
62                                    .target(entity)
63                                    .propagate(Propagation::Up),
64                            );
65                        }
66                    }
67                }
68
69                _ => {}
70            }
71        }
72    }
73}
74
75pub struct VectorEdit<T> {
76    // Subwidgets
77    textbox_x: Entity,
78    textbox_y: Entity,
79    textbox_z: Entity,
80    textbox_w: Entity,
81    dims: Entity,
82
83    // Animations
84    reveal: Animation,
85    hide: Animation,
86    grow: Animation,
87    shrink: Animation,
88
89    // Data
90    pub x: T,
91    pub y: T,
92    pub z: T,
93    pub w: T,
94    pub num_of_dims: u8,
95
96    // Callbacks
97    on_change: Option<Box<dyn Fn(&mut Self, &mut State, Entity)>>,
98}
99
100impl<T> VectorEdit<T>
101where
102    T: 'static
103        + Default
104        + std::fmt::Debug
105        + std::fmt::Display
106        + Copy
107        + PartialEq
108        + std::str::FromStr,
109{
110    pub fn new() -> Self {
111        VectorEdit {
112            textbox_x: Entity::null(),
113            textbox_y: Entity::null(),
114            textbox_z: Entity::null(),
115            textbox_w: Entity::null(),
116            dims: Entity::null(),
117
118            reveal: Animation::default(),
119            hide: Animation::default(),
120            grow: Animation::default(),
121            shrink: Animation::default(),
122
123            x: T::default(),
124            y: T::default(),
125            z: T::default(),
126            w: T::default(),
127            num_of_dims: 4,
128
129            on_change: None,
130        }
131    }
132
133    pub fn with_x(mut self, val: T) -> Self {
134        self.x = val;
135
136        self
137    }
138
139    pub fn with_y(mut self, val: T) -> Self {
140        self.y = val;
141
142        self
143    }
144
145    pub fn with_z(mut self, val: T) -> Self {
146        self.z = val;
147
148        self
149    }
150
151    pub fn with_w(mut self, val: T) -> Self {
152        self.w = val;
153
154        self
155    }
156
157    pub fn on_change<F>(mut self, message: F) -> Self
158    where
159        F: 'static + Fn(&mut Self, &mut State, Entity),
160    {
161        self.on_change = Some(Box::new(message));
162
163        self
164    }
165}
166
167impl<T> Widget for VectorEdit<T>
168where
169    T: 'static
170        + Default
171        + std::fmt::Debug
172        + std::fmt::Display
173        + Copy
174        + PartialEq
175        + std::str::FromStr,
176{
177    type Ret = Entity;
178    type Data = ();
179    fn on_build(&mut self, state: &mut State, entity: Entity) -> Self::Ret {
180        //state.add_theme(VEC_EDIT_STYLE);
181
182        entity.set_layout_type(state, LayoutType::Row);
183
184        self.textbox_x = Textbox::new(&self.x.to_string())
185            .build(state, entity, |builder| 
186                builder.set_right(Pixels(5.0))
187        );
188        self.textbox_y = Textbox::new(&self.y.to_string()).build(state, entity, |builder| {
189            builder.set_right(Pixels(5.0))
190        });
191        self.textbox_z = Textbox::new(&self.z.to_string()).build(state, entity, |builder| {
192            builder.set_right(Pixels(5.0))
193        });
194        self.textbox_w = Textbox::new(&self.w.to_string()).build(state, entity, |builder| {
195            builder.set_right(Pixels(5.0))
196        });
197
198        self.dims = Dropdown::<()>::new("4")
199            .build(state, entity, |builder| {
200                builder
201                    .set_width(Pixels(30.0))
202                    //.set_text_justify(Justify::End)
203                    .class("dim")
204            });
205
206        Dimension::new("1").build(state, self.dims, |builder| builder.class("item"));
207        Dimension::new("2").build(state, self.dims, |builder| builder.class("item"));
208        Dimension::new("3").build(state, self.dims, |builder| builder.class("item"));
209        Dimension::new("4").build(state, self.dims, |builder| builder.class("item"));
210
211        self.reveal = state.style.width.insert_animation(
212            AnimationState::new()
213                .with_duration(std::time::Duration::from_millis(100))
214                .with_keyframe((0.0, Stretch(0.0)))
215                .with_keyframe((1.0, Stretch(1.0))),
216        );
217
218        self.grow = state.style.right.insert_animation(
219            AnimationState::new()
220                .with_duration(std::time::Duration::from_millis(100))
221                .with_keyframe((0.0, Units::Pixels(0.0)))
222                .with_keyframe((1.0, Units::Pixels(5.0))),
223        );
224
225        self.shrink = state.style.right.insert_animation(
226            AnimationState::new()
227                .with_duration(std::time::Duration::from_millis(100))
228                .with_keyframe((0.0, Units::Pixels(5.0)))
229                .with_keyframe((1.0, Units::Pixels(0.0))),
230        );
231
232        self.hide = state.style.width.insert_animation(
233            AnimationState::new()
234                .with_duration(std::time::Duration::from_millis(100))
235                .with_keyframe((0.0, Stretch(1.0)))
236                .with_keyframe((1.0, Stretch(0.0))),
237        );
238
239        if let Some(callback) = self.on_change.take() {
240            (callback)(self, state, entity);
241            self.on_change = Some(callback);
242        }
243
244        entity.set_element(state, "vector_edit");
245
246        entity
247    }
248
249    fn on_event(&mut self, state: &mut State, entity: Entity, event: &mut Event) {
250        let target = event.target;
251
252        if let Some(dropdown_event) = event.message.downcast::<DropdownEvent>() {
253            match dropdown_event {
254                DropdownEvent::SetText(text) => match text.as_ref() {
255                    "1" => {
256                        if state.data.get_width(self.textbox_x) == 0.0 {
257                            state.style.width.play_animation(self.textbox_x, self.reveal);
258                            state.style.right.play_animation(self.textbox_x, self.grow);
259                        }
260
261                        if state.data.get_width(self.textbox_y) != 0.0 {
262                            state.style.width.play_animation(self.textbox_y, self.hide);
263                            state.style.right.play_animation(self.textbox_y, self.shrink);
264                        }
265
266                        if state.data.get_width(self.textbox_z) != 0.0 {
267                            state.style.width.play_animation(self.textbox_z, self.hide);
268                            state.style.right.play_animation(self.textbox_z, self.shrink);
269                        }
270
271                        if state.data.get_width(self.textbox_w) != 0.0 {
272                            state.style.width.play_animation(self.textbox_w, self.hide);
273                            state.style.right.play_animation(self.textbox_w, self.shrink);
274                        }
275
276                        self.textbox_x.set_width(state, Stretch(1.0));
277                        self.textbox_y.set_width(state, Stretch(0.0));
278                        self.textbox_z.set_width(state, Stretch(0.0));
279                        self.textbox_w.set_width(state, Stretch(0.0));
280
281                        self.textbox_x.set_right(state, Pixels(5.0));
282                        self.textbox_y.set_right(state, Pixels(0.0));
283                        self.textbox_z.set_right(state, Pixels(0.0));
284                        self.textbox_w.set_right(state, Pixels(0.0));
285
286                        self.num_of_dims = 1;
287
288                        state.insert_event(
289                            Event::new(VectorEditEvent::Dim1(self.x)).target(entity),
290                        );
291                    }
292
293                    "2" => {
294                        if state.data.get_width(self.textbox_x) == 0.0 {
295                            state.style.width.play_animation(self.textbox_x, self.reveal);
296                            state.style.right.play_animation(self.textbox_x, self.grow);
297                        }
298
299                        if state.data.get_width(self.textbox_y) == 0.0 {
300                            state.style.width.play_animation(self.textbox_y, self.reveal);
301                            state.style.right.play_animation(self.textbox_y, self.grow);
302                        }
303
304                        if state.data.get_width(self.textbox_z) != 0.0 {
305                            state.style.width.play_animation(self.textbox_z, self.hide);
306                            state.style.right.play_animation(self.textbox_z, self.shrink);
307                        }
308
309                        if state.data.get_width(self.textbox_w) != 0.0 {
310                            state.style.width.play_animation(self.textbox_w, self.hide);
311                            state.style.right.play_animation(self.textbox_w, self.shrink);
312                        }
313
314                        self.textbox_x.set_width(state, Stretch(1.0));
315                        self.textbox_y.set_width(state, Stretch(1.0));
316                        self.textbox_z.set_width(state, Stretch(0.0));
317                        self.textbox_w.set_width(state, Stretch(0.0));
318
319                        self.textbox_x.set_right(state, Units::Pixels(5.0));
320                        self.textbox_y.set_right(state, Units::Pixels(5.0));
321                        self.textbox_z.set_right(state, Units::Pixels(0.0));
322                        self.textbox_w.set_right(state, Units::Pixels(0.0));
323
324                        self.num_of_dims = 2;
325
326                        state.insert_event(
327                            Event::new(VectorEditEvent::Dim2(self.x, self.y)).target(entity),
328                        );
329                    }
330
331                    "3" => {
332                        if state.data.get_width(self.textbox_x) == 0.0 {
333                            state.style.width.play_animation(self.textbox_x, self.reveal);
334                            state.style.right.play_animation(self.textbox_x, self.grow);
335                        }
336
337                        if state.data.get_width(self.textbox_y) == 0.0 {
338                            state.style.width.play_animation(self.textbox_y, self.reveal);
339                            state.style.right.play_animation(self.textbox_y, self.grow);
340                        }
341
342                        if state.data.get_width(self.textbox_z) == 0.0 {
343                            state.style.width.play_animation(self.textbox_z, self.reveal);
344                            state.style.right.play_animation(self.textbox_z, self.grow);
345                        }
346
347                        if state.data.get_width(self.textbox_w) != 0.0 {
348                            state.style.width.play_animation(self.textbox_w, self.hide);
349                            state.style.right.play_animation(self.textbox_w, self.shrink);
350                        }
351
352                        self.textbox_x.set_width(state, Stretch(1.0));
353                        self.textbox_y.set_width(state, Stretch(1.0));
354                        self.textbox_z.set_width(state, Stretch(1.0));
355                        self.textbox_w.set_width(state, Stretch(0.0));
356
357                        self.textbox_x.set_right(state, Units::Pixels(5.0));
358                        self.textbox_y.set_right(state, Units::Pixels(5.0));
359                        self.textbox_z.set_right(state, Units::Pixels(5.0));
360                        self.textbox_w.set_right(state, Units::Pixels(0.0));
361
362                        self.num_of_dims = 3;
363
364                        state.insert_event(
365                            Event::new(VectorEditEvent::Dim3(self.x, self.y, self.z))
366                                .target(entity),
367                        );
368                    }
369
370                    "4" => {
371                        if state.data.get_width(self.textbox_x) == 0.0 {
372                            state.style.width.play_animation(self.textbox_x, self.reveal);
373                            state.style.right.play_animation(self.textbox_x, self.grow);
374                        }
375
376                        if state.data.get_width(self.textbox_y) == 0.0 {
377                            state.style.width.play_animation(self.textbox_y, self.reveal);
378                            state.style.right.play_animation(self.textbox_y, self.grow);
379                        }
380
381                        if state.data.get_width(self.textbox_z) == 0.0 {
382                            state.style.width.play_animation(self.textbox_z, self.reveal);
383                            state.style.right.play_animation(self.textbox_z, self.grow);
384                        }
385
386                        if state.data.get_width(self.textbox_w) == 0.0 {
387                            state.style.width.play_animation(self.textbox_w, self.reveal);
388                            state.style.right.play_animation(self.textbox_w, self.grow);
389                        }
390
391                        self.textbox_x.set_width(state, Stretch(1.0));
392                        self.textbox_y.set_width(state, Stretch(1.0));
393                        self.textbox_z.set_width(state, Stretch(1.0));
394                        self.textbox_w.set_width(state, Stretch(1.0));
395
396                        self.textbox_x.set_right(state, Units::Pixels(5.0));
397                        self.textbox_y.set_right(state, Units::Pixels(5.0));
398                        self.textbox_z.set_right(state, Units::Pixels(5.0));
399                        self.textbox_w.set_right(state, Units::Pixels(5.0));
400
401                        self.num_of_dims = 4;
402
403                        state.insert_event(
404                            Event::new(VectorEditEvent::Dim4(
405                                self.x, self.y, self.z, self.w,
406                            ))
407                            .target(entity),
408                        );
409                    }
410
411                    _ => {}
412                },
413            }
414        }
415
416        if let Some(textbox_event) = event.message.downcast::<TextboxEvent>() {
417            match textbox_event {
418                TextboxEvent::ValueChanged(text) => {
419                    if let Ok(val) = text.clone().parse::<T>() {
420                        if target == self.textbox_x {
421                            self.x = val;
422                        }
423
424                        if target == self.textbox_y {
425                            self.y = val;
426                        }
427
428                        if target == self.textbox_z {
429                            self.z = val;
430                        }
431
432                        if target == self.textbox_w {
433                            self.w = val;
434                        }
435
436                        match self.num_of_dims {
437                            1 => state.insert_event(
438                                Event::new(VectorEditEvent::Dim1(self.x)).target(entity),
439                            ),
440                            2 => state.insert_event(
441                                Event::new(VectorEditEvent::Dim2(self.x, self.y))
442                                    .target(entity),
443                            ),
444                            3 => state.insert_event(
445                                Event::new(VectorEditEvent::Dim3(self.x, self.y, self.z))
446                                    .target(entity),
447                            ),
448                            4 => state.insert_event(
449                                Event::new(VectorEditEvent::Dim4(
450                                    self.x, self.y, self.z, self.w,
451                                ))
452                                .target(entity),
453                            ),
454                            _ => {}
455                        }
456
457                        if let Some(callback) = self.on_change.take() {
458                            (callback)(self, state, entity);
459                            self.on_change = Some(callback);
460                        }
461
462                        //state.insert_event(Event::new(VectorEditEvent::ValueChanged(self.xval, self.yval, self.zval, self.wval)).target(entity));
463                    }
464                }
465
466                _ => {}
467            }
468        }
469    }
470}