rg3d_ui/inspector/editors/
numeric.rs1use crate::{
2 core::num_traits::NumCast,
3 inspector::{
4 editors::{
5 PropertyEditorBuildContext, PropertyEditorDefinition, PropertyEditorInstance,
6 PropertyEditorMessageContext,
7 },
8 FieldKind, InspectorError, PropertyChanged,
9 },
10 message::{MessageDirection, UiMessage},
11 numeric::{NumericType, NumericUpDownBuilder, NumericUpDownMessage},
12 widget::WidgetBuilder,
13 Thickness,
14};
15use std::{any::TypeId, marker::PhantomData};
16
17#[derive(Debug)]
18pub struct NumericPropertyEditorDefinition<T>
19where
20 T: NumericType,
21{
22 phantom: PhantomData<T>,
23}
24
25impl<T> Default for NumericPropertyEditorDefinition<T>
26where
27 T: NumericType,
28{
29 fn default() -> Self {
30 Self {
31 phantom: PhantomData,
32 }
33 }
34}
35
36impl<T> PropertyEditorDefinition for NumericPropertyEditorDefinition<T>
37where
38 T: NumericType,
39{
40 fn value_type_id(&self) -> TypeId {
41 TypeId::of::<T>()
42 }
43
44 fn create_instance(
45 &self,
46 ctx: PropertyEditorBuildContext,
47 ) -> Result<PropertyEditorInstance, InspectorError> {
48 let value = ctx.property_info.cast_value::<T>()?;
49 Ok(PropertyEditorInstance::Simple {
50 editor: NumericUpDownBuilder::new(
51 WidgetBuilder::new().with_margin(Thickness::uniform(1.0)),
52 )
53 .with_min_value(
54 ctx.property_info
55 .min_value
56 .and_then(NumCast::from)
57 .unwrap_or_else(T::min_value),
58 )
59 .with_max_value(
60 ctx.property_info
61 .max_value
62 .and_then(NumCast::from)
63 .unwrap_or_else(T::max_value),
64 )
65 .with_step(
66 ctx.property_info
67 .step
68 .and_then(NumCast::from)
69 .unwrap_or_else(T::one),
70 )
71 .with_precision(ctx.property_info.precision.unwrap_or(3))
72 .with_value(*value)
73 .build(ctx.build_context),
74 })
75 }
76
77 fn create_message(
78 &self,
79 ctx: PropertyEditorMessageContext,
80 ) -> Result<Option<UiMessage>, InspectorError> {
81 let value = ctx.property_info.cast_value::<T>()?;
82 Ok(Some(NumericUpDownMessage::value(
83 ctx.instance,
84 MessageDirection::ToWidget,
85 *value,
86 )))
87 }
88
89 fn translate_message(
90 &self,
91 name: &str,
92 owner_type_id: TypeId,
93 message: &UiMessage,
94 ) -> Option<PropertyChanged> {
95 if message.direction() == MessageDirection::FromWidget {
96 if let Some(NumericUpDownMessage::Value(value)) =
97 message.data::<NumericUpDownMessage<T>>()
98 {
99 return Some(PropertyChanged {
100 name: name.to_string(),
101 owner_type_id,
102 value: FieldKind::object(*value),
103 });
104 }
105 }
106
107 None
108 }
109}