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}