Skip to main content

fyrox_ui/
widget.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//! Base widget for every other widget in the crate. It contains layout-specific info, parent-child relations
22//! visibility, various transforms, drag'n'drop-related data, etc. See [`Widget`] docs for more info.
23
24#![warn(missing_docs)]
25
26use crate::draw::RenderData;
27use crate::{
28    brush::Brush,
29    core::{
30        algebra::{Matrix3, Point2, Vector2},
31        math::Rect,
32        pool::Handle,
33        reflect::prelude::*,
34        uuid::Uuid,
35        visitor::prelude::*,
36        ImmutableString, SafeLock,
37    },
38    core::{parking_lot::Mutex, variable::InheritableVariable},
39    message::{CursorIcon, Force, KeyCode, MessageData, UiMessage},
40    style::{
41        resource::{StyleResource, StyleResourceExt},
42        Style, StyledProperty, DEFAULT_STYLE,
43    },
44    BuildContext, HorizontalAlignment, LayoutEvent, MouseButton, MouseState, RcUiNodeHandle,
45    Thickness, UiNode, UserInterface, VerticalAlignment,
46};
47use fyrox_core::pool::ObjectOrVariant;
48use fyrox_graph::SceneGraph;
49use fyrox_material::{Material, MaterialResource};
50use fyrox_resource::Resource;
51use std::{
52    any::Any,
53    cell::{Cell, RefCell},
54    cmp::Ordering,
55    fmt::{Debug, Formatter},
56    ops::{Deref, DerefMut},
57    sync::{mpsc::Sender, Arc},
58};
59
60/// Sorting predicate that is used to sort widgets by some criteria.
61#[derive(Clone)]
62pub struct SortingPredicate(
63    pub Arc<dyn Fn(Handle<UiNode>, Handle<UiNode>, &UserInterface) -> Ordering + Send + Sync>,
64);
65
66impl SortingPredicate {
67    /// Creates new sorting predicate.
68    pub fn new<F>(func: F) -> Self
69    where
70        F: Fn(Handle<UiNode>, Handle<UiNode>, &UserInterface) -> Ordering + Send + Sync + 'static,
71    {
72        Self(Arc::new(func))
73    }
74}
75
76impl Debug for SortingPredicate {
77    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
78        write!(f, "SortingPredicate")
79    }
80}
81
82impl PartialEq for SortingPredicate {
83    fn eq(&self, other: &Self) -> bool {
84        std::ptr::eq(self.0.as_ref(), other.0.as_ref())
85    }
86}
87
88/// A set of messages for any kind of widgets (including user controls). These messages provide basic
89/// communication elements of the UI library.
90#[derive(Debug, Clone, PartialEq)]
91pub enum WidgetMessage {
92    /// Initiated when a user clicks on a widget's geometry.
93    ///
94    /// Direction: **From UI**.
95    MouseDown {
96        /// Position of cursor.
97        pos: Vector2<f32>,
98        /// A button that was pressed.
99        button: MouseButton,
100    },
101
102    /// Initiated when a user releases mouse button while the cursor is over widget's geometry.
103    ///
104    /// Direction: **From UI**.
105    MouseUp {
106        /// Position of cursor.
107        pos: Vector2<f32>,
108        /// A button that was released.
109        button: MouseButton,
110    },
111
112    /// Initiated when user moves cursor over widget's geometry.
113    ///
114    /// Direction: **From/To UI**.
115    MouseMove {
116        /// New position of cursor in screen coordinates.
117        pos: Vector2<f32>,
118        /// State of mouse buttons.
119        state: MouseState,
120    },
121
122    /// Initiated when a user scrolls mouse wheel while the cursor is over widget's geometry.
123    ///
124    /// Direction: **From/To UI**.
125    MouseWheel {
126        /// Position of cursor.
127        pos: Vector2<f32>,
128        /// Amount of lines per mouse wheel turn.
129        amount: f32,
130    },
131
132    /// Initiated when cursor leaves geometry of a widget.
133    ///
134    /// Direction: **From UI**.
135    MouseLeave,
136
137    /// Initiated when the cursor enters geometry of a widget.
138    ///
139    /// Direction: **From UI**.
140    MouseEnter,
141
142    /// Initiated when widget is in focus and user types something on a keyboard.
143    ///
144    /// Direction: **From/To UI**.
145    Text(String),
146
147    /// Initiated when widget is in focus and user presses a button on a keyboard.
148    ///
149    /// Direction: **From UI**.
150    KeyDown(KeyCode),
151
152    /// Initiated when the widget is in focus and user releases a button on a keyboard.
153    ///
154    /// Direction: **From UI**.
155    KeyUp(KeyCode),
156
157    /// Initiated when widget received focus (when direction is [`crate::message::MessageDirection::FromWidget`]). In most cases, focus is received
158    /// by clicking on widget. You can request focus explicitly by sending this message to a widget with [`crate::message::MessageDirection::ToWidget`]
159    ///
160    /// Direction: **From UI/To UI**.
161    Focus,
162
163    /// Initiated when widget has lost its focus (when direction is [`crate::message::MessageDirection::FromWidget`]). Can be used to
164    ///  remove focus from the widget if sent with [`crate::message::MessageDirection::ToWidget`]
165    ///
166    /// Direction: **From UI/To UI**.
167    Unfocus,
168
169    /// Initiated when dragging of a widget has started.
170    ///
171    /// Direction: **From UI**.
172    DragStarted(Handle<UiNode>),
173
174    /// Initiated when a user drags a widget over some other widget.
175    ///
176    /// Direction: **From UI**.
177    DragOver(Handle<UiNode>),
178
179    /// Initiated when a user drops a widget onto some other widget.
180    ///
181    /// Direction: **From UI**.
182    Drop(Handle<UiNode>),
183
184    /// A request to make widget topmost. Widget can be made topmost only in the same hierarchy
185    /// level only!
186    ///
187    /// Direction: **From/To UI**.
188    Topmost,
189
190    /// A request to make widget lowermost. Widget can be made lowermost only in the same hierarchy
191    /// level only!
192    ///
193    /// Direction: **From/To UI**.
194    Lowermost,
195
196    /// A request to detach widget from its current parent and attach to root canvas.
197    ///
198    /// Direction: **From/To UI**.
199    Unlink,
200
201    /// A request to delete widget with all its children widgets. All handles to a node and its
202    /// children will be invalid after processing such message!
203    ///
204    /// Direction: **From/To UI**.
205    Remove,
206
207    /// A request to link initiator with specified widget.
208    ///
209    /// Direction: **From/To UI**.
210    LinkWith(Handle<UiNode>),
211
212    /// A request to link initiator with a specified widget and put it in front of children list.
213    ///
214    /// Direction: **From/To UI**.
215    LinkWithReverse(Handle<UiNode>),
216
217    /// A request to delete all the children widgets and replace them with the given nodes as the
218    /// new child nodes.
219    ///
220    /// Direction: **To UI**.
221    ReplaceChildren(Vec<Handle<UiNode>>),
222
223    /// A request to change background brush of a widget. Background brushes are used to fill the volume with widgets.
224    ///
225    /// Direction: **From/To UI**
226    Background(StyledProperty<Brush>),
227
228    /// A request to change foreground brush of a widget. Foreground brushes are used for text, borders and so on.
229    ///
230    /// Direction: **From/To UI**
231    Foreground(StyledProperty<Brush>),
232
233    /// A request to change the name of a widget. Name is given to widget mostly for debugging purposes.
234    ///
235    /// Direction: **From/To UI**
236    Name(String),
237
238    /// A request to set the width of a widget. In most cases, there is no need to explicitly set the width of a widget,
239    /// because fyrox-ui uses automatic layout engine which will correctly calculate the desired width of a widget.
240    ///
241    /// Direction: **From/To UI**
242    Width(f32),
243
244    /// A request to set the height of a widget. In most cases, there is no need to explicitly set the height of a widget,
245    /// because fyrox-ui uses automatic layout engine which will correctly calculate the desired height of a widget.
246    ///
247    /// Direction: **From/To UI**
248    Height(f32),
249
250    /// A request to set vertical alignment of a widget. Vertical alignment tells where to put widget in the parent
251    /// widget's bounds in vertical direction.
252    ///
253    /// Direction: **From/To UI**
254    VerticalAlignment(VerticalAlignment),
255
256    /// A request to set horizontal alignment of a widget. Horizontal alignment tells where to put widget in the parent
257    /// widget's bounds in horizontal direction.
258    ///
259    /// Direction: **From/To UI**
260    HorizontalAlignment(HorizontalAlignment),
261
262    /// A request to set the maximum size of widget. Maximum size restricts the size of a widget during layout pass. For example,
263    /// you can set the maximum size to a button which was placed into a grid's cell. if the maximum size wouldn't be set, the button
264    /// would be stretched to fill the entire cell.
265    ///
266    /// Direction: **From/To UI**
267    MaxSize(Vector2<f32>),
268
269    /// A request to set the minimum size of widget. Minimum size restricts the size of a widget during layout pass. For example,
270    /// you can set minimum size to a button which was placed into a grid's cell, if minimum size wouldn't be set, the button
271    /// would be compressed to fill the entire cell.
272    ///
273    /// Direction: **From/To UI**
274    MinSize(Vector2<f32>),
275
276    /// A request to set row number of a grid to which widget should belong to.
277    ///
278    /// Direction: **From/To UI**
279    ///
280    /// # Notes
281    ///
282    /// This is a bad API, and it should be changed in the future. Grid should have an explicit list of pairs (row, child) instead
283    /// of this indirect attachment.
284    Row(usize),
285
286    /// A request to set column number of a grid to which widget should belong to.
287    ///
288    /// Direction: **From/To UI**
289    ///
290    /// # Notes
291    ///
292    /// This is a bad API, and it should be changed in the future. Grid should have an explicit list of pairs (column, child) instead
293    /// of this indirect attachment.
294    Column(usize),
295
296    /// A request to set new margin of widget. Margin could be used to add some free space around the widget to make the UI look less
297    /// dense.
298    ///
299    /// Direction: **From/To UI**
300    Margin(Thickness),
301
302    /// A request to set new state hit test visibility. If set to false, the widget will become "non-clickable". It is useful for
303    /// decorations which should be transparent for mouse events.
304    ///
305    /// Direction: **From/To UI**
306    HitTestVisibility(bool),
307
308    /// A request to set new visibility of a widget. Widget can be either visible or not. Invisible widgets do not take space
309    /// in layout pass and collapsed to a point.
310    ///
311    /// Direction: **From/To UI**
312    Visibility(bool),
313
314    /// A request to set new z index of a widget. Z index is used to change drawing order of widgets. Please note that it works
315    /// only in the same hierarchy level, which means that it is impossible to set z index to 9999 (or similar huge value) to force
316    /// the widget to be drawn on top of everything.
317    ///
318    /// Direction: **From/To UI**
319    ZIndex(usize),
320
321    /// A request to set new desired position of a widget. It is called "desired" because the layout system may ignore it and set
322    /// some other position. Desired position works with a combination of a layout panel that supports direct coordinated
323    /// (Canvas for example).
324    ///
325    /// Direction: **From/To UI**
326    DesiredPosition(Vector2<f32>),
327
328    /// Aligns the widget in the specified widget's bounds using the given options. It can be used only if the
329    /// widget is a child of a container that supports arbitrary positions (such as Canvas).
330    Align {
331        /// A handle of a node to which the sender of this message should be aligned to.
332        relative_to: Handle<UiNode>,
333        /// Horizontal alignment of the widget.
334        horizontal_alignment: HorizontalAlignment,
335        /// Vertical alignment of the widget.
336        vertical_alignment: VerticalAlignment,
337        /// Margins for each side.
338        margin: Thickness,
339    },
340
341    /// A request to enable or disable widget. Disabled widget won't receive mouse events and may look differently (it is defined
342    /// by internal styling).
343    ///
344    /// Direction: **From/To UI**
345    Enabled(bool),
346
347    /// A request to set the desired position at center in local coordinates.
348    ///
349    /// Direction: **From/To UI**
350    Center,
351
352    /// A request to adjust widget's position to fit in parent's bounds.
353    AdjustPositionToFit,
354
355    /// A request to set new cursor icon for widget.
356    ///
357    /// Direction: **From/To UI**
358    Cursor(Option<CursorIcon>),
359
360    /// A request to set new opacity for widget.
361    ///
362    /// Direction: **From/To UI**
363    Opacity(Option<f32>),
364
365    /// A request to set new layout transform.
366    LayoutTransform(Matrix3<f32>),
367
368    /// A request to set new render transform.
369    RenderTransform(Matrix3<f32>),
370
371    /// A double click of a mouse button has occurred on a widget.
372    DoubleClick {
373        /// A button, that was double-clicked.
374        button: MouseButton,
375    },
376
377    /// A request to set new context menu for a widget. The old context menu will be removed only if its
378    /// reference counter was 1.
379    ContextMenu(Option<RcUiNodeHandle>),
380
381    /// A request to set new tooltip for a widget. The old tooltip will be removed only if its reference
382    /// counter was 1.
383    Tooltip(Option<RcUiNodeHandle>),
384
385    /// Initiated when user places finger on the screen.
386    ///
387    /// Direction: **From UI**.
388    TouchStarted {
389        /// position of user's finger
390        pos: Vector2<f32>,
391        /// pressure exerted on screen at pos
392        force: Option<Force>,
393        /// unique identifier for touch event
394        id: u64,
395    },
396
397    /// Initiated when user removes finger from the screen.
398    ///
399    /// Direction: **From UI**.
400    TouchEnded {
401        /// position of user's finger
402        pos: Vector2<f32>,
403        /// unique identifier for touch event
404        id: u64,
405    },
406
407    /// Initiated when a user drags their finger across the screen.
408    ///
409    /// Direction: **From UI**.
410    TouchMoved {
411        /// position of user's finger
412        pos: Vector2<f32>,
413        /// pressure exerted on screen at pos
414        force: Option<Force>,
415        /// unique identifier for touch event
416        id: u64,
417    },
418
419    /// Initiated when a user cancels their touch event.
420    ///
421    /// Direction: **From UI**.
422    TouchCancelled {
423        /// position of user's finger
424        pos: Vector2<f32>,
425        /// unique identifier for touch event
426        id: u64,
427    },
428
429    /// Initiated when a user taps the screen two or more times in rapid succession.
430    ///
431    /// Direction: **From UI**.
432    DoubleTap {
433        /// position of user's finger
434        pos: Vector2<f32>,
435        /// pressure exerted on screen at pos
436        force: Option<Force>,
437        /// unique identifier for touch event
438        id: u64,
439    },
440
441    /// Sorts children widgets of a widget.
442    ///
443    /// Direction: **To UI**.
444    SortChildren(SortingPredicate),
445
446    /// Applies a style to the widget.
447    Style(StyleResource),
448
449    /// Asks a widget to reset its visual state. The actual response to this message is widget-specific.
450    /// In most cases, it does nothing.
451    ResetVisual,
452}
453
454impl WidgetMessage {
455    /// Creates a [`Self::DragStarted`] message.
456    pub fn drag_started(handle: Handle<impl ObjectOrVariant<UiNode>>) -> Self {
457        Self::DragStarted(handle.to_base())
458    }
459
460    /// Creates a [`Self::DragOver`] message.
461    pub fn drag_over(handle: Handle<impl ObjectOrVariant<UiNode>>) -> Self {
462        Self::DragOver(handle.to_base())
463    }
464
465    /// Creates a [`Self::Drop`] message.
466    pub fn drop(handle: Handle<impl ObjectOrVariant<UiNode>>) -> Self {
467        Self::Drop(handle.to_base())
468    }
469
470    /// Creates a [`Self::LinkWith`] message.
471    pub fn link_with(handle: Handle<impl ObjectOrVariant<UiNode>>) -> Self {
472        Self::LinkWith(handle.to_base())
473    }
474
475    /// Creates a [`Self::LinkWithReverse`] message.
476    pub fn link_with_reverse(handle: Handle<impl ObjectOrVariant<UiNode>>) -> Self {
477        Self::LinkWithReverse(handle.to_base())
478    }
479}
480
481impl MessageData for WidgetMessage {
482    fn need_perform_layout(&self) -> bool {
483        matches!(
484            self,
485            Self::Center | Self::AdjustPositionToFit | Self::Align { .. }
486        )
487    }
488}
489
490#[doc(hidden)]
491#[derive(Clone, Debug, Reflect, PartialEq)]
492pub struct WidgetMaterial(pub MaterialResource);
493
494impl Visit for WidgetMaterial {
495    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
496        self.0.visit(name, visitor)
497    }
498}
499
500impl Default for WidgetMaterial {
501    fn default() -> Self {
502        Self(MaterialResource::new_embedded(Material::standard_widget()))
503    }
504}
505
506impl Deref for WidgetMaterial {
507    type Target = MaterialResource;
508
509    fn deref(&self) -> &Self::Target {
510        &self.0
511    }
512}
513
514impl DerefMut for WidgetMaterial {
515    fn deref_mut(&mut self) -> &mut Self::Target {
516        &mut self.0
517    }
518}
519
520/// A set of data emitted by a widget during the draw pass.
521#[derive(Default, Debug, Clone)]
522pub struct WidgetRenderDataSet {
523    /// The result of calling the [`crate::control::Control::draw`] method.
524    pub draw_result: RenderData,
525
526    /// The result of calling the [`crate::control::Control::post_draw`] method.
527    pub post_draw_result: RenderData,
528}
529
530impl WidgetRenderDataSet {
531    /// Clears the data set.
532    pub fn clear(&mut self) {
533        self.draw_result.clear();
534        self.post_draw_result.clear();
535    }
536}
537
538/// Widget is a base UI element, that is always used to build derived, more complex, widgets. In general, it is a container
539/// for layout information, basic visual appearance, visibility options, parent-child information. It does almost nothing
540/// on its own, instead, the user interface modifies its state accordingly.
541#[derive(Default, Debug, Clone, Reflect, Visit)]
542#[visit(optional)]
543pub struct Widget {
544    /// Self handle of the widget. It is valid **only**, if the widget is added to the user interface, in other
545    /// cases it will most likely be [`Handle::NONE`].
546    #[reflect(hidden)]
547    pub handle: Handle<UiNode>,
548    /// Name of the widget. Could be useful for debugging purposes.
549    pub name: ImmutableString,
550    /// Desired position relative to the parent node. It is just a recommendation for the layout system, actual position
551    /// will be stored in the `actual_local_position` field and can be fetched using [`Widget::actual_local_position`]
552    /// method.
553    #[reflect(setter = "set_desired_local_position_notify")]
554    pub desired_local_position: InheritableVariable<Vector2<f32>>,
555    /// Explicit width for the widget, or automatic if [`f32::NAN`] (means the value is undefined). Default is [`f32::NAN`].
556    #[reflect(setter = "set_width_notify")]
557    pub width: InheritableVariable<f32>,
558    /// Explicit height for the widget, or automatic if [`f32::NAN`] (means the value is undefined). Default is [`f32::NAN`].
559    #[reflect(setter = "set_height_notify")]
560    pub height: InheritableVariable<f32>,
561    /// Minimum width and height. Default is 0.0 for both axes.
562    #[reflect(setter = "set_min_size_notify")]
563    pub min_size: InheritableVariable<Vector2<f32>>,
564    /// Maximum width and height. Default is [`f32::INFINITY`] for both axes.
565    #[reflect(setter = "set_max_size_notify")]
566    pub max_size: InheritableVariable<Vector2<f32>>,
567    /// Background brush of the widget.
568    pub background: InheritableVariable<StyledProperty<Brush>>,
569    /// Foreground brush of the widget.
570    pub foreground: InheritableVariable<StyledProperty<Brush>>,
571    /// Index of the row to which this widget belongs to. It is valid only when used in [`crate::grid::Grid`] widget.
572    #[reflect(setter = "set_row_notify")]
573    pub row: InheritableVariable<usize>,
574    /// Index of the column to which this widget belongs to. It is valid only when used in [`crate::grid::Grid`] widget.
575    #[reflect(setter = "set_column_notify")]
576    pub column: InheritableVariable<usize>,
577    /// Vertical alignment of the widget.
578    #[reflect(setter = "set_vertical_alignment_notify")]
579    pub vertical_alignment: InheritableVariable<VerticalAlignment>,
580    /// Horizontal alignment of the widget.
581    #[reflect(setter = "set_horizontal_alignment_notify")]
582    pub horizontal_alignment: InheritableVariable<HorizontalAlignment>,
583    /// Margin for every side of bounding rectangle. See [`Thickness`] docs for more info.
584    #[reflect(setter = "set_margin_notify")]
585    pub margin: InheritableVariable<Thickness>,
586    /// Current, **local**, visibility state of the widget.
587    #[reflect(setter = "set_visibility_notify")]
588    pub visibility: InheritableVariable<bool>,
589    /// Current, **global** (including the chain of parent widgets), visibility state of the widget.
590    #[reflect(hidden)]
591    pub global_visibility: bool,
592    /// A set of handles to children nodes of this widget.
593    #[reflect(hidden)]
594    pub children: Vec<Handle<UiNode>>,
595    /// A handle to the parent node of this widget.
596    #[reflect(hidden)]
597    pub parent: Handle<UiNode>,
598    /// The visual data of the widget.
599    #[reflect(hidden)]
600    #[visit(skip)]
601    pub render_data_set: RefCell<WidgetRenderDataSet>,
602    /// A flag, that indicates that the mouse is directly over the widget. It will be raised only for top-most widget in the
603    /// "stack" of widgets.
604    #[reflect(hidden)]
605    pub is_mouse_directly_over: bool,
606    /// A flag, that defines whether the widget is "visible" for hit testing (picking). Could be useful to prevent some widgets
607    /// from any interactions with mouse.
608    pub hit_test_visibility: InheritableVariable<bool>,
609    /// Index of the widget in parent's children list that defines its order in drawing and picking.
610    pub z_index: InheritableVariable<usize>,
611    /// A flag, that defines whether the drag from drag'n'drop functionality can be started by the widget or not.
612    pub allow_drag: InheritableVariable<bool>,
613    /// A flag, that defines whether the drop from drag'n'drop functionality can be accepted by the widget or not.
614    pub allow_drop: InheritableVariable<bool>,
615    /// Style of the widget.
616    pub style: Option<StyleResource>,
617    /// Optional, user-defined data.
618    #[reflect(hidden)]
619    #[visit(skip)]
620    pub user_data: Option<Arc<Mutex<dyn Any + Send>>>,
621    /// A flag, that defines whether the widget should be drawn in a separate drawing pass after any other widget that draws
622    /// normally.
623    pub draw_on_top: InheritableVariable<bool>,
624    /// A flag, that defines whether the widget is enabled or not. Disabled widgets cannot be interacted by used, and they're
625    /// greyed out.
626    pub enabled: InheritableVariable<bool>,
627    /// Optional cursor icon that will be used for mouse cursor when hovering over the widget.
628    pub cursor: InheritableVariable<Option<CursorIcon>>,
629    /// Optional opacity of the widget. It should be in `[0.0..1.0]` range, where 0.0 - fully transparent, 1.0 - fully opaque.
630    pub opacity: InheritableVariable<Option<f32>>,
631    /// An optional ref counted handle to a tooltip used by the widget.
632    pub tooltip: Option<RcUiNodeHandle>,
633    /// Maximum available time to show the tooltip after the cursor was moved away from the widget.
634    pub tooltip_time: f32,
635    /// An optional ref counted handle to a context menu used by the widget.
636    pub context_menu: Option<RcUiNodeHandle>,
637    /// A flag, that defines whether the widget should be clipped by the parent bounds or not.
638    pub clip_to_bounds: InheritableVariable<bool>,
639    /// Current render transform of the node. It modifies layout information of the widget, as well as it affects visual transform
640    /// of the widget.
641    #[reflect(hidden)]
642    layout_transform: Matrix3<f32>,
643    /// Current render transform of the node. It only modifies the widget at drawing stage, layout information remains unmodified.
644    #[reflect(hidden)]
645    render_transform: Matrix3<f32>,
646    /// Current visual transform of the node. It always contains a result of mixing the layout and
647    /// render transformation matrices. Visual transform could be used to transform a point to
648    /// screen space. To transform a screen space point to local coordinates use [`Widget::screen_to_local`]
649    /// method.
650    #[reflect(hidden)]
651    pub visual_transform: Matrix3<f32>,
652    /// A flag, that defines whether the widget will preview UI messages or not. Basically, it defines whether [crate::Control::preview_message]
653    /// is called or not.
654    pub preview_messages: bool,
655    /// A flag, that defines whether the widget will receive any OS events or not. Basically, it defines whether [crate::Control::handle_os_event]
656    /// is called or not.
657    pub handle_os_events: bool,
658    /// Defines the order in which this widget will get keyboard focus when the Tab key is pressed.
659    /// If set to [`None`], Tab key won't do anything on such widget. Default is [`None`].
660    pub tab_index: InheritableVariable<Option<usize>>,
661    /// A flag, that defines whether the Tab key navigation is enabled or disabled for this widget.
662    pub tab_stop: InheritableVariable<bool>,
663    /// A flag, that defines whether the widget will be updated or not. Basically, it defines whether [crate::Control::update]
664    /// is called or not.
665    pub need_update: bool,
666    /// Enables (`false`) or disables (`true`) layout rounding.
667    pub ignore_layout_rounding: bool,
668    /// A flag, that indicates that the widget accepts user input. It could be used to determine if
669    /// a user can interact with the widget using a keyboard. It is also used for automatic assignment
670    /// of the tab index. Keep in mind that this flag is only a marker and does not do anything else
671    /// on its own. The Default value is `false`.
672    pub accepts_input: bool,
673    /// Internal sender for layout events.
674    #[reflect(hidden)]
675    #[visit(skip)]
676    pub layout_events_sender: Option<Sender<LayoutEvent>>,
677    /// Unique identifier of the widget.
678    pub id: Uuid,
679    /// A flag, that indicates whether this widget is a root widget of a hierarchy of widgets
680    /// instantiated from a resource.
681    #[reflect(hidden)]
682    pub is_resource_instance_root: bool,
683    /// A resource from which this widget was instantiated from, can work in pair with `original`
684    /// handle to get a corresponding widget from resource.
685    #[reflect(read_only)]
686    pub resource: Option<Resource<UserInterface>>,
687    /// A material, that should be used when rendering the widget.
688    pub material: InheritableVariable<WidgetMaterial>,
689    /// Handle to a widget in a user interface resource from which this node was instantiated from.
690    #[reflect(hidden)]
691    pub original_handle_in_resource: Handle<UiNode>,
692    //
693    // Layout. Interior mutability is a must here because layout performed in a series of recursive calls.
694    //
695    /// A flag, that defines whether the measurement results are still valid or not.
696    #[reflect(hidden)]
697    #[visit(skip)]
698    pub measure_valid: Cell<bool>,
699    /// A flag, that defines whether the arrangement results are still valid or not.
700    #[reflect(hidden)]
701    #[visit(skip)]
702    pub arrange_valid: Cell<bool>,
703    /// A flag, that defines whether the visual is still valid or not.
704    #[reflect(hidden)]
705    #[visit(skip)]
706    pub visual_valid: Cell<bool>,
707    /// Results or previous measurement.
708    #[reflect(hidden)]
709    #[visit(skip)]
710    pub prev_measure: Cell<Vector2<f32>>,
711    /// Results or previous arrangement.
712    #[reflect(hidden)]
713    #[visit(skip)]
714    pub prev_arrange: Cell<Rect<f32>>,
715    /// The desired size of the node after Measure pass.
716    #[reflect(hidden)]
717    #[visit(skip)]
718    pub desired_size: Cell<Vector2<f32>>,
719    /// Actual local position of the widget after Arrange pass.
720    #[reflect(hidden)]
721    #[visit(skip)]
722    pub actual_local_position: Cell<Vector2<f32>>,
723    /// Actual local size of the widget after Arrange pass.
724    #[reflect(hidden)]
725    #[visit(skip)]
726    pub actual_local_size: Cell<Vector2<f32>>,
727    /// Previous global visibility of the widget.
728    #[reflect(hidden)]
729    #[visit(skip)]
730    pub prev_global_visibility: bool,
731    /// Current clip bounds of the widget.
732    #[reflect(hidden)]
733    #[visit(skip)]
734    pub clip_bounds: Cell<Rect<f32>>,
735}
736
737impl Widget {
738    /// Returns self handle of the widget.
739    #[inline]
740    pub fn handle(&self) -> Handle<UiNode> {
741        self.handle
742    }
743
744    /// Returns the name of the widget.
745    #[inline]
746    pub fn name(&self) -> &str {
747        self.name.as_str()
748    }
749
750    /// Sets the new name of the widget.
751    #[inline]
752    pub fn set_name<P: AsRef<str>>(&mut self, name: P) -> &mut Self {
753        self.name = ImmutableString::new(name);
754        self
755    }
756
757    /// Returns the actual size of the widget after the full layout cycle.
758    #[inline]
759    pub fn actual_local_size(&self) -> Vector2<f32> {
760        self.actual_local_size.get()
761    }
762
763    /// Returns size of the widget without any layout or rendering transform applied.
764    #[inline]
765    pub fn actual_initial_size(&self) -> Vector2<f32> {
766        Rect::new(
767            0.0,
768            0.0,
769            self.actual_local_size.get().x,
770            self.actual_local_size.get().y,
771        )
772        .transform(&self.visual_transform.try_inverse().unwrap_or_default())
773        .size
774    }
775
776    /// Returns the actual global size of the widget after the full layout cycle.
777    #[inline]
778    pub fn actual_global_size(&self) -> Vector2<f32> {
779        self.screen_bounds().size
780    }
781
782    /// Sets the new minimum size of the widget.
783    #[inline]
784    pub fn set_min_size(&mut self, value: Vector2<f32>) -> &mut Self {
785        self.min_size.set_value_and_mark_modified(value);
786        self
787    }
788
789    fn set_min_size_notify(&mut self, value: Vector2<f32>) -> Vector2<f32> {
790        self.invalidate_layout();
791        self.min_size.set_value_and_mark_modified(value)
792    }
793
794    /// Sets the new minimum width of the widget.
795    #[inline]
796    pub fn set_min_width(&mut self, value: f32) -> &mut Self {
797        self.min_size.x = value;
798        self
799    }
800
801    /// Sets the new minimum height of the widget.
802    #[inline]
803    pub fn set_min_height(&mut self, value: f32) -> &mut Self {
804        self.min_size.y = value;
805        self
806    }
807
808    /// Sets the new minimum size of the widget.
809    #[inline]
810    pub fn min_size(&self) -> Vector2<f32> {
811        *self.min_size
812    }
813
814    /// Returns the minimum width of the widget.
815    #[inline]
816    pub fn min_width(&self) -> f32 {
817        self.min_size.x
818    }
819
820    /// Returns the minimum height of the widget.
821    #[inline]
822    pub fn min_height(&self) -> f32 {
823        self.min_size.y
824    }
825
826    /// Return `true` if the dragging of the widget is allowed, `false` - otherwise.
827    #[inline]
828    pub fn is_drag_allowed(&self) -> bool {
829        *self.allow_drag
830    }
831
832    /// Return `true` if the dropping of other widgets is allowed on this widget, `false` - otherwise.
833    #[inline]
834    pub fn is_drop_allowed(&self) -> bool {
835        *self.allow_drop
836    }
837
838    /// Maps the given point from screen to local widget's coordinates. Could be used to transform
839    /// mouse cursor position (which is in screen space) to local widget coordinates.
840    #[inline]
841    pub fn screen_to_local(&self, point: Vector2<f32>) -> Vector2<f32> {
842        self.visual_transform
843            .try_inverse()
844            .unwrap_or_default()
845            .transform_point(&Point2::from(point))
846            .coords
847    }
848
849    /// Maps the given point from local widget's coordinates to screen.
850    #[inline]
851    pub fn local_to_screen(&self, point: Vector2<f32>) -> Vector2<f32> {
852        self.visual_transform
853            .transform_point(&Point2::from(point))
854            .coords
855    }
856
857    /// Invalidates the layout of the widget. **WARNING**: Do not use this method, unless you understand what you're doing,
858    /// it will cause new layout pass for this widget which could be quite heavy and doing so on every frame for multiple
859    /// widgets **will** cause severe performance issues.
860    #[inline]
861    pub fn invalidate_layout(&self) {
862        self.invalidate_measure();
863        self.invalidate_arrange();
864        self.try_send_transform_changed_event();
865    }
866
867    /// Invalidates the visual of the widget, forcing it to be fully redrawn. This method must be
868    /// called if your widget has custom implementation of [`crate::control::Control::draw`] or
869    /// [`crate::control::Control::post_draw`] methods and if it uses some properties that may be
870    /// changed at runtime. Otherwise, the widget won't be redrawn and you won't see the changes.
871    #[inline]
872    pub fn invalidate_visual(&self) {
873        self.visual_valid.set(false);
874        if let Some(sender) = self.layout_events_sender.as_ref() {
875            sender
876                .send(LayoutEvent::VisualInvalidated(self.handle))
877                .unwrap()
878        }
879    }
880
881    pub(crate) fn notify_z_index_changed(&self) {
882        if let Some(sender) = self.layout_events_sender.as_ref() {
883            sender
884                .send(LayoutEvent::ZIndexChanged(self.handle))
885                .unwrap()
886        }
887    }
888
889    /// Invalidates measurement results of the widget. **WARNING**: Do not use this method, unless you understand what you're
890    /// doing, it will cause new measurement pass for this widget which could be quite heavy and doing so on every frame for
891    /// multiple widgets **will** cause severe performance issues.
892    #[inline]
893    pub fn invalidate_measure(&self) {
894        self.measure_valid.set(false);
895
896        if let Some(layout_events_sender) = self.layout_events_sender.as_ref() {
897            let _ = layout_events_sender.send(LayoutEvent::MeasurementInvalidated(self.handle));
898        }
899    }
900
901    /// Invalidates arrangement results of the widget. **WARNING**: Do not use this method, unless you understand what you're
902    /// doing, it will cause a new arrangement pass for this widget which could be quite heavy and doing so on every frame for
903    /// multiple widgets **will** cause severe performance issues.
904    #[inline]
905    pub fn invalidate_arrange(&self) {
906        self.arrange_valid.set(false);
907
908        if let Some(layout_events_sender) = self.layout_events_sender.as_ref() {
909            let _ = layout_events_sender.send(LayoutEvent::ArrangementInvalidated(self.handle));
910        }
911    }
912
913    /// Returns `true` if the widget is able to participate in hit testing, `false` - otherwise.
914    #[inline]
915    pub fn is_hit_test_visible(&self) -> bool {
916        *self.hit_test_visibility
917    }
918
919    /// Sets the new maximum size of the widget.
920    #[inline]
921    pub fn set_max_size(&mut self, value: Vector2<f32>) -> &mut Self {
922        self.max_size.set_value_and_mark_modified(value);
923        self
924    }
925
926    fn set_max_size_notify(&mut self, value: Vector2<f32>) -> Vector2<f32> {
927        self.invalidate_layout();
928        std::mem::replace(&mut self.max_size, value)
929    }
930
931    /// Returns the current maximum size of the widget.
932    #[inline]
933    pub fn max_size(&self) -> Vector2<f32> {
934        *self.max_size
935    }
936
937    /// Returns maximum width of the widget.
938    #[inline]
939    pub fn max_width(&self) -> f32 {
940        self.max_size.x
941    }
942
943    /// Return maximum height of the widget.
944    #[inline]
945    pub fn max_height(&self) -> f32 {
946        self.max_size.y
947    }
948
949    /// Sets new Z index for the widget. Z index defines the sorting (stable) index which will be used to "arrange" widgets
950    /// in the correct order.
951    #[inline]
952    pub fn set_z_index(&mut self, z_index: usize) -> &mut Self {
953        self.z_index.set_value_and_mark_modified(z_index);
954        self.notify_z_index_changed();
955        self
956    }
957
958    /// Returns current Z index of the widget.
959    #[inline]
960    pub fn z_index(&self) -> usize {
961        *self.z_index
962    }
963
964    /// Sets the new background of the widget.
965    #[inline]
966    pub fn set_background(&mut self, brush: Brush) -> &mut Self {
967        self.background.property = brush;
968        self
969    }
970
971    /// Returns current background of the widget.
972    #[inline]
973    pub fn background(&self) -> Brush {
974        self.background.property.clone()
975    }
976
977    /// Sets new foreground of the widget.
978    #[inline]
979    pub fn set_foreground(&mut self, brush: Brush) -> &mut Self {
980        self.foreground.property = brush;
981        self
982    }
983
984    /// Returns current foreground of the widget.
985    #[inline]
986    pub fn foreground(&self) -> Brush {
987        self.foreground.property.clone()
988    }
989
990    /// Sets new width of the widget.
991    #[inline]
992    pub fn set_width(&mut self, width: f32) -> &mut Self {
993        self.width
994            .set_value_and_mark_modified(width.clamp(self.min_size.x, self.max_size.x));
995        self
996    }
997
998    fn set_width_notify(&mut self, width: f32) -> f32 {
999        self.invalidate_layout();
1000        std::mem::replace(&mut self.width, width)
1001    }
1002
1003    /// Returns the current width of the widget.
1004    #[inline]
1005    pub fn width(&self) -> f32 {
1006        *self.width
1007    }
1008
1009    /// Return `true` if the widget is set to be drawn on top of every other, normally drawn, widgets, `false` - otherwise.
1010    pub fn is_draw_on_top(&self) -> bool {
1011        *self.draw_on_top
1012    }
1013
1014    /// Sets new height of the widget.
1015    #[inline]
1016    pub fn set_height(&mut self, height: f32) -> &mut Self {
1017        self.height
1018            .set_value_and_mark_modified(height.clamp(self.min_size.y, self.max_size.y));
1019        self
1020    }
1021
1022    fn set_height_notify(&mut self, height: f32) -> f32 {
1023        self.invalidate_layout();
1024        std::mem::replace(&mut self.height, height)
1025    }
1026
1027    /// Returns the current height of the widget.
1028    #[inline]
1029    pub fn height(&self) -> f32 {
1030        *self.height
1031    }
1032
1033    /// Sets the desired local position of the widget.
1034    #[inline]
1035    pub fn set_desired_local_position(&mut self, pos: Vector2<f32>) -> &mut Self {
1036        self.desired_local_position.set_value_and_mark_modified(pos);
1037        self
1038    }
1039
1040    /// Returns current screen-space position of the widget.
1041    #[inline]
1042    pub fn screen_position(&self) -> Vector2<f32> {
1043        Vector2::new(self.visual_transform[6], self.visual_transform[7])
1044    }
1045
1046    #[inline]
1047    pub(crate) fn add_child(&mut self, child: Handle<UiNode>, in_front: bool) {
1048        self.invalidate_layout();
1049        if in_front && !self.children.is_empty() {
1050            self.children.insert(0, child)
1051        } else {
1052            self.children.push(child)
1053        }
1054    }
1055
1056    /// Returns a reference to the slice with the children widgets of this widget.
1057    #[inline(always)]
1058    pub fn children(&self) -> &[Handle<UiNode>] {
1059        &self.children
1060    }
1061
1062    #[inline]
1063    pub(crate) fn clear_children(&mut self) {
1064        self.invalidate_layout();
1065        self.children.clear();
1066    }
1067
1068    #[inline]
1069    pub(crate) fn remove_child(&mut self, child: Handle<UiNode>) {
1070        if let Some(i) = self.children.iter().position(|h| *h == child) {
1071            self.children.remove(i);
1072            self.invalidate_layout();
1073        }
1074    }
1075
1076    /// Returns current parent handle of the widget.
1077    #[inline]
1078    pub fn parent(&self) -> Handle<UiNode> {
1079        self.parent
1080    }
1081
1082    /// Sets new
1083    #[inline]
1084    pub(super) fn set_parent(&mut self, parent: Handle<UiNode>) {
1085        self.parent = parent;
1086    }
1087
1088    /// Sets new column of the widget. Columns are used only by [`crate::grid::Grid`] widget.
1089    #[inline]
1090    pub fn set_column(&mut self, column: usize) -> &mut Self {
1091        self.column.set_value_and_mark_modified(column);
1092        self
1093    }
1094
1095    fn set_column_notify(&mut self, column: usize) -> usize {
1096        self.invalidate_layout();
1097        std::mem::replace(&mut self.column, column)
1098    }
1099
1100    /// Returns current column of the widget. Columns are used only by [`crate::grid::Grid`] widget.
1101    #[inline]
1102    pub fn column(&self) -> usize {
1103        *self.column
1104    }
1105
1106    /// Sets new row of the widget. Rows are used only by [`crate::grid::Grid`] widget.
1107    #[inline]
1108    pub fn set_row(&mut self, row: usize) -> &mut Self {
1109        self.row.set_value_and_mark_modified(row);
1110        self
1111    }
1112
1113    fn set_row_notify(&mut self, row: usize) -> usize {
1114        self.invalidate_layout();
1115        std::mem::replace(&mut self.row, row)
1116    }
1117
1118    /// Returns the current row of the widget. Rows are used only by [`crate::grid::Grid`] widget.
1119    #[inline]
1120    pub fn row(&self) -> usize {
1121        *self.row
1122    }
1123
1124    /// Returns the desired size of the widget.
1125    #[inline]
1126    pub fn desired_size(&self) -> Vector2<f32> {
1127        self.desired_size.get()
1128    }
1129
1130    /// Returns current desired local position of the widget.
1131    #[inline]
1132    pub fn desired_local_position(&self) -> Vector2<f32> {
1133        *self.desired_local_position
1134    }
1135
1136    fn set_desired_local_position_notify(&mut self, position: Vector2<f32>) -> Vector2<f32> {
1137        self.invalidate_layout();
1138        self.desired_local_position
1139            .set_value_and_mark_modified(position)
1140    }
1141
1142    /// Returns current screen-space bounds of the widget.
1143    #[inline]
1144    pub fn screen_bounds(&self) -> Rect<f32> {
1145        self.bounding_rect().transform(&self.visual_transform)
1146    }
1147
1148    /// Returns local-space bounding rect of the widget.
1149    #[inline]
1150    pub fn bounding_rect(&self) -> Rect<f32> {
1151        Rect::new(
1152            0.0,
1153            0.0,
1154            self.actual_local_size.get().x,
1155            self.actual_local_size.get().y,
1156        )
1157    }
1158
1159    /// Returns current visual transform of the widget.
1160    #[inline]
1161    pub fn visual_transform(&self) -> &Matrix3<f32> {
1162        &self.visual_transform
1163    }
1164
1165    /// Returns scaling along both axes.
1166    #[inline]
1167    pub fn visual_scaling(&self) -> Vector2<f32> {
1168        self.visual_transform
1169            .transform_vector(&Vector2::new(1.0, 1.0))
1170    }
1171
1172    /// Returns max uniform scaling of both axes.
1173    #[inline]
1174    pub fn visual_max_scaling(&self) -> f32 {
1175        self.visual_scaling().max()
1176    }
1177
1178    /// Sets new render transform.
1179    pub fn set_render_transform(&mut self, transform: Matrix3<f32>) {
1180        self.render_transform = transform;
1181        self.try_send_transform_changed_event();
1182    }
1183
1184    /// Returns current render transform of the widget.
1185    #[inline]
1186    pub fn render_transform(&self) -> &Matrix3<f32> {
1187        &self.render_transform
1188    }
1189
1190    /// Sets new layout transform.
1191    pub fn set_layout_transform(&mut self, transform: Matrix3<f32>) {
1192        self.layout_transform = transform;
1193        self.invalidate_layout();
1194    }
1195
1196    /// Returns current layout transform of the widget.
1197    #[inline]
1198    pub fn layout_transform(&self) -> &Matrix3<f32> {
1199        &self.layout_transform
1200    }
1201
1202    /// Returns `true`, if the widget has a descendant widget with the specified handle, `false` - otherwise.
1203    pub fn has_descendant(&self, node_handle: Handle<UiNode>, ui: &UserInterface) -> bool {
1204        for child_handle in self.children.iter() {
1205            if *child_handle == node_handle {
1206                return true;
1207            }
1208
1209            let result = ui
1210                .nodes
1211                .borrow(*child_handle)
1212                .has_descendant(node_handle, ui);
1213            if result {
1214                return true;
1215            }
1216        }
1217        false
1218    }
1219
1220    /// Searches a node up on tree starting from the given root that matches a criteria defined by the given func.
1221    pub fn find_by_criteria_up<Func: Fn(&UiNode) -> bool>(
1222        &self,
1223        ui: &UserInterface,
1224        func: Func,
1225    ) -> Handle<UiNode> {
1226        let mut parent_handle = self.parent;
1227        while parent_handle.is_some() {
1228            if let Ok(parent_node) = ui.nodes.try_borrow(parent_handle) {
1229                if func(parent_node) {
1230                    return parent_handle;
1231                }
1232                parent_handle = parent_node.parent;
1233            } else {
1234                break;
1235            }
1236        }
1237        Handle::NONE
1238    }
1239
1240    /// Handles incoming [`WidgetMessage`]s. This method **must** be called in [`crate::control::Control::handle_routed_message`]
1241    /// of any derived widgets!
1242    pub fn handle_routed_message(&mut self, ui: &mut UserInterface, msg: &mut UiMessage) {
1243        if let Some(msg) = msg.data_for::<WidgetMessage>(self.handle()) {
1244            match msg {
1245                &WidgetMessage::Opacity(opacity) => {
1246                    self.invalidate_visual();
1247                    self.opacity.set_value_and_mark_modified(opacity);
1248                }
1249                WidgetMessage::Background(background) => {
1250                    self.invalidate_visual();
1251                    *self.background = background.clone();
1252                }
1253                WidgetMessage::Foreground(foreground) => {
1254                    self.invalidate_visual();
1255                    *self.foreground = foreground.clone();
1256                }
1257                WidgetMessage::Name(name) => self.name = ImmutableString::new(name),
1258                &WidgetMessage::Width(width) => {
1259                    if *self.width != width {
1260                        self.set_width_notify(width);
1261                    }
1262                }
1263                &WidgetMessage::Height(height) => {
1264                    if *self.height != height {
1265                        self.set_height_notify(height);
1266                    }
1267                }
1268                WidgetMessage::VerticalAlignment(vertical_alignment) => {
1269                    if *self.vertical_alignment != *vertical_alignment {
1270                        self.set_vertical_alignment(*vertical_alignment);
1271                    }
1272                }
1273                WidgetMessage::HorizontalAlignment(horizontal_alignment) => {
1274                    if *self.horizontal_alignment != *horizontal_alignment {
1275                        self.set_horizontal_alignment(*horizontal_alignment);
1276                    }
1277                }
1278                WidgetMessage::MaxSize(max_size) => {
1279                    if *self.max_size != *max_size {
1280                        self.set_max_size_notify(*max_size);
1281                    }
1282                }
1283                WidgetMessage::MinSize(min_size) => {
1284                    if *self.min_size != *min_size {
1285                        self.set_min_size_notify(*min_size);
1286                    }
1287                }
1288                &WidgetMessage::Row(row) => {
1289                    if *self.row != row {
1290                        self.set_row_notify(row);
1291                    }
1292                }
1293                &WidgetMessage::Column(column) => {
1294                    if *self.column != column {
1295                        self.set_column_notify(column);
1296                    }
1297                }
1298                &WidgetMessage::Margin(margin) => {
1299                    if *self.margin != margin {
1300                        self.set_margin_notify(margin);
1301                    }
1302                }
1303                WidgetMessage::HitTestVisibility(hit_test_visibility) => {
1304                    self.hit_test_visibility
1305                        .set_value_and_mark_modified(*hit_test_visibility);
1306                }
1307                &WidgetMessage::Visibility(visibility) => {
1308                    self.set_visibility(visibility);
1309                }
1310                &WidgetMessage::DesiredPosition(pos) => {
1311                    if *self.desired_local_position != pos {
1312                        self.set_desired_local_position_notify(pos);
1313                    }
1314                }
1315                &WidgetMessage::Enabled(enabled) => {
1316                    self.invalidate_layout();
1317                    self.enabled.set_value_and_mark_modified(enabled);
1318                }
1319                &WidgetMessage::Cursor(icon) => {
1320                    self.cursor.set_value_and_mark_modified(icon);
1321                }
1322                WidgetMessage::LayoutTransform(transform) => {
1323                    if &self.layout_transform != transform {
1324                        self.set_layout_transform(*transform);
1325                    }
1326                }
1327                WidgetMessage::RenderTransform(transform) => {
1328                    self.set_render_transform(*transform);
1329                }
1330                WidgetMessage::ZIndex(index) => {
1331                    if *self.z_index != *index {
1332                        self.set_z_index(*index);
1333                        self.invalidate_layout();
1334                    }
1335                }
1336                WidgetMessage::SortChildren(predicate) => {
1337                    self.children
1338                        .sort_unstable_by(|a, b| predicate.0(*a, *b, ui));
1339                    self.invalidate_layout();
1340                }
1341                WidgetMessage::Style(style) => {
1342                    self.invalidate_visual();
1343                    self.background.update(style);
1344                    self.foreground.update(style);
1345                    self.style = Some(style.clone());
1346                }
1347                _ => (),
1348            }
1349        }
1350    }
1351
1352    /// Sets new vertical alignment of the widget.
1353    #[inline]
1354    pub fn set_vertical_alignment(&mut self, vertical_alignment: VerticalAlignment) -> &mut Self {
1355        self.vertical_alignment
1356            .set_value_and_mark_modified(vertical_alignment);
1357        self
1358    }
1359
1360    fn set_vertical_alignment_notify(
1361        &mut self,
1362        vertical_alignment: VerticalAlignment,
1363    ) -> VerticalAlignment {
1364        self.invalidate_layout();
1365        self.vertical_alignment
1366            .set_value_and_mark_modified(vertical_alignment)
1367    }
1368
1369    /// Returns current vertical alignment of the widget.
1370    #[inline]
1371    pub fn vertical_alignment(&self) -> VerticalAlignment {
1372        *self.vertical_alignment
1373    }
1374
1375    /// Sets new horizontal alignment of the widget.
1376    #[inline]
1377    pub fn set_horizontal_alignment(
1378        &mut self,
1379        horizontal_alignment: HorizontalAlignment,
1380    ) -> &mut Self {
1381        self.horizontal_alignment
1382            .set_value_and_mark_modified(horizontal_alignment);
1383        self
1384    }
1385
1386    fn set_horizontal_alignment_notify(
1387        &mut self,
1388        horizontal_alignment: HorizontalAlignment,
1389    ) -> HorizontalAlignment {
1390        self.invalidate_layout();
1391        self.horizontal_alignment
1392            .set_value_and_mark_modified(horizontal_alignment)
1393    }
1394
1395    /// Returns current horizontal alignment of the widget.
1396    #[inline]
1397    pub fn horizontal_alignment(&self) -> HorizontalAlignment {
1398        *self.horizontal_alignment
1399    }
1400
1401    /// Sets new margin of the widget.
1402    #[inline]
1403    pub fn set_margin(&mut self, margin: Thickness) -> &mut Self {
1404        self.margin.set_value_and_mark_modified(margin);
1405        self
1406    }
1407
1408    fn set_margin_notify(&mut self, margin: Thickness) -> Thickness {
1409        self.invalidate_layout();
1410        self.margin.set_value_and_mark_modified(margin)
1411    }
1412
1413    /// Returns the current margin of the widget.
1414    #[inline]
1415    pub fn margin(&self) -> Thickness {
1416        *self.margin
1417    }
1418
1419    /// Performs standard measurement of children nodes. It provides available size as a constraint and returns
1420    /// the maximum desired size across all children. As a result, this widget will have this size as its desired
1421    /// size to fit all the children nodes.
1422    #[inline]
1423    pub fn measure_override(
1424        &self,
1425        ui: &UserInterface,
1426        available_size: Vector2<f32>,
1427    ) -> Vector2<f32> {
1428        let mut size: Vector2<f32> = Vector2::default();
1429
1430        for &child in self.children.iter() {
1431            ui.measure_node(child, available_size);
1432            let desired_size = ui.node(child).desired_size();
1433            size.x = size.x.max(desired_size.x);
1434            size.y = size.y.max(desired_size.y);
1435        }
1436
1437        size
1438    }
1439
1440    /// Performs standard arrangement of the children nodes of the widget. It uses input final size to make a final
1441    /// bounding rectangle to arrange children. As a result, all the children nodes will be located in the top-left
1442    /// corner of this widget and stretched to fit its bounds.
1443    #[inline]
1444    pub fn arrange_override(&self, ui: &UserInterface, final_size: Vector2<f32>) -> Vector2<f32> {
1445        let final_rect = Rect::new(0.0, 0.0, final_size.x, final_size.y);
1446
1447        for &child in self.children.iter() {
1448            ui.arrange_node(child, &final_rect);
1449        }
1450
1451        final_size
1452    }
1453
1454    #[inline]
1455    pub(crate) fn commit_arrange(&self, position: Vector2<f32>, size: Vector2<f32>) {
1456        let old_actual_local_size = self.actual_local_size.replace(size);
1457        let old_actual_local_position = self.actual_local_position.replace(position);
1458        self.arrange_valid.set(true);
1459        if old_actual_local_position != position || old_actual_local_size != size {
1460            self.try_send_transform_changed_event();
1461        }
1462    }
1463
1464    fn try_send_transform_changed_event(&self) {
1465        if let Some(sender) = self.layout_events_sender.as_ref() {
1466            let _ = sender.send(LayoutEvent::TransformChanged(self.handle));
1467        }
1468    }
1469
1470    #[inline]
1471    pub(crate) fn set_children(&mut self, children: Vec<Handle<UiNode>>) {
1472        self.invalidate_layout();
1473        self.request_update_visibility();
1474        self.children = children;
1475    }
1476
1477    /// Returns `true` if the widget has a parent object in a resource from which it may restore
1478    /// values of its inheritable properties.
1479    #[inline]
1480    pub fn has_inheritance_parent(&self) -> bool {
1481        self.original_handle_in_resource.is_some() && self.resource.is_some()
1482    }
1483
1484    /// Returns `true` if the current results of arrangement of the widget are valid, `false` - otherwise.
1485    #[inline(always)]
1486    pub fn is_arrange_valid(&self) -> bool {
1487        self.arrange_valid.get()
1488    }
1489
1490    #[inline]
1491    pub(crate) fn commit_measure(&self, desired_size: Vector2<f32>) {
1492        self.desired_size.set(desired_size);
1493        self.measure_valid.set(true);
1494    }
1495
1496    /// Returns `true` if the current results of measurement of the widget are valid, `false` - otherwise.
1497    #[inline(always)]
1498    pub fn is_measure_valid(&self) -> bool {
1499        self.measure_valid.get()
1500    }
1501
1502    /// Returns current actual local position of the widget. It is valid only after layout pass!
1503    #[inline]
1504    pub fn actual_local_position(&self) -> Vector2<f32> {
1505        self.actual_local_position.get()
1506    }
1507
1508    /// Returns center point of the widget. It is valid only after layout pass!
1509    #[inline]
1510    pub fn center(&self) -> Vector2<f32> {
1511        self.actual_local_position() + self.actual_local_size().scale(0.5)
1512    }
1513
1514    #[inline]
1515    pub(crate) fn set_global_visibility(&mut self, value: bool) {
1516        self.prev_global_visibility = self.global_visibility;
1517        self.global_visibility = value;
1518    }
1519
1520    /// Returns `true` of the widget is globally visible, which means that all its parents are visible as well
1521    /// as this widget. It is valid only after the first update of the layout, otherwise if you will be always false.
1522    #[inline]
1523    pub fn is_globally_visible(&self) -> bool {
1524        self.global_visibility
1525    }
1526
1527    /// Sets new visibility of the widget.
1528    #[inline]
1529    pub fn set_visibility(&mut self, visibility: bool) -> &mut Self {
1530        if *self.visibility != visibility {
1531            self.set_visibility_notify(visibility);
1532        }
1533        self
1534    }
1535
1536    fn set_visibility_notify(&mut self, visibility: bool) -> bool {
1537        self.invalidate_layout();
1538        self.request_update_visibility();
1539        std::mem::replace(&mut self.visibility, visibility)
1540    }
1541
1542    /// Requests (via event queue, so the request is deferred) the update of the visibility of the widget.
1543    #[inline]
1544    pub fn request_update_visibility(&self) {
1545        if let Some(layout_events_sender) = self.layout_events_sender.as_ref() {
1546            let _ = layout_events_sender.send(LayoutEvent::VisibilityChanged(self.handle));
1547        }
1548    }
1549
1550    /// Returns current visibility of the widget.
1551    #[inline]
1552    pub fn visibility(&self) -> bool {
1553        *self.visibility
1554    }
1555
1556    /// Enables or disables the widget. Disabled widgets do not interact with user and usually greyed out.
1557    #[inline]
1558    pub fn set_enabled(&mut self, enabled: bool) -> &mut Self {
1559        self.enabled.set_value_and_mark_modified(enabled);
1560        self
1561    }
1562
1563    /// Returns `true` if the widget if enabled, `false` - otherwise.
1564    #[inline]
1565    pub fn enabled(&self) -> bool {
1566        *self.enabled
1567    }
1568
1569    /// Sets new cursor of the widget.
1570    #[inline]
1571    pub fn set_cursor(&mut self, cursor: Option<CursorIcon>) {
1572        self.cursor.set_value_and_mark_modified(cursor);
1573    }
1574
1575    /// Returns the current cursor of the widget.
1576    #[inline]
1577    pub fn cursor(&self) -> Option<CursorIcon> {
1578        *self.cursor
1579    }
1580
1581    /// Tries to fetch user-defined data of the specified type `T`.
1582    #[inline]
1583    pub fn user_data_cloned<T: Clone + 'static>(&self) -> Option<T> {
1584        self.user_data.as_ref().and_then(|v| {
1585            let guard = v.safe_lock();
1586            guard.downcast_ref::<T>().cloned()
1587        })
1588    }
1589
1590    /// Returns current clipping bounds of the widget. It is valid only after at least one layout pass.
1591    #[inline]
1592    pub fn clip_bounds(&self) -> Rect<f32> {
1593        self.clip_bounds.get()
1594    }
1595
1596    /// Set new opacity of the widget. Opacity should be in `[0.0..1.0]` range.
1597    #[inline]
1598    pub fn set_opacity(&mut self, opacity: Option<f32>) -> &mut Self {
1599        self.opacity.set_value_and_mark_modified(opacity);
1600        self
1601    }
1602
1603    /// Returns current opacity of the widget.
1604    #[inline]
1605    pub fn opacity(&self) -> Option<f32> {
1606        *self.opacity
1607    }
1608
1609    /// Returns current tooltip handle of the widget.
1610    #[inline]
1611    pub fn tooltip(&self) -> Option<RcUiNodeHandle> {
1612        self.tooltip.clone()
1613    }
1614
1615    /// Sets new tooltip handle of the widget (if any).
1616    #[inline]
1617    pub fn set_tooltip(&mut self, tooltip: Option<RcUiNodeHandle>) -> &mut Self {
1618        self.tooltip = tooltip;
1619        self
1620    }
1621
1622    /// Returns maximum available time to show the tooltip after the cursor was moved away from the widget.
1623    #[inline]
1624    pub fn tooltip_time(&self) -> f32 {
1625        self.tooltip_time
1626    }
1627
1628    /// Set the maximum available time to show the tooltip after the cursor was moved away from the widget.
1629    #[inline]
1630    pub fn set_tooltip_time(&mut self, tooltip_time: f32) -> &mut Self {
1631        self.tooltip_time = tooltip_time;
1632        self
1633    }
1634
1635    /// Returns current context menu of the widget.
1636    #[inline]
1637    pub fn context_menu(&self) -> Option<RcUiNodeHandle> {
1638        self.context_menu.clone()
1639    }
1640
1641    /// The context menu receives `PopupMessage`s for being displayed, and so should support those.
1642    #[inline]
1643    pub fn set_context_menu(&mut self, context_menu: Option<RcUiNodeHandle>) -> &mut Self {
1644        self.context_menu = context_menu;
1645        self
1646    }
1647}
1648
1649/// Implements `Deref<Target = Widget> + DerefMut` for your widget via the specified struct member.
1650/// It is used to reduce boilerplate code and make it less bug-prone.
1651#[macro_export]
1652macro_rules! define_widget_deref_proxy {
1653    ($ty:ty, $proxy:ident) => {
1654        impl std::ops::Deref for $ty {
1655            type Target = $crate::widget::Widget;
1656
1657            fn deref(&self) -> &Self::Target {
1658                &self.$proxy
1659            }
1660        }
1661
1662        impl std::ops::DerefMut for $ty {
1663            fn deref_mut(&mut self) -> &mut Self::Target {
1664                &mut self.$proxy
1665            }
1666        }
1667    };
1668}
1669
1670/// Implements `Deref<Target = Widget> + DerefMut` for your widget. It is used to reduce boilerplate code and
1671/// make it less bug-prone. The same as `define_widget_deref_proxy!(YourType, widget)`.
1672#[macro_export]
1673macro_rules! define_widget_deref {
1674    ($ty:ty) => {
1675        $crate::define_widget_deref_proxy!($ty, widget);
1676    };
1677}
1678
1679/// Widget builder creates [`Widget`] instances.
1680pub struct WidgetBuilder {
1681    /// Name of the widget.
1682    pub name: String,
1683    /// Width of the widget.
1684    pub width: f32,
1685    /// Height of the widget.
1686    pub height: f32,
1687    /// Desired position of the widget.
1688    pub desired_position: Vector2<f32>,
1689    /// Vertical alignment of the widget.
1690    pub vertical_alignment: VerticalAlignment,
1691    /// Horizontal alignment of the widget.
1692    pub horizontal_alignment: HorizontalAlignment,
1693    /// Max size of the widget.
1694    pub max_size: Option<Vector2<f32>>,
1695    /// Min size of the widget.
1696    pub min_size: Option<Vector2<f32>>,
1697    /// Background brush of the widget.
1698    pub background: Option<StyledProperty<Brush>>,
1699    /// Foreground brush of the widget.
1700    pub foreground: Option<StyledProperty<Brush>>,
1701    /// Row index of the widget.
1702    pub row: usize,
1703    /// Column index of the widget.
1704    pub column: usize,
1705    /// Margin of the widget.
1706    pub margin: Thickness,
1707    /// Children handles of the widget.
1708    pub children: Vec<Handle<UiNode>>,
1709    /// Whether the hit test is enabled or not.
1710    pub is_hit_test_visible: bool,
1711    /// Whether the widget is visible or not.
1712    pub visibility: bool,
1713    /// Z index of the widget.
1714    pub z_index: usize,
1715    /// Whether the dragging of the widget is allowed or not.
1716    pub allow_drag: bool,
1717    /// Whether the drop of the widget is allowed or not.
1718    pub allow_drop: bool,
1719    /// User-defined data.
1720    pub user_data: Option<Arc<Mutex<dyn Any + Send>>>,
1721    /// Whether to draw the widget on top of any other or not.
1722    pub draw_on_top: bool,
1723    /// Whether the widget is enabled or not.
1724    pub enabled: bool,
1725    /// Cursor of the widget.
1726    pub cursor: Option<CursorIcon>,
1727    /// Opacity of the widget.
1728    pub opacity: Option<f32>,
1729    /// Tooltip of the widget.
1730    pub tooltip: Option<RcUiNodeHandle>,
1731    /// Visibility interval (in seconds) of the tooltip of the widget.
1732    pub tooltip_time: f32,
1733    /// Context menu of the widget.
1734    pub context_menu: Option<RcUiNodeHandle>,
1735    /// Whether the preview messages is enabled or not.
1736    pub preview_messages: bool,
1737    /// Whether the widget will handle OS events or not.
1738    pub handle_os_events: bool,
1739    /// Whether the widget will be updated or not.
1740    pub need_update: bool,
1741    /// Layout transform of the widget.
1742    pub layout_transform: Matrix3<f32>,
1743    /// Render transform of the widget.
1744    pub render_transform: Matrix3<f32>,
1745    /// Whether the widget bounds should be clipped by its parent or not.
1746    pub clip_to_bounds: bool,
1747    /// Unique id of the widget.
1748    pub id: Uuid,
1749    /// Defines the order in which this widget will get keyboard focus when the Tab key is pressed.
1750    /// If set to [`None`], Tab key won't do anything on such widget. Default is [`None`].
1751    pub tab_index: Option<usize>,
1752    /// A flag, that defines whether the Tab key navigation is enabled or disabled for this widget.
1753    pub tab_stop: bool,
1754    /// A flag, that indicates that the widget accepts user input.
1755    pub accepts_input: bool,
1756    /// A material that will be used for rendering.
1757    pub material: WidgetMaterial,
1758    /// Style of the widget.
1759    pub style: StyleResource,
1760}
1761
1762impl Default for WidgetBuilder {
1763    fn default() -> Self {
1764        Self::new()
1765    }
1766}
1767
1768impl WidgetBuilder {
1769    /// Creates new widget builder with the default values.
1770    pub fn new() -> Self {
1771        Self {
1772            name: Default::default(),
1773            width: f32::NAN,
1774            height: f32::NAN,
1775            vertical_alignment: VerticalAlignment::default(),
1776            horizontal_alignment: HorizontalAlignment::default(),
1777            max_size: None,
1778            min_size: None,
1779            background: None,
1780            foreground: None,
1781            row: 0,
1782            column: 0,
1783            margin: Thickness::zero(),
1784            desired_position: Vector2::default(),
1785            children: Vec::new(),
1786            is_hit_test_visible: true,
1787            visibility: true,
1788            z_index: 0,
1789            allow_drag: false,
1790            allow_drop: false,
1791            user_data: None,
1792            draw_on_top: false,
1793            enabled: true,
1794            cursor: None,
1795            opacity: None,
1796            tooltip: Default::default(),
1797            tooltip_time: 0.1,
1798            context_menu: Default::default(),
1799            preview_messages: false,
1800            handle_os_events: false,
1801            need_update: false,
1802            layout_transform: Matrix3::identity(),
1803            render_transform: Matrix3::identity(),
1804            clip_to_bounds: true,
1805            id: Uuid::new_v4(),
1806            tab_index: None,
1807            tab_stop: false,
1808            accepts_input: false,
1809            material: Default::default(),
1810            style: DEFAULT_STYLE.resource.clone(),
1811        }
1812    }
1813
1814    /// Enables or disables message previewing of the widget. It basically defines whether the [`crate::Control::preview_message`] will
1815    /// be called or not.
1816    pub fn with_preview_messages(mut self, state: bool) -> Self {
1817        self.preview_messages = state;
1818        self
1819    }
1820
1821    /// Enables or disables OS event handling of the widget. It basically defines whether the [`crate::Control::handle_os_event`] will
1822    /// be called or not.
1823    pub fn with_handle_os_events(mut self, state: bool) -> Self {
1824        self.handle_os_events = state;
1825        self
1826    }
1827
1828    /// Enables or disables updating of the widget. It basically defines whether the [`crate::Control::update`] will
1829    /// be called or not.
1830    pub fn with_need_update(mut self, state: bool) -> Self {
1831        self.need_update = state;
1832        self
1833    }
1834
1835    /// Sets the desired width of the widget.
1836    pub fn with_width(mut self, width: f32) -> Self {
1837        self.width = width;
1838        self
1839    }
1840
1841    /// Sets the desired height of the widget.
1842    pub fn with_height(mut self, height: f32) -> Self {
1843        self.height = height;
1844        self
1845    }
1846
1847    /// Enables or disables clipping of widget's bound to its parent's bounds.
1848    pub fn with_clip_to_bounds(mut self, clip_to_bounds: bool) -> Self {
1849        self.clip_to_bounds = clip_to_bounds;
1850        self
1851    }
1852
1853    /// Enables or disables the widget.
1854    pub fn with_enabled(mut self, enabled: bool) -> Self {
1855        self.enabled = enabled;
1856        self
1857    }
1858
1859    /// Sets the desired vertical alignment of the widget.
1860    pub fn with_vertical_alignment(mut self, valign: VerticalAlignment) -> Self {
1861        self.vertical_alignment = valign;
1862        self
1863    }
1864
1865    /// Sets the desired horizontal alignment of the widget.
1866    pub fn with_horizontal_alignment(mut self, halign: HorizontalAlignment) -> Self {
1867        self.horizontal_alignment = halign;
1868        self
1869    }
1870
1871    /// Sets the max size of the widget.
1872    pub fn with_max_size(mut self, max_size: Vector2<f32>) -> Self {
1873        self.max_size = Some(max_size);
1874        self
1875    }
1876
1877    /// Sets the min size of the widget.
1878    pub fn with_min_size(mut self, min_size: Vector2<f32>) -> Self {
1879        self.min_size = Some(min_size);
1880        self
1881    }
1882
1883    /// Sets the desired background brush of the widget.
1884    pub fn with_background(mut self, brush: StyledProperty<Brush>) -> Self {
1885        self.background = Some(brush);
1886        self
1887    }
1888
1889    /// Sets the desired foreground brush of the widget.
1890    pub fn with_foreground(mut self, brush: StyledProperty<Brush>) -> Self {
1891        self.foreground = Some(brush);
1892        self
1893    }
1894
1895    /// Sets the desired row index of the widget.
1896    pub fn on_row(mut self, row: usize) -> Self {
1897        self.row = row;
1898        self
1899    }
1900
1901    /// Sets the desired column index of the widget.
1902    pub fn on_column(mut self, column: usize) -> Self {
1903        self.column = column;
1904        self
1905    }
1906
1907    /// Sets the desired margin of the widget.
1908    pub fn with_margin(mut self, margin: Thickness) -> Self {
1909        self.margin = margin;
1910        self
1911    }
1912
1913    /// Sets the desired, uniform margin of the widget.
1914    pub fn with_uniform_margin(mut self, margin: f32) -> Self {
1915        self.margin = Thickness::uniform(margin);
1916        self
1917    }
1918
1919    /// Sets the desired position of the widget.
1920    pub fn with_desired_position(mut self, desired_position: Vector2<f32>) -> Self {
1921        self.desired_position = desired_position;
1922        self
1923    }
1924
1925    /// Sets the desired layout transform of the widget.
1926    pub fn with_layout_transform(mut self, layout_transform: Matrix3<f32>) -> Self {
1927        self.layout_transform = layout_transform;
1928        self
1929    }
1930
1931    /// Sets the desired render transform of the widget.
1932    pub fn with_render_transform(mut self, render_transform: Matrix3<f32>) -> Self {
1933        self.render_transform = render_transform;
1934        self
1935    }
1936
1937    /// Sets the desired Z index of the widget.
1938    pub fn with_z_index(mut self, z_index: usize) -> Self {
1939        self.z_index = z_index;
1940        self
1941    }
1942
1943    /// Adds a child handle to the widget. [`Handle::NONE`] values are ignored.
1944    pub fn with_child(mut self, handle: Handle<impl ObjectOrVariant<UiNode>>) -> Self {
1945        if handle.is_some() {
1946            self.children.push(handle.to_base());
1947        }
1948        self
1949    }
1950
1951    /// Enables or disables top-most widget drawing.
1952    pub fn with_draw_on_top(mut self, draw_on_top: bool) -> Self {
1953        self.draw_on_top = draw_on_top;
1954        self
1955    }
1956
1957    /// Sets the desired set of children nodes.
1958    pub fn with_children<I: IntoIterator<Item = Handle<UiNode>>>(mut self, children: I) -> Self {
1959        for child in children.into_iter() {
1960            if child.is_some() {
1961                self.children.push(child)
1962            }
1963        }
1964        self
1965    }
1966
1967    /// Sets the desired widget name.
1968    pub fn with_name(mut self, name: &str) -> Self {
1969        self.name = String::from(name);
1970        self
1971    }
1972
1973    /// Enables or disables hit test of the widget.
1974    pub fn with_hit_test_visibility(mut self, state: bool) -> Self {
1975        self.is_hit_test_visible = state;
1976        self
1977    }
1978
1979    /// Sets the desired widget visibility.
1980    pub fn with_visibility(mut self, visibility: bool) -> Self {
1981        self.visibility = visibility;
1982        self
1983    }
1984
1985    /// Enables or disables the ability to drop other widgets on this widget.
1986    pub fn with_allow_drop(mut self, allow_drop: bool) -> Self {
1987        self.allow_drop = allow_drop;
1988        self
1989    }
1990
1991    /// Enables or disables dragging of the widget.
1992    pub fn with_allow_drag(mut self, allow_drag: bool) -> Self {
1993        self.allow_drag = allow_drag;
1994        self
1995    }
1996
1997    /// Sets the desired widget user data.
1998    pub fn with_user_data_value_opt<T: Any + Send>(mut self, user_data: Option<T>) -> Self {
1999        if let Some(data) = user_data {
2000            self.user_data = Some(Arc::new(Mutex::new(data)));
2001        }
2002        self
2003    }
2004
2005    /// Sets the desired widget user data.
2006    pub fn with_user_data_value<T: Any + Send>(self, user_data: T) -> Self {
2007        self.with_user_data_value_opt(Some(user_data))
2008    }
2009
2010    /// Sets the desired widget user data.
2011    pub fn with_user_data(mut self, user_data: Arc<Mutex<dyn Any + Send>>) -> Self {
2012        self.user_data = Some(user_data);
2013        self
2014    }
2015
2016    /// Sets the desired widget cursor.
2017    pub fn with_cursor(mut self, cursor: Option<CursorIcon>) -> Self {
2018        self.cursor = cursor;
2019        self
2020    }
2021
2022    /// Sets the desired widget opacity.
2023    pub fn with_opacity(mut self, opacity: Option<f32>) -> Self {
2024        self.opacity = opacity;
2025        self
2026    }
2027
2028    /// Sets the desired widget id.
2029    pub fn with_id(mut self, id: Uuid) -> Self {
2030        self.id = id;
2031        self
2032    }
2033
2034    /// Sets the desired tooltip for the node.
2035    ///
2036    /// ## Important
2037    ///
2038    /// The widget will share the tooltip, which means that when the widget will be deleted, the
2039    /// tooltip will be deleted only if there's no one using the tooltip anymore.
2040    pub fn with_tooltip(mut self, tooltip: RcUiNodeHandle) -> Self {
2041        self.tooltip = Some(tooltip);
2042        self
2043    }
2044
2045    /// Sets the desired tooltip for the node.
2046    ///
2047    /// ## Important
2048    ///
2049    /// The widget will share the tooltip, which means that when the widget will be deleted, the
2050    /// tooltip will be deleted only if there's no one using the tooltip anymore.
2051    pub fn with_opt_tooltip(mut self, tooltip: Option<RcUiNodeHandle>) -> Self {
2052        self.tooltip = tooltip;
2053        self
2054    }
2055
2056    /// Sets the desired tooltip time.
2057    pub fn with_tooltip_time(mut self, tooltip_time: f32) -> Self {
2058        self.tooltip_time = tooltip_time;
2059        self
2060    }
2061
2062    /// The context menu receives `PopupMessage`s for being displayed, and so should support those.
2063    pub fn with_context_menu(mut self, context_menu: RcUiNodeHandle) -> Self {
2064        self.context_menu = Some(context_menu);
2065        self
2066    }
2067
2068    /// Sets the desired tab index.
2069    pub fn with_tab_index(mut self, tab_index: Option<usize>) -> Self {
2070        self.tab_index = tab_index;
2071        self
2072    }
2073
2074    /// Sets a flag, that defines whether the Tab key navigation is enabled or disabled for this widget.
2075    pub fn with_tab_stop(mut self, tab_stop: bool) -> Self {
2076        self.tab_stop = tab_stop;
2077        self
2078    }
2079
2080    /// Sets a flag, that indicates that the widget accepts user input.
2081    pub fn with_accepts_input(mut self, accepts_input: bool) -> Self {
2082        self.accepts_input = accepts_input;
2083        self
2084    }
2085
2086    /// Sets a material which will be used for rendering of this widget.
2087    pub fn with_material(mut self, material: WidgetMaterial) -> Self {
2088        self.material = material;
2089        self
2090    }
2091
2092    /// Finishes building of the base widget.
2093    pub fn build(self, ctx: &BuildContext) -> Widget {
2094        Widget {
2095            handle: Default::default(),
2096            name: self.name.into(),
2097            desired_local_position: self.desired_position.into(),
2098            width: self.width.into(),
2099            height: self.height.into(),
2100            desired_size: Cell::new(Vector2::default()),
2101            actual_local_position: Cell::new(Vector2::default()),
2102            actual_local_size: Cell::new(Vector2::default()),
2103            min_size: self.min_size.unwrap_or_default().into(),
2104            max_size: self
2105                .max_size
2106                .unwrap_or_else(|| Vector2::new(f32::INFINITY, f32::INFINITY))
2107                .into(),
2108            background: self
2109                .background
2110                .unwrap_or_else(|| ctx.style.property(Style::BRUSH_PRIMARY))
2111                .into(),
2112            foreground: self
2113                .foreground
2114                .unwrap_or_else(|| ctx.style.property(Style::BRUSH_FOREGROUND))
2115                .into(),
2116            row: self.row.into(),
2117            column: self.column.into(),
2118            vertical_alignment: self.vertical_alignment.into(),
2119            horizontal_alignment: self.horizontal_alignment.into(),
2120            margin: self.margin.into(),
2121            visibility: self.visibility.into(),
2122            global_visibility: true,
2123            prev_global_visibility: false,
2124            children: self.children,
2125            parent: Handle::NONE,
2126            render_data_set: RefCell::new(Default::default()),
2127            is_mouse_directly_over: false,
2128            measure_valid: Cell::new(false),
2129            arrange_valid: Cell::new(false),
2130            hit_test_visibility: self.is_hit_test_visible.into(),
2131            prev_measure: Default::default(),
2132            prev_arrange: Default::default(),
2133            z_index: self.z_index.into(),
2134            allow_drag: self.allow_drag.into(),
2135            allow_drop: self.allow_drop.into(),
2136            user_data: self.user_data.clone(),
2137            draw_on_top: self.draw_on_top.into(),
2138            enabled: self.enabled.into(),
2139            cursor: self.cursor.into(),
2140            clip_bounds: Cell::new(Default::default()),
2141            opacity: self.opacity.into(),
2142            tooltip: self.tooltip,
2143            tooltip_time: self.tooltip_time,
2144            context_menu: self.context_menu,
2145            preview_messages: self.preview_messages,
2146            handle_os_events: self.handle_os_events,
2147            tab_index: self.tab_index.into(),
2148            tab_stop: self.tab_stop.into(),
2149            need_update: self.need_update,
2150            ignore_layout_rounding: false,
2151            accepts_input: self.accepts_input,
2152            layout_events_sender: None,
2153            layout_transform: self.layout_transform,
2154            render_transform: self.render_transform,
2155            visual_transform: Matrix3::identity(),
2156            clip_to_bounds: self.clip_to_bounds.into(),
2157            id: self.id,
2158            is_resource_instance_root: false,
2159            resource: None,
2160            material: self.material.into(),
2161            original_handle_in_resource: Default::default(),
2162            style: Some(ctx.style.clone()),
2163            visual_valid: Cell::new(false),
2164        }
2165    }
2166}