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}