rg3d_ui/vec/
vec2.rs

1use crate::{
2    core::{algebra::Vector2, color::Color, pool::Handle},
3    define_constructor,
4    grid::{Column, GridBuilder, Row},
5    message::{MessageDirection, UiMessage},
6    numeric::{NumericType, NumericUpDownMessage},
7    vec::{make_mark, make_numeric_input},
8    BuildContext, Control, NodeHandleMapping, UiNode, UserInterface, Widget, WidgetBuilder,
9};
10use std::{
11    any::{Any, TypeId},
12    ops::{Deref, DerefMut},
13};
14
15#[derive(Debug, Clone, PartialEq)]
16pub enum Vec2EditorMessage<T: NumericType> {
17    Value(Vector2<T>),
18}
19
20impl<T: NumericType> Vec2EditorMessage<T> {
21    define_constructor!(Vec2EditorMessage:Value => fn value(Vector2<T>), layout: false);
22}
23
24#[derive(Clone)]
25pub struct Vec2Editor<T: NumericType> {
26    widget: Widget,
27    x_field: Handle<UiNode>,
28    y_field: Handle<UiNode>,
29    value: Vector2<T>,
30}
31
32impl<T: NumericType> Deref for Vec2Editor<T> {
33    type Target = Widget;
34
35    fn deref(&self) -> &Self::Target {
36        &self.widget
37    }
38}
39
40impl<T: NumericType> DerefMut for Vec2Editor<T> {
41    fn deref_mut(&mut self) -> &mut Self::Target {
42        &mut self.widget
43    }
44}
45
46impl<T: NumericType> Control for Vec2Editor<T> {
47    fn query_component(&self, type_id: TypeId) -> Option<&dyn Any> {
48        if type_id == TypeId::of::<Self>() {
49            Some(self)
50        } else {
51            None
52        }
53    }
54
55    fn resolve(&mut self, node_map: &NodeHandleMapping) {
56        node_map.resolve(&mut self.x_field);
57        node_map.resolve(&mut self.y_field);
58    }
59
60    fn handle_routed_message(&mut self, ui: &mut UserInterface, message: &mut UiMessage) {
61        self.widget.handle_routed_message(ui, message);
62
63        if let Some(&NumericUpDownMessage::Value(value)) = message.data::<NumericUpDownMessage<T>>()
64        {
65            if message.direction() == MessageDirection::FromWidget {
66                if message.destination() == self.x_field {
67                    ui.send_message(Vec2EditorMessage::value(
68                        self.handle(),
69                        MessageDirection::ToWidget,
70                        Vector2::new(value, self.value.y),
71                    ));
72                } else if message.destination() == self.y_field {
73                    ui.send_message(Vec2EditorMessage::value(
74                        self.handle(),
75                        MessageDirection::ToWidget,
76                        Vector2::new(self.value.x, value),
77                    ));
78                }
79            }
80        } else if let Some(&Vec2EditorMessage::Value(value)) =
81            message.data::<Vec2EditorMessage<T>>()
82        {
83            if message.direction() == MessageDirection::ToWidget {
84                let mut changed = false;
85                if self.value.x != value.x {
86                    self.value.x = value.x;
87                    ui.send_message(NumericUpDownMessage::value(
88                        self.x_field,
89                        MessageDirection::ToWidget,
90                        value.x,
91                    ));
92                    changed = true;
93                }
94                if self.value.y != value.y {
95                    self.value.y = value.y;
96                    ui.send_message(NumericUpDownMessage::value(
97                        self.y_field,
98                        MessageDirection::ToWidget,
99                        value.y,
100                    ));
101                    changed = true;
102                }
103                if changed {
104                    ui.send_message(message.reverse());
105                }
106            }
107        }
108    }
109}
110
111pub struct Vec2EditorBuilder<T: NumericType> {
112    widget_builder: WidgetBuilder,
113    value: Vector2<T>,
114}
115
116impl<T: NumericType> Vec2EditorBuilder<T> {
117    pub fn new(widget_builder: WidgetBuilder) -> Self {
118        Self {
119            widget_builder,
120            value: Vector2::new(T::zero(), T::zero()),
121        }
122    }
123
124    pub fn with_value(mut self, value: Vector2<T>) -> Self {
125        self.value = value;
126        self
127    }
128
129    pub fn build(self, ctx: &mut BuildContext) -> Handle<UiNode> {
130        let x_field;
131        let y_field;
132        let grid = GridBuilder::new(
133            WidgetBuilder::new()
134                .with_child(make_mark(ctx, "X", 0, Color::opaque(120, 0, 0)))
135                .with_child({
136                    x_field = make_numeric_input(ctx, 1, self.value.x);
137                    x_field
138                })
139                .with_child(make_mark(ctx, "Y", 2, Color::opaque(0, 120, 0)))
140                .with_child({
141                    y_field = make_numeric_input(ctx, 3, self.value.y);
142                    y_field
143                }),
144        )
145        .add_row(Row::stretch())
146        .add_column(Column::auto())
147        .add_column(Column::stretch())
148        .add_column(Column::auto())
149        .add_column(Column::stretch())
150        .build(ctx);
151
152        let node = Vec2Editor {
153            widget: self.widget_builder.with_child(grid).build(),
154            x_field,
155            y_field,
156            value: self.value,
157        };
158
159        ctx.add_node(UiNode::new(node))
160    }
161}