Skip to main content

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