fyrox_ui/
uuid.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
21//! UUID editor is used to show an arbitrary UUID and give an ability to generate a new value. See [`UuidEditor`] docs for
22//! more info and usage examples.
23
24#![warn(missing_docs)]
25
26use crate::{
27    button::{ButtonBuilder, ButtonMessage},
28    core::{pool::Handle, reflect::prelude::*, type_traits::prelude::*, visitor::prelude::*},
29    define_constructor, define_widget_deref,
30    grid::{Column, GridBuilder, Row},
31    message::{MessageDirection, UiMessage},
32    text::{TextBuilder, TextMessage},
33    widget::{Widget, WidgetBuilder},
34    BuildContext, Control, Thickness, UiNode, UserInterface, VerticalAlignment,
35};
36
37use fyrox_core::uuid_provider;
38use fyrox_graph::constructor::{ConstructorProvider, GraphNodeConstructor};
39use std::ops::{Deref, DerefMut};
40
41/// A set of messages that is used to fetch or modify values of [`UuidEditor`] widgets.
42#[derive(Debug, Clone, PartialEq, Eq)]
43pub enum UuidEditorMessage {
44    /// Fetches or modifies a value of a [`UuidEditor`] widget.
45    Value(Uuid),
46}
47
48impl UuidEditorMessage {
49    define_constructor!(
50        /// Creates [`UuidEditorMessage::Value`] message.
51        UuidEditorMessage:Value => fn value(Uuid), layout: false
52    );
53}
54
55/// UUID editor is used to show an arbitrary UUID and give an ability to generate a new value. It is widely used in
56/// [`crate::inspector::Inspector`] to show and edit UUIDs.
57///
58/// ## Example
59///
60/// ```rust
61/// # use fyrox_ui::{
62/// #     core::{pool::Handle, uuid::Uuid},
63/// #     uuid::UuidEditorBuilder,
64/// #     widget::WidgetBuilder,
65/// #     BuildContext, UiNode,
66/// # };
67/// fn create_uuid_editor(ctx: &mut BuildContext) -> Handle<UiNode> {
68///     UuidEditorBuilder::new(WidgetBuilder::new())
69///         .with_value(Uuid::new_v4())
70///         .build(ctx)
71/// }
72/// ```
73#[derive(Default, Clone, Visit, Reflect, Debug, ComponentProvider)]
74#[reflect(derived_type = "UiNode")]
75pub struct UuidEditor {
76    widget: Widget,
77    value: Uuid,
78    text: Handle<UiNode>,
79    generate: Handle<UiNode>,
80}
81
82impl ConstructorProvider<UiNode, UserInterface> for UuidEditor {
83    fn constructor() -> GraphNodeConstructor<UiNode, UserInterface> {
84        GraphNodeConstructor::new::<Self>()
85            .with_variant("Uuid Editor", |ui| {
86                UuidEditorBuilder::new(WidgetBuilder::new().with_name("Uuid Editor"))
87                    .build(&mut ui.build_ctx())
88                    .into()
89            })
90            .with_group("Input")
91    }
92}
93
94define_widget_deref!(UuidEditor);
95
96uuid_provider!(UuidEditor = "667f7f48-2448-42da-91dd-cd743ca7117e");
97
98impl Control for UuidEditor {
99    fn handle_routed_message(&mut self, ui: &mut UserInterface, message: &mut UiMessage) {
100        self.widget.handle_routed_message(ui, message);
101
102        if message.destination() == self.handle && message.direction() == MessageDirection::ToWidget
103        {
104            if let Some(UuidEditorMessage::Value(value)) = message.data() {
105                if self.value != *value {
106                    self.value = *value;
107                    ui.send_message(message.reverse());
108
109                    ui.send_message(TextMessage::text(
110                        self.text,
111                        MessageDirection::ToWidget,
112                        value.to_string(),
113                    ));
114                }
115            }
116        } else if message.destination() == self.generate {
117            if let Some(ButtonMessage::Click) = message.data() {
118                ui.send_message(UuidEditorMessage::value(
119                    self.handle,
120                    MessageDirection::ToWidget,
121                    Uuid::new_v4(),
122                ));
123            }
124        }
125    }
126}
127
128/// Creates [`UuidEditor`] widgets and add them to the user interface.
129pub struct UuidEditorBuilder {
130    widget_builder: WidgetBuilder,
131    value: Uuid,
132}
133
134impl UuidEditorBuilder {
135    /// Creates new builder instance.
136    pub fn new(widget_builder: WidgetBuilder) -> Self {
137        Self {
138            widget_builder,
139            value: Default::default(),
140        }
141    }
142
143    /// Sets a desired value of the [`UuidEditor`].
144    pub fn with_value(mut self, value: Uuid) -> Self {
145        self.value = value;
146        self
147    }
148
149    /// Finishes widget building.
150    pub fn build(self, ctx: &mut BuildContext) -> Handle<UiNode> {
151        let text;
152        let generate;
153        let grid = GridBuilder::new(
154            WidgetBuilder::new()
155                .with_child({
156                    text = TextBuilder::new(
157                        WidgetBuilder::new()
158                            .on_column(0)
159                            .on_row(0)
160                            .with_margin(Thickness::uniform(1.0))
161                            .with_vertical_alignment(VerticalAlignment::Center),
162                    )
163                    .with_text(self.value.to_string())
164                    .build(ctx);
165                    text
166                })
167                .with_child({
168                    generate = ButtonBuilder::new(
169                        WidgetBuilder::new()
170                            .on_column(1)
171                            .on_row(0)
172                            .with_width(24.0)
173                            .with_margin(Thickness::uniform(1.0)),
174                    )
175                    .with_text("^/v")
176                    .build(ctx);
177                    generate
178                }),
179        )
180        .add_row(Row::stretch())
181        .add_column(Column::stretch())
182        .add_column(Column::auto())
183        .build(ctx);
184
185        let uuid_editor = UuidEditor {
186            widget: self.widget_builder.with_child(grid).build(ctx),
187            value: self.value,
188            text,
189            generate,
190        };
191
192        ctx.add_node(UiNode::new(uuid_editor))
193    }
194}
195
196#[cfg(test)]
197mod test {
198    use crate::uuid::UuidEditorBuilder;
199    use crate::{test::test_widget_deletion, widget::WidgetBuilder};
200
201    #[test]
202    fn test_deletion() {
203        test_widget_deletion(|ctx| UuidEditorBuilder::new(WidgetBuilder::new()).build(ctx));
204    }
205}