1use crate::{
2 core::{algebra::Vector4, 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 Vec4EditorMessage<T: NumericType> {
17 Value(Vector4<T>),
18}
19
20impl<T: NumericType> Vec4EditorMessage<T> {
21 define_constructor!(Vec4EditorMessage:Value => fn value(Vector4<T>), layout: false);
22}
23
24#[derive(Clone)]
25pub struct Vec4Editor<T: NumericType> {
26 widget: Widget,
27 x_field: Handle<UiNode>,
28 y_field: Handle<UiNode>,
29 z_field: Handle<UiNode>,
30 w_field: Handle<UiNode>,
31 value: Vector4<T>,
32}
33
34impl<T: NumericType> Deref for Vec4Editor<T> {
35 type Target = Widget;
36
37 fn deref(&self) -> &Self::Target {
38 &self.widget
39 }
40}
41
42impl<T: NumericType> DerefMut for Vec4Editor<T> {
43 fn deref_mut(&mut self) -> &mut Self::Target {
44 &mut self.widget
45 }
46}
47
48impl<T: NumericType> Control for Vec4Editor<T> {
49 fn query_component(&self, type_id: TypeId) -> Option<&dyn Any> {
50 if type_id == TypeId::of::<Self>() {
51 Some(self)
52 } else {
53 None
54 }
55 }
56
57 fn resolve(&mut self, node_map: &NodeHandleMapping) {
58 node_map.resolve(&mut self.x_field);
59 node_map.resolve(&mut self.y_field);
60 node_map.resolve(&mut self.z_field);
61 node_map.resolve(&mut self.w_field);
62 }
63
64 fn handle_routed_message(&mut self, ui: &mut UserInterface, message: &mut UiMessage) {
65 self.widget.handle_routed_message(ui, message);
66
67 if let Some(&NumericUpDownMessage::Value(value)) = message.data::<NumericUpDownMessage<T>>()
68 {
69 if message.direction() == MessageDirection::FromWidget {
70 if message.destination() == self.x_field {
71 ui.send_message(Vec4EditorMessage::value(
72 self.handle(),
73 MessageDirection::ToWidget,
74 Vector4::new(value, self.value.y, self.value.z, self.value.w),
75 ));
76 } else if message.destination() == self.y_field {
77 ui.send_message(Vec4EditorMessage::value(
78 self.handle(),
79 MessageDirection::ToWidget,
80 Vector4::new(self.value.x, value, self.value.z, self.value.w),
81 ));
82 } else if message.destination() == self.z_field {
83 ui.send_message(Vec4EditorMessage::value(
84 self.handle(),
85 MessageDirection::ToWidget,
86 Vector4::new(self.value.x, self.value.y, value, self.value.w),
87 ));
88 } else if message.destination() == self.w_field {
89 ui.send_message(Vec4EditorMessage::value(
90 self.handle(),
91 MessageDirection::ToWidget,
92 Vector4::new(self.value.x, self.value.y, self.value.z, value),
93 ));
94 }
95 }
96 } else if let Some(&Vec4EditorMessage::Value(value)) =
97 message.data::<Vec4EditorMessage<T>>()
98 {
99 if message.direction() == MessageDirection::ToWidget {
100 let mut changed = false;
101 if self.value.x != value.x {
102 self.value.x = value.x;
103 ui.send_message(NumericUpDownMessage::value(
104 self.x_field,
105 MessageDirection::ToWidget,
106 value.x,
107 ));
108 changed = true;
109 }
110 if self.value.y != value.y {
111 self.value.y = value.y;
112 ui.send_message(NumericUpDownMessage::value(
113 self.y_field,
114 MessageDirection::ToWidget,
115 value.y,
116 ));
117 changed = true;
118 }
119 if self.value.z != value.z {
120 self.value.z = value.z;
121 ui.send_message(NumericUpDownMessage::value(
122 self.z_field,
123 MessageDirection::ToWidget,
124 value.z,
125 ));
126 changed = true;
127 }
128 if self.value.w != value.w {
129 self.value.w = value.w;
130 ui.send_message(NumericUpDownMessage::value(
131 self.w_field,
132 MessageDirection::ToWidget,
133 value.w,
134 ));
135 changed = true;
136 }
137 if changed {
138 ui.send_message(message.reverse());
139 }
140 }
141 }
142 }
143}
144
145pub struct Vec4EditorBuilder<T: NumericType> {
146 widget_builder: WidgetBuilder,
147 value: Vector4<T>,
148}
149
150impl<T: NumericType> Vec4EditorBuilder<T> {
151 pub fn new(widget_builder: WidgetBuilder) -> Self {
152 Self {
153 widget_builder,
154 value: Vector4::new(T::zero(), T::zero(), T::zero(), T::zero()),
155 }
156 }
157
158 pub fn with_value(mut self, value: Vector4<T>) -> Self {
159 self.value = value;
160 self
161 }
162
163 pub fn build(self, ctx: &mut BuildContext) -> Handle<UiNode> {
164 let x_field;
165 let y_field;
166 let z_field;
167 let w_field;
168 let grid = GridBuilder::new(
169 WidgetBuilder::new()
170 .with_child(make_mark(ctx, "X", 0, Color::opaque(120, 0, 0)))
171 .with_child({
172 x_field = make_numeric_input(ctx, 1, self.value.x);
173 x_field
174 })
175 .with_child(make_mark(ctx, "Y", 2, Color::opaque(0, 120, 0)))
176 .with_child({
177 y_field = make_numeric_input(ctx, 3, self.value.y);
178 y_field
179 })
180 .with_child(make_mark(ctx, "Z", 4, Color::opaque(0, 0, 120)))
181 .with_child({
182 z_field = make_numeric_input(ctx, 5, self.value.z);
183 z_field
184 })
185 .with_child(make_mark(ctx, "W", 6, Color::opaque(120, 0, 120)))
186 .with_child({
187 w_field = make_numeric_input(ctx, 7, self.value.w);
188 w_field
189 }),
190 )
191 .add_row(Row::stretch())
192 .add_column(Column::auto())
193 .add_column(Column::stretch())
194 .add_column(Column::auto())
195 .add_column(Column::stretch())
196 .add_column(Column::auto())
197 .add_column(Column::stretch())
198 .add_column(Column::auto())
199 .add_column(Column::stretch())
200 .build(ctx);
201
202 let node = Vec4Editor {
203 widget: self.widget_builder.with_child(grid).build(),
204 x_field,
205 y_field,
206 z_field,
207 w_field,
208 value: self.value,
209 };
210
211 ctx.add_node(UiNode::new(node))
212 }
213}