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