fyrox_ui/inspector/editors/
numeric.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21use crate::{
22    core::num_traits::NumCast,
23    inspector::{
24        editors::{
25            PropertyEditorBuildContext, PropertyEditorDefinition, PropertyEditorInstance,
26            PropertyEditorMessageContext, PropertyEditorTranslationContext,
27        },
28        FieldKind, InspectorError, PropertyChanged,
29    },
30    message::{MessageDirection, UiMessage},
31    numeric::{NumericType, NumericUpDownBuilder, NumericUpDownMessage},
32    widget::WidgetBuilder,
33    Thickness,
34};
35use std::{any::TypeId, marker::PhantomData};
36
37#[derive(Debug)]
38pub struct NumericPropertyEditorDefinition<T>
39where
40    T: NumericType,
41{
42    phantom: PhantomData<T>,
43}
44
45impl<T> Default for NumericPropertyEditorDefinition<T>
46where
47    T: NumericType,
48{
49    fn default() -> Self {
50        Self {
51            phantom: PhantomData,
52        }
53    }
54}
55
56impl<T> PropertyEditorDefinition for NumericPropertyEditorDefinition<T>
57where
58    T: NumericType,
59{
60    fn value_type_id(&self) -> TypeId {
61        TypeId::of::<T>()
62    }
63
64    fn create_instance(
65        &self,
66        ctx: PropertyEditorBuildContext,
67    ) -> Result<PropertyEditorInstance, InspectorError> {
68        let value = ctx.property_info.cast_value::<T>()?;
69        Ok(PropertyEditorInstance::Simple {
70            editor: NumericUpDownBuilder::new(
71                WidgetBuilder::new().with_margin(Thickness::top_bottom(1.0)),
72            )
73            .with_min_value(
74                ctx.property_info
75                    .min_value
76                    .and_then(NumCast::from)
77                    .unwrap_or_else(T::min_value),
78            )
79            .with_max_value(
80                ctx.property_info
81                    .max_value
82                    .and_then(NumCast::from)
83                    .unwrap_or_else(T::max_value),
84            )
85            .with_step(
86                ctx.property_info
87                    .step
88                    .and_then(NumCast::from)
89                    .unwrap_or_else(T::one),
90            )
91            .with_precision(ctx.property_info.precision.unwrap_or(3))
92            .with_value(*value)
93            .build(ctx.build_context),
94        })
95    }
96
97    fn create_message(
98        &self,
99        ctx: PropertyEditorMessageContext,
100    ) -> Result<Option<UiMessage>, InspectorError> {
101        let value = ctx.property_info.cast_value::<T>()?;
102        Ok(Some(NumericUpDownMessage::value(
103            ctx.instance,
104            MessageDirection::ToWidget,
105            *value,
106        )))
107    }
108
109    fn translate_message(&self, ctx: PropertyEditorTranslationContext) -> Option<PropertyChanged> {
110        if ctx.message.direction() == MessageDirection::FromWidget {
111            if let Some(NumericUpDownMessage::Value(value)) =
112                ctx.message.data::<NumericUpDownMessage<T>>()
113            {
114                return Some(PropertyChanged {
115                    name: ctx.name.to_string(),
116
117                    value: FieldKind::object(*value),
118                });
119            }
120        }
121
122        None
123    }
124}