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::style::DEFAULT_STYLE;
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 define_constructor,
40 message::{CursorIcon, Force, KeyCode, MessageDirection, UiMessage},
41 style::{
42 resource::{StyleResource, StyleResourceExt},
43 Style, StyledProperty,
44 },
45 BuildContext, HorizontalAlignment, LayoutEvent, MouseButton, MouseState, RcUiNodeHandle,
46 Thickness, UiNode, UserInterface, VerticalAlignment,
47};
48use fyrox_graph::BaseSceneGraph;
49use fyrox_material::{Material, MaterialResource};
50use fyrox_resource::Resource;
51use std::ops::{Deref, DerefMut};
52use std::{
53 any::Any,
54 cell::{Cell, RefCell},
55 cmp::Ordering,
56 fmt::{Debug, Formatter},
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 provides basic
89/// communication elements of the UI library.
90#[derive(Debug, Clone, PartialEq)]
91pub enum WidgetMessage {
92 /// Initiated when 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 user releases mouse button while 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 user scrolls mouse wheel while 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 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 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 [`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 [`MessageDirection::ToWidget`]
159 ///
160 /// Direction: **From UI/To UI**.
161 Focus,
162
163 /// Initiated when widget has lost its focus (when direction is [`MessageDirection::FromWidget`]). Can be used to
164 /// removed focus from widget if sent with [`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 user drags a widget over some other widget.
175 ///
176 /// Direction: **From UI**.
177 DragOver(Handle<UiNode>),
178
179 /// Initiated when 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 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 volume of 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 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 width of a widget. In most cases there is no need to explicitly set width of a widget,
239 /// because fyrox-ui uses automatic layout engine which will correctly calculate desired width of a widget.
240 ///
241 /// Direction: **From/To UI**
242 Width(f32),
243
244 /// A request to set height of a widget. In most cases there is no need to explicitly set height of a widget,
245 /// because fyrox-ui uses automatic layout engine which will correctly calculate 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 maximum size of widget. Maximum size restricts size of a widget during layout pass. For example
263 /// you can set maximum size to a button which was placed into a grid's cell, if maximum size wouldn't be set, button
264 /// would be stretched to fill entire cell.
265 ///
266 /// Direction: **From/To UI**
267 MaxSize(Vector2<f32>),
268
269 /// A request to set minimum size of widget. Minimum size restricts 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, button
271 /// would be compressed to fill 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 bad API and it should be changed in future. Grid should have 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 bad API and it should be changed in future. Grid should have 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 widget to make 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, 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 does 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 same hierarchy level, which means that it is impossible to set z index to 9999 (or similar huge value) to force
316 /// 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 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 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. 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. 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 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 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 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 define_constructor!(
456 /// Creates [`WidgetMessage::Remove`] message.
457 WidgetMessage:Remove => fn remove(), layout: false
458 );
459
460 define_constructor!(
461 /// Creates [`WidgetMessage::Unlink`] message.
462 WidgetMessage:Unlink => fn unlink(), layout: false
463 );
464
465 define_constructor!(
466 /// Creates [`WidgetMessage::LinkWith`] message.
467 WidgetMessage:LinkWith => fn link(Handle<UiNode>), layout: false
468 );
469
470 define_constructor!(
471 /// Creates [`WidgetMessage::LinkWithReverse`] message.
472 WidgetMessage:LinkWithReverse => fn link_reverse(Handle<UiNode>), layout: false
473 );
474
475 define_constructor!(
476 /// Creates [`WidgetMessage::ReplaceChildren`] message.
477 WidgetMessage:ReplaceChildren => fn replace_children(Vec<Handle<UiNode>>), layout: false
478 );
479
480 define_constructor!(
481 /// Creates [`WidgetMessage::Background`] message.
482 WidgetMessage:Background => fn background(StyledProperty<Brush>), layout: false
483 );
484
485 define_constructor!(
486 /// Creates [`WidgetMessage::Foreground`] message.
487 WidgetMessage:Foreground => fn foreground(StyledProperty<Brush>), layout: false
488 );
489
490 define_constructor!(
491 /// Creates [`WidgetMessage::Visibility`] message.
492 WidgetMessage:Visibility => fn visibility(bool), layout: false
493 );
494
495 define_constructor!(
496 /// Creates [`WidgetMessage::Width`] message.
497 WidgetMessage:Width => fn width(f32), layout: false
498 );
499
500 define_constructor!(
501 /// Creates [`WidgetMessage::Height`] message.
502 WidgetMessage:Height => fn height(f32), layout: false
503 );
504
505 define_constructor!(
506 /// Creates [`WidgetMessage::DesiredPosition`] message.
507 WidgetMessage:DesiredPosition => fn desired_position(Vector2<f32>), layout: false
508 );
509
510 define_constructor!(
511 /// Creates [`WidgetMessage::Center`] message.
512 WidgetMessage:Center => fn center(), layout: true
513 );
514
515 define_constructor!(
516 /// Creates [`WidgetMessage::AdjustPositionToFit`] message.
517 WidgetMessage:AdjustPositionToFit => fn adjust_position_to_fit(), layout: true
518 );
519
520 define_constructor!(
521 /// Creates [`WidgetMessage::Align`] message.
522 WidgetMessage:Align => fn align(
523 relative_to: Handle<UiNode>,
524 horizontal_alignment: HorizontalAlignment,
525 vertical_alignment: VerticalAlignment,
526 margin: Thickness),
527 layout: true
528 );
529
530 define_constructor!(
531 /// Creates [`WidgetMessage::Topmost`] message.
532 WidgetMessage:Topmost => fn topmost(), layout: false
533 );
534
535 define_constructor!(
536 /// Creates [`WidgetMessage::Lowermost`] message.
537 WidgetMessage:Lowermost => fn lowermost(), layout: false
538 );
539
540 define_constructor!(
541 /// Creates [`WidgetMessage::Enabled`] message.
542 WidgetMessage:Enabled => fn enabled(bool), layout: false
543 );
544
545 define_constructor!(
546 /// Creates [`WidgetMessage::Name`] message.
547 WidgetMessage:Name => fn name(String), layout: false
548 );
549
550 define_constructor!(
551 /// Creates [`WidgetMessage::Row`] message.
552 WidgetMessage:Row => fn row(usize), layout: false
553 );
554
555 define_constructor!(
556 /// Creates [`WidgetMessage::Column`] message.
557 WidgetMessage:Column => fn column(usize), layout: false
558 );
559
560 define_constructor!(
561 /// Creates [`WidgetMessage::Cursor`] message.
562 WidgetMessage:Cursor => fn cursor(Option<CursorIcon>), layout: false
563 );
564
565 define_constructor!(
566 /// Creates [`WidgetMessage::ZIndex`] message.
567 WidgetMessage:ZIndex => fn z_index(usize), layout: false
568 );
569
570 define_constructor!(
571 /// Creates [`WidgetMessage::HitTestVisibility`] message.
572 WidgetMessage:HitTestVisibility => fn hit_test_visibility(bool), layout: false
573 );
574
575 define_constructor!(
576 /// Creates [`WidgetMessage::Margin`] message.
577 WidgetMessage:Margin => fn margin(Thickness), layout: false
578 );
579
580 define_constructor!(
581 /// Creates [`WidgetMessage::MinSize`] message.
582 WidgetMessage:MinSize => fn min_size(Vector2<f32>), layout: false
583 );
584
585 define_constructor!(
586 /// Creates [`WidgetMessage::MaxSize`] message.
587 WidgetMessage:MaxSize => fn max_size(Vector2<f32>), layout: false
588 );
589
590 define_constructor!(
591 /// Creates [`WidgetMessage::HorizontalAlignment`] message.
592 WidgetMessage:HorizontalAlignment => fn horizontal_alignment(HorizontalAlignment), layout: false
593 );
594
595 define_constructor!(
596 /// Creates [`WidgetMessage::VerticalAlignment`] message.
597 WidgetMessage:VerticalAlignment => fn vertical_alignment(VerticalAlignment), layout: false
598 );
599
600 define_constructor!(
601 /// Creates [`WidgetMessage::Opacity`] message.
602 WidgetMessage:Opacity => fn opacity(Option<f32>), layout: false
603 );
604
605 define_constructor!(
606 /// Creates [`WidgetMessage::LayoutTransform`] message.
607 WidgetMessage:LayoutTransform => fn layout_transform(Matrix3<f32>), layout: false
608 );
609
610 define_constructor!(
611 /// Creates [`WidgetMessage::RenderTransform`] message.
612 WidgetMessage:RenderTransform => fn render_transform(Matrix3<f32>), layout: false
613 );
614
615 define_constructor!(
616 /// Creates [`WidgetMessage::ContextMenu`] message.
617 WidgetMessage:ContextMenu => fn context_menu(Option<RcUiNodeHandle>), layout: false
618 );
619
620 define_constructor!(
621 /// Creates [`WidgetMessage::Tooltip`] message.
622 WidgetMessage:Tooltip => fn tooltip(Option<RcUiNodeHandle>), layout: false
623 );
624
625 define_constructor!(
626 /// Creates [`WidgetMessage::Focus`] message.
627 WidgetMessage:Focus => fn focus(), layout: false
628 );
629
630 define_constructor!(
631 /// Creates [`WidgetMessage::Unfocus`] message.
632 WidgetMessage:Unfocus => fn unfocus(), layout: false
633 );
634
635 // Internal messages. Do not use.
636 define_constructor!(
637 /// Creates [`WidgetMessage::MouseDown`] message. This method is for internal use only, and should not
638 /// be used anywhere else.
639 WidgetMessage:MouseDown => fn mouse_down(pos: Vector2<f32>, button: MouseButton), layout: false
640 );
641
642 define_constructor!(
643 /// Creates [`WidgetMessage::MouseUp`] message. This method is for internal use only, and should not
644 /// be used anywhere else.
645 WidgetMessage:MouseUp => fn mouse_up(pos: Vector2<f32>, button: MouseButton), layout: false
646 );
647
648 define_constructor!(
649 /// Creates [`WidgetMessage::MouseMove`] message. This method is for internal use only, and should not
650 /// be used anywhere else.
651 WidgetMessage:MouseMove => fn mouse_move(pos: Vector2<f32>, state: MouseState), layout: false
652 );
653
654 define_constructor!(
655 /// Creates [`WidgetMessage::MouseWheel`] message. This method is for internal use only, and should not
656 /// be used anywhere else.
657 WidgetMessage:MouseWheel => fn mouse_wheel(pos: Vector2<f32>, amount: f32), layout: false
658 );
659
660 define_constructor!(
661 /// Creates [`WidgetMessage::MouseLeave`] message. This method is for internal use only, and should not
662 /// be used anywhere else.
663 WidgetMessage:MouseLeave => fn mouse_leave(), layout: false
664 );
665
666 define_constructor!(
667 /// Creates [`WidgetMessage::MouseEnter`] message. This method is for internal use only, and should not
668 /// be used anywhere else.
669 WidgetMessage:MouseEnter => fn mouse_enter(), layout: false
670 );
671
672 define_constructor!(
673 /// Creates [`WidgetMessage::Text`] message. This method is for internal use only, and should not
674 /// be used anywhere else.
675 WidgetMessage:Text => fn text(String), layout: false
676 );
677
678 define_constructor!(
679 /// Creates [`WidgetMessage::KeyDown`] message. This method is for internal use only, and should not
680 /// be used anywhere else.
681 WidgetMessage:KeyDown => fn key_down(KeyCode), layout: false
682 );
683
684 define_constructor!(
685 /// Creates [`WidgetMessage::KeyUp`] message. This method is for internal use only, and should not
686 /// be used anywhere else.
687 WidgetMessage:KeyUp => fn key_up(KeyCode), layout: false
688 );
689
690 define_constructor!(
691 /// Creates [`WidgetMessage::DragStarted`] message. This method is for internal use only, and should not
692 /// be used anywhere else.
693 WidgetMessage:DragStarted => fn drag_started(Handle<UiNode>), layout: false
694 );
695
696 define_constructor!(
697 /// Creates [`WidgetMessage::DragOver`] message. This method is for internal use only, and should not
698 /// be used anywhere else.
699 WidgetMessage:DragOver => fn drag_over(Handle<UiNode>), layout: false
700 );
701
702 define_constructor!(
703 /// Creates [`WidgetMessage::Drop`] message. This method is for internal use only, and should not
704 /// be used anywhere else.
705 WidgetMessage:Drop => fn drop(Handle<UiNode>), layout: false
706 );
707
708 define_constructor!(
709 /// Creates [`WidgetMessage::DoubleClick`] message. This method is for internal use only, and should not
710 /// be used anywhere else.
711 WidgetMessage:DoubleClick => fn double_click(button: MouseButton), layout: false
712 );
713
714 define_constructor!(
715 /// Creates [`WidgetMessage::TouchStarted`] message. This method is for internal use only, and should not
716 /// be used anywhere else.
717 WidgetMessage:TouchStarted => fn touch_started(pos: Vector2<f32>, force: Option<Force>, id: u64), layout: false
718 );
719
720 define_constructor!(
721 /// Creates [`WidgetMessage::TouchEnded`] message. This method is for internal use only, and should not
722 /// be used anywhere else.
723 WidgetMessage:TouchEnded => fn touch_ended(pos: Vector2<f32>, id: u64), layout: false
724 );
725
726 define_constructor!(
727 /// Creates [`WidgetMessage::TouchMoved`] message. This method is for internal use only, and should not
728 /// be used anywhere else.
729 WidgetMessage:TouchMoved => fn touch_moved(pos: Vector2<f32>, force: Option<Force>, id: u64), layout: false
730 );
731
732 define_constructor!(
733 /// Creates [`WidgetMessage::TouchCancelled`] message. This method is for internal use only, and should not
734 /// be used anywhere else.
735 WidgetMessage:TouchCancelled => fn touch_cancelled(pos: Vector2<f32>, id: u64), layout: false
736 );
737
738 define_constructor!(
739 /// Creates [`WidgetMessage::DoubleTap`] message. This method is for internal use only, and should not
740 /// be used anywhere else.
741 WidgetMessage:DoubleTap => fn double_tap(pos: Vector2<f32>, force: Option<Force>, id: u64), layout: false
742 );
743
744 define_constructor!(
745 /// Creates [`WidgetMessage::SortChildren`] message.
746 WidgetMessage:SortChildren => fn sort_children(SortingPredicate), layout: false
747 );
748
749 define_constructor!(
750 /// Creates [`WidgetMessage::Style`] message.
751 WidgetMessage:Style => fn style(StyleResource), layout: false
752 );
753
754 define_constructor!(
755 /// Creates [`WidgetMessage::ResetVisual`] message.
756 WidgetMessage:ResetVisual => fn reset_visual(), layout: false
757 );
758}
759
760#[doc(hidden)]
761#[derive(Clone, Debug, Reflect, PartialEq)]
762pub struct WidgetMaterial(pub MaterialResource);
763
764impl Visit for WidgetMaterial {
765 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
766 self.0.visit(name, visitor)
767 }
768}
769
770impl Default for WidgetMaterial {
771 fn default() -> Self {
772 Self(MaterialResource::new_embedded(Material::standard_widget()))
773 }
774}
775
776impl Deref for WidgetMaterial {
777 type Target = MaterialResource;
778
779 fn deref(&self) -> &Self::Target {
780 &self.0
781 }
782}
783
784impl DerefMut for WidgetMaterial {
785 fn deref_mut(&mut self) -> &mut Self::Target {
786 &mut self.0
787 }
788}
789
790/// Widget is a base UI element, that is always used to build derived, more complex, widgets. In general, it is a container
791/// for layout information, basic visual appearance, visibility options, parent-child information. It does almost nothing
792/// on its own, instead, the user interface modifies its state accordingly.
793#[derive(Default, Debug, Clone, Reflect, Visit)]
794#[visit(optional)]
795pub struct Widget {
796 /// Self handle of the widget. It is valid **only**, if the widget is added to the user interface, in other
797 /// cases it will most likely be [`Handle::NONE`].
798 #[reflect(hidden)]
799 pub handle: Handle<UiNode>,
800 /// Name of the widget. Could be useful for debugging purposes.
801 pub name: ImmutableString,
802 /// Desired position relative to the parent node. It is just a recommendation for the layout system, actual position
803 /// will be stored in the `actual_local_position` field and can be fetched using [`Widget::actual_local_position`]
804 /// method.
805 #[reflect(setter = "set_desired_local_position_notify")]
806 pub desired_local_position: InheritableVariable<Vector2<f32>>,
807 /// Explicit width for the widget, or automatic if [`f32::NAN`] (means the value is undefined). Default is [`f32::NAN`].
808 #[reflect(setter = "set_width_notify")]
809 pub width: InheritableVariable<f32>,
810 /// Explicit height for the widget, or automatic if [`f32::NAN`] (means the value is undefined). Default is [`f32::NAN`].
811 #[reflect(setter = "set_height_notify")]
812 pub height: InheritableVariable<f32>,
813 /// Minimum width and height. Default is 0.0 for both axes.
814 #[reflect(setter = "set_min_size_notify")]
815 pub min_size: InheritableVariable<Vector2<f32>>,
816 /// Maximum width and height. Default is [`f32::INFINITY`] for both axes.
817 #[reflect(setter = "set_max_size_notify")]
818 pub max_size: InheritableVariable<Vector2<f32>>,
819 /// Background brush of the widget.
820 pub background: InheritableVariable<StyledProperty<Brush>>,
821 /// Foreground brush of the widget.
822 pub foreground: InheritableVariable<StyledProperty<Brush>>,
823 /// Index of the row to which this widget belongs to. It is valid only in when used in [`crate::grid::Grid`] widget.
824 #[reflect(setter = "set_row_notify")]
825 pub row: InheritableVariable<usize>,
826 /// Index of the column to which this widget belongs to. It is valid only in when used in [`crate::grid::Grid`] widget.
827 #[reflect(setter = "set_column_notify")]
828 pub column: InheritableVariable<usize>,
829 /// Vertical alignment of the widget.
830 #[reflect(setter = "set_vertical_alignment_notify")]
831 pub vertical_alignment: InheritableVariable<VerticalAlignment>,
832 /// Horizontal alignment of the widget.
833 #[reflect(setter = "set_horizontal_alignment_notify")]
834 pub horizontal_alignment: InheritableVariable<HorizontalAlignment>,
835 /// Margin for every sides of bounding rectangle. See [`Thickness`] docs for more info.
836 #[reflect(setter = "set_margin_notify")]
837 pub margin: InheritableVariable<Thickness>,
838 /// Current, **local**, visibility state of the widget.
839 #[reflect(setter = "set_visibility_notify")]
840 pub visibility: InheritableVariable<bool>,
841 /// Current, **global** (including the chain of parent widgets), visibility state of the widget.
842 #[reflect(hidden)]
843 pub global_visibility: bool,
844 /// A set of handles to children nodes of this widget.
845 #[reflect(hidden)]
846 pub children: Vec<Handle<UiNode>>,
847 /// A handle to the parent node of this widget.
848 #[reflect(hidden)]
849 pub parent: Handle<UiNode>,
850 /// Indices of drawing commands in the drawing context emitted by this widget. It is used for picking.
851 #[reflect(hidden)]
852 #[visit(skip)]
853 pub command_indices: RefCell<Vec<usize>>,
854 /// A flag, that indicates that the mouse is directly over the widget. It will be raised only for top-most widget in the
855 /// "stack" of widgets.
856 #[reflect(hidden)]
857 pub is_mouse_directly_over: bool,
858 /// A flag, that defines whether the widget is "visible" for hit testing (picking). Could be useful to prevent some widgets
859 /// from any interactions with mouse.
860 pub hit_test_visibility: InheritableVariable<bool>,
861 /// Index of the widget in parent's children list that defines its order in drawing and picking.
862 pub z_index: InheritableVariable<usize>,
863 /// A flag, that defines whether the drag from drag'n'drop functionality can be started by the widget or not.
864 pub allow_drag: InheritableVariable<bool>,
865 /// A flag, that defines whether the drop from drag'n'drop functionality can be accepted by the widget or not.
866 pub allow_drop: InheritableVariable<bool>,
867 /// Style of the widget.
868 pub style: Option<StyleResource>,
869 /// Optional, user-defined data.
870 #[reflect(hidden)]
871 #[visit(skip)]
872 pub user_data: Option<Arc<Mutex<dyn Any + Send>>>,
873 /// A flag, that defines whether the widget should be drawn in a separate drawind pass after any other widget that draws
874 /// normally.
875 pub draw_on_top: InheritableVariable<bool>,
876 /// A flag, that defines whether the widget is enabled or not. Disabled widgets cannot be interacted by used and they're
877 /// greyed out.
878 pub enabled: InheritableVariable<bool>,
879 /// Optional cursor icon that will be used for mouse cursor when hovering over the widget.
880 pub cursor: InheritableVariable<Option<CursorIcon>>,
881 /// Optional opacity of the widget. It should be in `[0.0..1.0]` range, where 0.0 - fully transparent, 1.0 - fully opaque.
882 pub opacity: InheritableVariable<Option<f32>>,
883 /// An optional ref counted handle to a tooltip used by the widget.
884 pub tooltip: Option<RcUiNodeHandle>,
885 /// Maximum available time to show the tooltip after the cursor was moved away from the widget.
886 pub tooltip_time: f32,
887 /// An optional ref counted handle to a context menu used by the widget.
888 pub context_menu: Option<RcUiNodeHandle>,
889 /// A flag, that defines whether the widget should be clipped by the parent bounds or not.
890 pub clip_to_bounds: InheritableVariable<bool>,
891 /// Current render transform of the node. It modifies layout information of the widget, as well as it affects visual transform
892 /// of the widget.
893 #[reflect(hidden)]
894 layout_transform: Matrix3<f32>,
895 /// Current render transform of the node. It only modifies the widget at drawing stage, layout information remains unmodified.
896 #[reflect(hidden)]
897 render_transform: Matrix3<f32>,
898 /// Current visual transform of the node. It always contains a result of mixing the layout and
899 /// render transformation matrices. Visual transform could be used to transform a point to
900 /// screen space. To transform a screen space point to local coordinates use [`Widget::screen_to_local`]
901 /// method.
902 #[reflect(hidden)]
903 pub visual_transform: Matrix3<f32>,
904 /// A flag, that defines whether the widget will preview UI messages or not. Basically, it defines whether [crate::Control::preview_message]
905 /// is called or not.
906 pub preview_messages: bool,
907 /// A flag, that defines whether the widget will receive any OS events or not. Basically, it defines whether [crate::Control::handle_os_event]
908 /// is called or not.
909 pub handle_os_events: bool,
910 /// Defines the order in which this widget will get keyboard focus when Tab key is pressed.
911 /// If set to [`None`], Tab key won't do anything on such widget. Default is [`None`].
912 pub tab_index: InheritableVariable<Option<usize>>,
913 /// A flag, that defines whether the Tab key navigation is enabled or disabled for this widget.
914 pub tab_stop: InheritableVariable<bool>,
915 /// A flag, that defines whether the widget will be update or not. Basically, it defines whether [crate::Control::update]
916 /// is called or not.
917 pub need_update: bool,
918 /// Enables (`false`) or disables (`true`) layout rounding.
919 pub ignore_layout_rounding: bool,
920 /// A flag, that indicates that the widget accepts user input. It could be used to determine, if
921 /// a user can interact with the widget using keyboard. It is also used for automatic assignment
922 /// of the tab index. Keep in mind, that this flag is only a marker and does not do anything else
923 /// on its own. Default value is `false`.
924 pub accepts_input: bool,
925 /// Internal sender for layout events.
926 #[reflect(hidden)]
927 #[visit(skip)]
928 pub layout_events_sender: Option<Sender<LayoutEvent>>,
929 /// Unique identifier of the widget.
930 pub id: Uuid,
931 /// A flag, that indicates whether this widget is a root widget of a hierarchy of widgets
932 /// instantiated from a resource.
933 #[reflect(hidden)]
934 pub is_resource_instance_root: bool,
935 /// A resource from which this widget was instantiated from, can work in pair with `original`
936 /// handle to get a corresponding widget from resource.
937 #[reflect(read_only)]
938 pub resource: Option<Resource<UserInterface>>,
939 /// A material, that should be used when rendering the widget.
940 pub material: InheritableVariable<WidgetMaterial>,
941 /// Handle to a widget in a user interface resource from which this node was instantiated from.
942 #[reflect(hidden)]
943 pub original_handle_in_resource: Handle<UiNode>,
944 //
945 // Layout. Interior mutability is a must here because layout performed in a series of recursive calls.
946 //
947 /// A flag, that defines whether the measurement results are still valid or not.
948 #[reflect(hidden)]
949 #[visit(skip)]
950 pub measure_valid: Cell<bool>,
951 /// A flag, that defines whether the arrangement results are still valid or not.
952 #[reflect(hidden)]
953 #[visit(skip)]
954 pub arrange_valid: Cell<bool>,
955 /// Results or previous measurement.
956 #[reflect(hidden)]
957 #[visit(skip)]
958 pub prev_measure: Cell<Vector2<f32>>,
959 /// Results or previous arrangement.
960 #[reflect(hidden)]
961 #[visit(skip)]
962 pub prev_arrange: Cell<Rect<f32>>,
963 /// Desired size of the node after Measure pass.
964 #[reflect(hidden)]
965 #[visit(skip)]
966 pub desired_size: Cell<Vector2<f32>>,
967 /// Actual local position of the widget after Arrange pass.
968 #[reflect(hidden)]
969 #[visit(skip)]
970 pub actual_local_position: Cell<Vector2<f32>>,
971 /// Actual local size of the widget after Arrange pass.
972 #[reflect(hidden)]
973 #[visit(skip)]
974 pub actual_local_size: Cell<Vector2<f32>>,
975 /// Previous global visibility of the widget.
976 #[reflect(hidden)]
977 #[visit(skip)]
978 pub prev_global_visibility: bool,
979 /// Current clip bounds of the widget.
980 #[reflect(hidden)]
981 #[visit(skip)]
982 pub clip_bounds: Cell<Rect<f32>>,
983}
984
985impl Widget {
986 /// Returns self handle of the widget.
987 #[inline]
988 pub fn handle(&self) -> Handle<UiNode> {
989 self.handle
990 }
991
992 /// Returns the name of the widget.
993 #[inline]
994 pub fn name(&self) -> &str {
995 self.name.as_str()
996 }
997
998 /// Sets the new name of the widget.
999 #[inline]
1000 pub fn set_name<P: AsRef<str>>(&mut self, name: P) -> &mut Self {
1001 self.name = ImmutableString::new(name);
1002 self
1003 }
1004
1005 /// Returns the actual size of the widget after the full layout cycle.
1006 #[inline]
1007 pub fn actual_local_size(&self) -> Vector2<f32> {
1008 self.actual_local_size.get()
1009 }
1010
1011 /// Returns size of the widget without any layout or rendering transform applied.
1012 #[inline]
1013 pub fn actual_initial_size(&self) -> Vector2<f32> {
1014 Rect::new(
1015 0.0,
1016 0.0,
1017 self.actual_local_size.get().x,
1018 self.actual_local_size.get().y,
1019 )
1020 .transform(&self.visual_transform.try_inverse().unwrap_or_default())
1021 .size
1022 }
1023
1024 /// Returns the actual global size of the widget after the full layout cycle.
1025 #[inline]
1026 pub fn actual_global_size(&self) -> Vector2<f32> {
1027 self.screen_bounds().size
1028 }
1029
1030 /// Sets the new minimum size of the widget.
1031 #[inline]
1032 pub fn set_min_size(&mut self, value: Vector2<f32>) -> &mut Self {
1033 self.min_size.set_value_and_mark_modified(value);
1034 self
1035 }
1036
1037 fn set_min_size_notify(&mut self, value: Vector2<f32>) -> Vector2<f32> {
1038 self.invalidate_layout();
1039 self.min_size.set_value_and_mark_modified(value)
1040 }
1041
1042 /// Sets the new minimum width of the widget.
1043 #[inline]
1044 pub fn set_min_width(&mut self, value: f32) -> &mut Self {
1045 self.min_size.x = value;
1046 self
1047 }
1048
1049 /// Sets the new minimum height of the widget.
1050 #[inline]
1051 pub fn set_min_height(&mut self, value: f32) -> &mut Self {
1052 self.min_size.y = value;
1053 self
1054 }
1055
1056 /// Sets the new minimum size of the widget.
1057 #[inline]
1058 pub fn min_size(&self) -> Vector2<f32> {
1059 *self.min_size
1060 }
1061
1062 /// Returns the minimum width of the widget.
1063 #[inline]
1064 pub fn min_width(&self) -> f32 {
1065 self.min_size.x
1066 }
1067
1068 /// Returns the minimum height of the widget.
1069 #[inline]
1070 pub fn min_height(&self) -> f32 {
1071 self.min_size.y
1072 }
1073
1074 /// Return `true` if the dragging of the widget is allowed, `false` - otherwise.
1075 #[inline]
1076 pub fn is_drag_allowed(&self) -> bool {
1077 *self.allow_drag
1078 }
1079
1080 /// Return `true` if the dropping of other widgets is allowed on this widget, `false` - otherwise.
1081 #[inline]
1082 pub fn is_drop_allowed(&self) -> bool {
1083 *self.allow_drop
1084 }
1085
1086 /// Maps the given point from screen to local widget's coordinates. Could be used to transform
1087 /// mouse cursor position (which is in screen space) to local widget coordinates.
1088 #[inline]
1089 pub fn screen_to_local(&self, point: Vector2<f32>) -> Vector2<f32> {
1090 self.visual_transform
1091 .try_inverse()
1092 .unwrap_or_default()
1093 .transform_point(&Point2::from(point))
1094 .coords
1095 }
1096
1097 /// Invalidates layout of the widget. **WARNING**: Do not use this method, unless you understand what you're doing,
1098 /// it will cause new layout pass for this widget which could be quite heavy and doing so on every frame for multiple
1099 /// widgets **will** cause severe performance issues.
1100 #[inline]
1101 pub fn invalidate_layout(&self) {
1102 self.invalidate_measure();
1103 self.invalidate_arrange();
1104 self.try_send_transform_changed_event();
1105 }
1106
1107 pub(crate) fn notify_z_index_changed(&self) {
1108 if let Some(sender) = self.layout_events_sender.as_ref() {
1109 sender
1110 .send(LayoutEvent::ZIndexChanged(self.handle))
1111 .unwrap()
1112 }
1113 }
1114
1115 /// Invalidates measurement results of the widget. **WARNING**: Do not use this method, unless you understand what you're
1116 /// doing, it will cause new measurement pass for this widget which could be quite heavy and doing so on every frame for
1117 /// multiple widgets **will** cause severe performance issues.
1118 #[inline]
1119 pub fn invalidate_measure(&self) {
1120 self.measure_valid.set(false);
1121
1122 if let Some(layout_events_sender) = self.layout_events_sender.as_ref() {
1123 let _ = layout_events_sender.send(LayoutEvent::MeasurementInvalidated(self.handle));
1124 }
1125 }
1126
1127 /// Invalidates arrangement results of the widget. **WARNING**: Do not use this method, unless you understand what you're
1128 /// doing, it will cause new arrangement pass for this widget which could be quite heavy and doing so on every frame for
1129 /// multiple widgets **will** cause severe performance issues.
1130 #[inline]
1131 pub fn invalidate_arrange(&self) {
1132 self.arrange_valid.set(false);
1133
1134 if let Some(layout_events_sender) = self.layout_events_sender.as_ref() {
1135 let _ = layout_events_sender.send(LayoutEvent::ArrangementInvalidated(self.handle));
1136 }
1137 }
1138
1139 /// Returns `true` if the widget is able to participate in hit testing, `false` - otherwise.
1140 #[inline]
1141 pub fn is_hit_test_visible(&self) -> bool {
1142 *self.hit_test_visibility
1143 }
1144
1145 /// Sets the new maximum size of the widget.
1146 #[inline]
1147 pub fn set_max_size(&mut self, value: Vector2<f32>) -> &mut Self {
1148 self.max_size.set_value_and_mark_modified(value);
1149 self
1150 }
1151
1152 fn set_max_size_notify(&mut self, value: Vector2<f32>) -> Vector2<f32> {
1153 self.invalidate_layout();
1154 std::mem::replace(&mut self.max_size, value)
1155 }
1156
1157 /// Returns current maximum size of the widget.
1158 #[inline]
1159 pub fn max_size(&self) -> Vector2<f32> {
1160 *self.max_size
1161 }
1162
1163 /// Returns maximum width of the widget.
1164 #[inline]
1165 pub fn max_width(&self) -> f32 {
1166 self.max_size.x
1167 }
1168
1169 /// Return maximum height of the widget.
1170 #[inline]
1171 pub fn max_height(&self) -> f32 {
1172 self.max_size.y
1173 }
1174
1175 /// Sets new Z index for the widget. Z index defines the sorting (stable) index which will be used to "arrange" widgets
1176 /// in the correct order.
1177 #[inline]
1178 pub fn set_z_index(&mut self, z_index: usize) -> &mut Self {
1179 self.z_index.set_value_and_mark_modified(z_index);
1180 self.notify_z_index_changed();
1181 self
1182 }
1183
1184 /// Returns current Z index of the widget.
1185 #[inline]
1186 pub fn z_index(&self) -> usize {
1187 *self.z_index
1188 }
1189
1190 /// Sets the new background of the widget.
1191 #[inline]
1192 pub fn set_background(&mut self, brush: Brush) -> &mut Self {
1193 self.background.property = brush;
1194 self
1195 }
1196
1197 /// Returns current background of the widget.
1198 #[inline]
1199 pub fn background(&self) -> Brush {
1200 self.background.property.clone()
1201 }
1202
1203 /// Sets new foreground of the widget.
1204 #[inline]
1205 pub fn set_foreground(&mut self, brush: Brush) -> &mut Self {
1206 self.foreground.property = brush;
1207 self
1208 }
1209
1210 /// Returns current foreground of the widget.
1211 #[inline]
1212 pub fn foreground(&self) -> Brush {
1213 self.foreground.property.clone()
1214 }
1215
1216 /// Sets new width of the widget.
1217 #[inline]
1218 pub fn set_width(&mut self, width: f32) -> &mut Self {
1219 self.width
1220 .set_value_and_mark_modified(width.clamp(self.min_size.x, self.max_size.x));
1221 self
1222 }
1223
1224 fn set_width_notify(&mut self, width: f32) -> f32 {
1225 self.invalidate_layout();
1226 std::mem::replace(&mut self.width, width)
1227 }
1228
1229 /// Returns current width of the widget.
1230 #[inline]
1231 pub fn width(&self) -> f32 {
1232 *self.width
1233 }
1234
1235 /// Return `true` if the widget is set to be drawn on top of every other, normally drawn, widgets, `false` - otherwise.
1236 pub fn is_draw_on_top(&self) -> bool {
1237 *self.draw_on_top
1238 }
1239
1240 /// Sets new height of the widget.
1241 #[inline]
1242 pub fn set_height(&mut self, height: f32) -> &mut Self {
1243 self.height
1244 .set_value_and_mark_modified(height.clamp(self.min_size.y, self.max_size.y));
1245 self
1246 }
1247
1248 fn set_height_notify(&mut self, height: f32) -> f32 {
1249 self.invalidate_layout();
1250 std::mem::replace(&mut self.height, height)
1251 }
1252
1253 /// Returns current height of the widget.
1254 #[inline]
1255 pub fn height(&self) -> f32 {
1256 *self.height
1257 }
1258
1259 /// Sets the desired local position of the widget.
1260 #[inline]
1261 pub fn set_desired_local_position(&mut self, pos: Vector2<f32>) -> &mut Self {
1262 self.desired_local_position.set_value_and_mark_modified(pos);
1263 self
1264 }
1265
1266 /// Returns current screen-space position of the widget.
1267 #[inline]
1268 pub fn screen_position(&self) -> Vector2<f32> {
1269 Vector2::new(self.visual_transform[6], self.visual_transform[7])
1270 }
1271
1272 #[inline]
1273 pub(crate) fn add_child(&mut self, child: Handle<UiNode>, in_front: bool) {
1274 self.invalidate_layout();
1275 if in_front && !self.children.is_empty() {
1276 self.children.insert(0, child)
1277 } else {
1278 self.children.push(child)
1279 }
1280 }
1281
1282 /// Returns a reference to the slice with the children widgets of this widget.
1283 #[inline(always)]
1284 pub fn children(&self) -> &[Handle<UiNode>] {
1285 &self.children
1286 }
1287
1288 #[inline]
1289 pub(crate) fn clear_children(&mut self) {
1290 self.invalidate_layout();
1291 self.children.clear();
1292 }
1293
1294 #[inline]
1295 pub(crate) fn remove_child(&mut self, child: Handle<UiNode>) {
1296 if let Some(i) = self.children.iter().position(|h| *h == child) {
1297 self.children.remove(i);
1298 self.invalidate_layout();
1299 }
1300 }
1301
1302 /// Returns current parent handle of the widget.
1303 #[inline]
1304 pub fn parent(&self) -> Handle<UiNode> {
1305 self.parent
1306 }
1307
1308 /// Sets new
1309 #[inline]
1310 pub(super) fn set_parent(&mut self, parent: Handle<UiNode>) {
1311 self.parent = parent;
1312 }
1313
1314 /// Sets new column of the widget. Columns are used only by [`crate::grid::Grid`] widget.
1315 #[inline]
1316 pub fn set_column(&mut self, column: usize) -> &mut Self {
1317 self.column.set_value_and_mark_modified(column);
1318 self
1319 }
1320
1321 fn set_column_notify(&mut self, column: usize) -> usize {
1322 self.invalidate_layout();
1323 std::mem::replace(&mut self.column, column)
1324 }
1325
1326 /// Returns current column of the widget. Columns are used only by [`crate::grid::Grid`] widget.
1327 #[inline]
1328 pub fn column(&self) -> usize {
1329 *self.column
1330 }
1331
1332 /// Sets new row of the widget. Rows are used only by [`crate::grid::Grid`] widget.
1333 #[inline]
1334 pub fn set_row(&mut self, row: usize) -> &mut Self {
1335 self.row.set_value_and_mark_modified(row);
1336 self
1337 }
1338
1339 fn set_row_notify(&mut self, row: usize) -> usize {
1340 self.invalidate_layout();
1341 std::mem::replace(&mut self.row, row)
1342 }
1343
1344 /// Returns current row of the widget. Rows are used only by [`crate::grid::Grid`] widget.
1345 #[inline]
1346 pub fn row(&self) -> usize {
1347 *self.row
1348 }
1349
1350 /// Returns the desired size of the widget.
1351 #[inline]
1352 pub fn desired_size(&self) -> Vector2<f32> {
1353 self.desired_size.get()
1354 }
1355
1356 /// Returns current desired local position of the widget.
1357 #[inline]
1358 pub fn desired_local_position(&self) -> Vector2<f32> {
1359 *self.desired_local_position
1360 }
1361
1362 fn set_desired_local_position_notify(&mut self, position: Vector2<f32>) -> Vector2<f32> {
1363 self.invalidate_layout();
1364 self.desired_local_position
1365 .set_value_and_mark_modified(position)
1366 }
1367
1368 /// Returns current screen-space bounds of the widget.
1369 #[inline]
1370 pub fn screen_bounds(&self) -> Rect<f32> {
1371 self.bounding_rect().transform(&self.visual_transform)
1372 }
1373
1374 /// Returns local-space bounding rect of the widget.
1375 #[inline]
1376 pub fn bounding_rect(&self) -> Rect<f32> {
1377 Rect::new(
1378 0.0,
1379 0.0,
1380 self.actual_local_size.get().x,
1381 self.actual_local_size.get().y,
1382 )
1383 }
1384
1385 /// Returns current visual transform of the widget.
1386 #[inline]
1387 pub fn visual_transform(&self) -> &Matrix3<f32> {
1388 &self.visual_transform
1389 }
1390
1391 /// Returns scaling along both axes.
1392 #[inline]
1393 pub fn visual_scaling(&self) -> Vector2<f32> {
1394 self.visual_transform
1395 .transform_vector(&Vector2::new(1.0, 1.0))
1396 }
1397
1398 /// Returns max uniform scaling of both axes.
1399 #[inline]
1400 pub fn visual_max_scaling(&self) -> f32 {
1401 self.visual_scaling().max()
1402 }
1403
1404 /// Sets new render transform.
1405 pub fn set_render_transform(&mut self, transform: Matrix3<f32>) {
1406 self.render_transform = transform;
1407 self.try_send_transform_changed_event();
1408 }
1409
1410 /// Returns current render transform of the widget.
1411 #[inline]
1412 pub fn render_transform(&self) -> &Matrix3<f32> {
1413 &self.render_transform
1414 }
1415
1416 /// Sets new layout transform.
1417 pub fn set_layout_transform(&mut self, transform: Matrix3<f32>) {
1418 self.layout_transform = transform;
1419 self.invalidate_layout();
1420 }
1421
1422 /// Returns current layout transform of the widget.
1423 #[inline]
1424 pub fn layout_transform(&self) -> &Matrix3<f32> {
1425 &self.layout_transform
1426 }
1427
1428 /// Returns `true`, if the widget has a descendant widget with the specified handle, `false` - otherwise.
1429 pub fn has_descendant(&self, node_handle: Handle<UiNode>, ui: &UserInterface) -> bool {
1430 for child_handle in self.children.iter() {
1431 if *child_handle == node_handle {
1432 return true;
1433 }
1434
1435 let result = ui
1436 .nodes
1437 .borrow(*child_handle)
1438 .has_descendant(node_handle, ui);
1439 if result {
1440 return true;
1441 }
1442 }
1443 false
1444 }
1445
1446 /// Searches a node up on tree starting from the given root that matches a criteria defined by the given func.
1447 pub fn find_by_criteria_up<Func: Fn(&UiNode) -> bool>(
1448 &self,
1449 ui: &UserInterface,
1450 func: Func,
1451 ) -> Handle<UiNode> {
1452 let mut parent_handle = self.parent;
1453 while parent_handle.is_some() {
1454 if let Some(parent_node) = ui.nodes.try_borrow(parent_handle) {
1455 if func(parent_node) {
1456 return parent_handle;
1457 }
1458 parent_handle = parent_node.parent;
1459 } else {
1460 break;
1461 }
1462 }
1463 Handle::NONE
1464 }
1465
1466 /// Handles incoming [`WidgetMessage`]s. This method **must** be called in [`crate::control::Control::handle_routed_message`]
1467 /// of any derived widgets!
1468 pub fn handle_routed_message(&mut self, ui: &mut UserInterface, msg: &mut UiMessage) {
1469 if msg.destination() == self.handle() && msg.direction() == MessageDirection::ToWidget {
1470 if let Some(msg) = msg.data::<WidgetMessage>() {
1471 match msg {
1472 &WidgetMessage::Opacity(opacity) => {
1473 self.opacity.set_value_and_mark_modified(opacity);
1474 }
1475 WidgetMessage::Background(background) => {
1476 *self.background = background.clone();
1477 }
1478 WidgetMessage::Foreground(foreground) => {
1479 *self.foreground = foreground.clone();
1480 }
1481 WidgetMessage::Name(name) => self.name = ImmutableString::new(name),
1482 &WidgetMessage::Width(width) => {
1483 if *self.width != width {
1484 self.set_width_notify(width);
1485 }
1486 }
1487 &WidgetMessage::Height(height) => {
1488 if *self.height != height {
1489 self.set_height_notify(height);
1490 }
1491 }
1492 WidgetMessage::VerticalAlignment(vertical_alignment) => {
1493 if *self.vertical_alignment != *vertical_alignment {
1494 self.set_vertical_alignment(*vertical_alignment);
1495 }
1496 }
1497 WidgetMessage::HorizontalAlignment(horizontal_alignment) => {
1498 if *self.horizontal_alignment != *horizontal_alignment {
1499 self.set_horizontal_alignment(*horizontal_alignment);
1500 }
1501 }
1502 WidgetMessage::MaxSize(max_size) => {
1503 if *self.max_size != *max_size {
1504 self.set_max_size_notify(*max_size);
1505 }
1506 }
1507 WidgetMessage::MinSize(min_size) => {
1508 if *self.min_size != *min_size {
1509 self.set_min_size_notify(*min_size);
1510 }
1511 }
1512 &WidgetMessage::Row(row) => {
1513 if *self.row != row {
1514 self.set_row_notify(row);
1515 }
1516 }
1517 &WidgetMessage::Column(column) => {
1518 if *self.column != column {
1519 self.set_column_notify(column);
1520 }
1521 }
1522 &WidgetMessage::Margin(margin) => {
1523 if *self.margin != margin {
1524 self.set_margin_notify(margin);
1525 }
1526 }
1527 WidgetMessage::HitTestVisibility(hit_test_visibility) => {
1528 self.hit_test_visibility
1529 .set_value_and_mark_modified(*hit_test_visibility);
1530 }
1531 &WidgetMessage::Visibility(visibility) => {
1532 self.set_visibility(visibility);
1533 }
1534 &WidgetMessage::DesiredPosition(pos) => {
1535 if *self.desired_local_position != pos {
1536 self.set_desired_local_position_notify(pos);
1537 }
1538 }
1539 &WidgetMessage::Enabled(enabled) => {
1540 self.enabled.set_value_and_mark_modified(enabled);
1541 }
1542 &WidgetMessage::Cursor(icon) => {
1543 self.cursor.set_value_and_mark_modified(icon);
1544 }
1545 WidgetMessage::LayoutTransform(transform) => {
1546 if &self.layout_transform != transform {
1547 self.set_layout_transform(*transform);
1548 }
1549 }
1550 WidgetMessage::RenderTransform(transform) => {
1551 self.set_render_transform(*transform);
1552 }
1553 WidgetMessage::ZIndex(index) => {
1554 if *self.z_index != *index {
1555 self.set_z_index(*index);
1556 self.invalidate_layout();
1557 }
1558 }
1559 WidgetMessage::SortChildren(predicate) => {
1560 self.children
1561 .sort_unstable_by(|a, b| predicate.0(*a, *b, ui));
1562 self.invalidate_layout();
1563 }
1564 WidgetMessage::Style(style) => {
1565 self.background.update(style);
1566 self.foreground.update(style);
1567 self.style = Some(style.clone());
1568 }
1569 _ => (),
1570 }
1571 }
1572 }
1573 }
1574
1575 /// Sets new vertical alignment of the widget.
1576 #[inline]
1577 pub fn set_vertical_alignment(&mut self, vertical_alignment: VerticalAlignment) -> &mut Self {
1578 self.vertical_alignment
1579 .set_value_and_mark_modified(vertical_alignment);
1580 self
1581 }
1582
1583 fn set_vertical_alignment_notify(
1584 &mut self,
1585 vertical_alignment: VerticalAlignment,
1586 ) -> VerticalAlignment {
1587 self.invalidate_layout();
1588 self.vertical_alignment
1589 .set_value_and_mark_modified(vertical_alignment)
1590 }
1591
1592 /// Returns current vertical alignment of the widget.
1593 #[inline]
1594 pub fn vertical_alignment(&self) -> VerticalAlignment {
1595 *self.vertical_alignment
1596 }
1597
1598 /// Sets new horizontal alignment of the widget.
1599 #[inline]
1600 pub fn set_horizontal_alignment(
1601 &mut self,
1602 horizontal_alignment: HorizontalAlignment,
1603 ) -> &mut Self {
1604 self.horizontal_alignment
1605 .set_value_and_mark_modified(horizontal_alignment);
1606 self
1607 }
1608
1609 fn set_horizontal_alignment_notify(
1610 &mut self,
1611 horizontal_alignment: HorizontalAlignment,
1612 ) -> HorizontalAlignment {
1613 self.invalidate_layout();
1614 self.horizontal_alignment
1615 .set_value_and_mark_modified(horizontal_alignment)
1616 }
1617
1618 /// Returns current horizontal alignment of the widget.
1619 #[inline]
1620 pub fn horizontal_alignment(&self) -> HorizontalAlignment {
1621 *self.horizontal_alignment
1622 }
1623
1624 /// Sets new margin of the widget.
1625 #[inline]
1626 pub fn set_margin(&mut self, margin: Thickness) -> &mut Self {
1627 self.margin.set_value_and_mark_modified(margin);
1628 self
1629 }
1630
1631 fn set_margin_notify(&mut self, margin: Thickness) -> Thickness {
1632 self.invalidate_layout();
1633 self.margin.set_value_and_mark_modified(margin)
1634 }
1635
1636 /// Returns current margin of the widget.
1637 #[inline]
1638 pub fn margin(&self) -> Thickness {
1639 *self.margin
1640 }
1641
1642 /// Performs standard measurement of children nodes. It provides available size as a constraint and returns
1643 /// the maximum desired size across all children. As a result, this widget will have this size as its desired
1644 /// size to fit all the children nodes.
1645 #[inline]
1646 pub fn measure_override(
1647 &self,
1648 ui: &UserInterface,
1649 available_size: Vector2<f32>,
1650 ) -> Vector2<f32> {
1651 let mut size: Vector2<f32> = Vector2::default();
1652
1653 for &child in self.children.iter() {
1654 ui.measure_node(child, available_size);
1655 let desired_size = ui.node(child).desired_size();
1656 size.x = size.x.max(desired_size.x);
1657 size.y = size.y.max(desired_size.y);
1658 }
1659
1660 size
1661 }
1662
1663 /// Performs standard arrangement of the children nodes of the widget. It uses input final size to make a final
1664 /// bounding rectangle to arrange children. As a result, all the children nodes will be located at the top-left
1665 /// corner of this widget and stretched to fit its bounds.
1666 #[inline]
1667 pub fn arrange_override(&self, ui: &UserInterface, final_size: Vector2<f32>) -> Vector2<f32> {
1668 let final_rect = Rect::new(0.0, 0.0, final_size.x, final_size.y);
1669
1670 for &child in self.children.iter() {
1671 ui.arrange_node(child, &final_rect);
1672 }
1673
1674 final_size
1675 }
1676
1677 #[inline]
1678 pub(crate) fn commit_arrange(&self, position: Vector2<f32>, size: Vector2<f32>) {
1679 let old_actual_local_size = self.actual_local_size.replace(size);
1680 let old_actual_local_position = self.actual_local_position.replace(position);
1681 self.arrange_valid.set(true);
1682 if old_actual_local_position != position || old_actual_local_size != size {
1683 self.try_send_transform_changed_event();
1684 }
1685 }
1686
1687 fn try_send_transform_changed_event(&self) {
1688 if let Some(sender) = self.layout_events_sender.as_ref() {
1689 let _ = sender.send(LayoutEvent::TransformChanged(self.handle));
1690 }
1691 }
1692
1693 #[inline]
1694 pub(crate) fn set_children(&mut self, children: Vec<Handle<UiNode>>) {
1695 self.invalidate_layout();
1696 self.request_update_visibility();
1697 self.children = children;
1698 }
1699
1700 /// Returns `true` if the widget has a parent object in a resource from which it may restore
1701 /// values of its inheritable properties.
1702 #[inline]
1703 pub fn has_inheritance_parent(&self) -> bool {
1704 self.original_handle_in_resource.is_some() && self.resource.is_some()
1705 }
1706
1707 /// Returns `true` if the current results of arrangement of the widget are valid, `false` - otherwise.
1708 #[inline(always)]
1709 pub fn is_arrange_valid(&self) -> bool {
1710 self.arrange_valid.get()
1711 }
1712
1713 #[inline]
1714 pub(crate) fn commit_measure(&self, desired_size: Vector2<f32>) {
1715 self.desired_size.set(desired_size);
1716 self.measure_valid.set(true);
1717 }
1718
1719 /// Returns `true` if the current results of measurement of the widget are valid, `false` - otherwise.
1720 #[inline(always)]
1721 pub fn is_measure_valid(&self) -> bool {
1722 self.measure_valid.get()
1723 }
1724
1725 /// Returns current actual local position of the widget. It is valid only after layout pass!
1726 #[inline]
1727 pub fn actual_local_position(&self) -> Vector2<f32> {
1728 self.actual_local_position.get()
1729 }
1730
1731 /// Returns center point of the widget. It is valid only after layout pass!
1732 #[inline]
1733 pub fn center(&self) -> Vector2<f32> {
1734 self.actual_local_position() + self.actual_local_size().scale(0.5)
1735 }
1736
1737 #[inline]
1738 pub(crate) fn set_global_visibility(&mut self, value: bool) {
1739 self.prev_global_visibility = self.global_visibility;
1740 self.global_visibility = value;
1741 }
1742
1743 /// Returns `true` of the widget is globally visible, which means that all its parents are visible as well
1744 /// as this widget. It is valid only after the first update of the layout, otherwise if will be always false.
1745 #[inline]
1746 pub fn is_globally_visible(&self) -> bool {
1747 self.global_visibility
1748 }
1749
1750 /// Sets new visibility of the widget.
1751 #[inline]
1752 pub fn set_visibility(&mut self, visibility: bool) -> &mut Self {
1753 if *self.visibility != visibility {
1754 self.set_visibility_notify(visibility);
1755 }
1756 self
1757 }
1758
1759 fn set_visibility_notify(&mut self, visibility: bool) -> bool {
1760 self.invalidate_layout();
1761 self.request_update_visibility();
1762 std::mem::replace(&mut self.visibility, visibility)
1763 }
1764
1765 /// Requests (via event queue, so the request is deferred) the update of the visibility of the widget.
1766 #[inline]
1767 pub fn request_update_visibility(&self) {
1768 if let Some(layout_events_sender) = self.layout_events_sender.as_ref() {
1769 let _ = layout_events_sender.send(LayoutEvent::VisibilityChanged(self.handle));
1770 }
1771 }
1772
1773 /// Returns current visibility of the widget.
1774 #[inline]
1775 pub fn visibility(&self) -> bool {
1776 *self.visibility
1777 }
1778
1779 /// Enables or disables the widget. Disabled widgets does not interact with user and usually greyed out.
1780 #[inline]
1781 pub fn set_enabled(&mut self, enabled: bool) -> &mut Self {
1782 self.enabled.set_value_and_mark_modified(enabled);
1783 self
1784 }
1785
1786 /// Returns `true` if the widget if enabled, `false` - otherwise.
1787 #[inline]
1788 pub fn enabled(&self) -> bool {
1789 *self.enabled
1790 }
1791
1792 /// Sets new cursor of the widget.
1793 #[inline]
1794 pub fn set_cursor(&mut self, cursor: Option<CursorIcon>) {
1795 self.cursor.set_value_and_mark_modified(cursor);
1796 }
1797
1798 /// Returns current cursor of the widget.
1799 #[inline]
1800 pub fn cursor(&self) -> Option<CursorIcon> {
1801 *self.cursor
1802 }
1803
1804 /// Tries to fetch user-defined data of the specified type `T`.
1805 #[inline]
1806 pub fn user_data_cloned<T: Clone + 'static>(&self) -> Option<T> {
1807 self.user_data.as_ref().and_then(|v| {
1808 let guard = v.safe_lock();
1809 guard.downcast_ref::<T>().cloned()
1810 })
1811 }
1812
1813 /// Returns current clipping bounds of the widget. It is valid only after at least one layout pass.
1814 #[inline]
1815 pub fn clip_bounds(&self) -> Rect<f32> {
1816 self.clip_bounds.get()
1817 }
1818
1819 /// Set new opacity of the widget. Opacity should be in `[0.0..1.0]` range.
1820 #[inline]
1821 pub fn set_opacity(&mut self, opacity: Option<f32>) -> &mut Self {
1822 self.opacity.set_value_and_mark_modified(opacity);
1823 self
1824 }
1825
1826 /// Returns current opacity of the widget.
1827 #[inline]
1828 pub fn opacity(&self) -> Option<f32> {
1829 *self.opacity
1830 }
1831
1832 /// Returns current tooltip handle of the widget.
1833 #[inline]
1834 pub fn tooltip(&self) -> Option<RcUiNodeHandle> {
1835 self.tooltip.clone()
1836 }
1837
1838 /// Sets new tooltip handle of the widget (if any).
1839 #[inline]
1840 pub fn set_tooltip(&mut self, tooltip: Option<RcUiNodeHandle>) -> &mut Self {
1841 self.tooltip = tooltip;
1842 self
1843 }
1844
1845 /// Returns maximum available time to show the tooltip after the cursor was moved away from the widget.
1846 #[inline]
1847 pub fn tooltip_time(&self) -> f32 {
1848 self.tooltip_time
1849 }
1850
1851 /// Set the maximum available time to show the tooltip after the cursor was moved away from the widget.
1852 #[inline]
1853 pub fn set_tooltip_time(&mut self, tooltip_time: f32) -> &mut Self {
1854 self.tooltip_time = tooltip_time;
1855 self
1856 }
1857
1858 /// Returns current context menu of the widget.
1859 #[inline]
1860 pub fn context_menu(&self) -> Option<RcUiNodeHandle> {
1861 self.context_menu.clone()
1862 }
1863
1864 /// The context menu receives `PopupMessage`s for being displayed, and so should support those.
1865 #[inline]
1866 pub fn set_context_menu(&mut self, context_menu: Option<RcUiNodeHandle>) -> &mut Self {
1867 self.context_menu = context_menu;
1868 self
1869 }
1870}
1871
1872/// Implements `Deref<Target = Widget> + DerefMut` for your widget. It is used to reduce boilerplate code and
1873/// make it less bug-prone.
1874#[macro_export]
1875macro_rules! define_widget_deref {
1876 ($ty: ty) => {
1877 impl Deref for $ty {
1878 type Target = Widget;
1879
1880 fn deref(&self) -> &Self::Target {
1881 &self.widget
1882 }
1883 }
1884
1885 impl DerefMut for $ty {
1886 fn deref_mut(&mut self) -> &mut Self::Target {
1887 &mut self.widget
1888 }
1889 }
1890 };
1891}
1892
1893/// Widget builder creates [`Widget`] instances.
1894pub struct WidgetBuilder {
1895 /// Name of the widget.
1896 pub name: String,
1897 /// Width of the widget.
1898 pub width: f32,
1899 /// Height of the widget.
1900 pub height: f32,
1901 /// Desired position of the widget.
1902 pub desired_position: Vector2<f32>,
1903 /// Vertical alignment of the widget.
1904 pub vertical_alignment: VerticalAlignment,
1905 /// Horizontal alignment of the widget.
1906 pub horizontal_alignment: HorizontalAlignment,
1907 /// Max size of the widget.
1908 pub max_size: Option<Vector2<f32>>,
1909 /// Min size of the widget.
1910 pub min_size: Option<Vector2<f32>>,
1911 /// Background brush of the widget.
1912 pub background: Option<StyledProperty<Brush>>,
1913 /// Foreground brush of the widget.
1914 pub foreground: Option<StyledProperty<Brush>>,
1915 /// Row index of the widget.
1916 pub row: usize,
1917 /// Column index of the widget.
1918 pub column: usize,
1919 /// Margin of the widget.
1920 pub margin: Thickness,
1921 /// Children handles of the widget.
1922 pub children: Vec<Handle<UiNode>>,
1923 /// Whether the hit test is enabled or not.
1924 pub is_hit_test_visible: bool,
1925 /// Whether the widget is visible or not.
1926 pub visibility: bool,
1927 /// Z index of the widget.
1928 pub z_index: usize,
1929 /// Whether the dragging of the widget is allowed or not.
1930 pub allow_drag: bool,
1931 /// Whether the drop of the widget is allowed or not.
1932 pub allow_drop: bool,
1933 /// User-defined data.
1934 pub user_data: Option<Arc<Mutex<dyn Any + Send>>>,
1935 /// Whether to draw the widget on top of any other or not.
1936 pub draw_on_top: bool,
1937 /// Whether the widget is enabled or not.
1938 pub enabled: bool,
1939 /// Cursor of the widget.
1940 pub cursor: Option<CursorIcon>,
1941 /// Opacity of the widget.
1942 pub opacity: Option<f32>,
1943 /// Tooltip of the widget.
1944 pub tooltip: Option<RcUiNodeHandle>,
1945 /// Visibility interval (in seconds) of the tooltip of the widget.
1946 pub tooltip_time: f32,
1947 /// Context menu of the widget.
1948 pub context_menu: Option<RcUiNodeHandle>,
1949 /// Whether the preview messages is enabled or not.
1950 pub preview_messages: bool,
1951 /// Whether the widget will handle OS events or not.
1952 pub handle_os_events: bool,
1953 /// Whether the widget will be updated or not.
1954 pub need_update: bool,
1955 /// Layout transform of the widget.
1956 pub layout_transform: Matrix3<f32>,
1957 /// Render transform of the widget.
1958 pub render_transform: Matrix3<f32>,
1959 /// Whether the widget bounds should be clipped by its parent or not.
1960 pub clip_to_bounds: bool,
1961 /// Unique id of the widget.
1962 pub id: Uuid,
1963 /// Defines the order in which this widget will get keyboard focus when Tab key is pressed.
1964 /// If set to [`None`], Tab key won't do anything on such widget. Default is [`None`].
1965 pub tab_index: Option<usize>,
1966 /// A flag, that defines whether the Tab key navigation is enabled or disabled for this widget.
1967 pub tab_stop: bool,
1968 /// A flag, that indicates that the widget accepts user input.
1969 pub accepts_input: bool,
1970 /// A material that will be used for rendering.
1971 pub material: WidgetMaterial,
1972 /// Style of the widget.
1973 pub style: StyleResource,
1974}
1975
1976impl Default for WidgetBuilder {
1977 fn default() -> Self {
1978 Self::new()
1979 }
1980}
1981
1982impl WidgetBuilder {
1983 /// Creates new widget builder with the default values.
1984 pub fn new() -> Self {
1985 Self {
1986 name: Default::default(),
1987 width: f32::NAN,
1988 height: f32::NAN,
1989 vertical_alignment: VerticalAlignment::default(),
1990 horizontal_alignment: HorizontalAlignment::default(),
1991 max_size: None,
1992 min_size: None,
1993 background: None,
1994 foreground: None,
1995 row: 0,
1996 column: 0,
1997 margin: Thickness::zero(),
1998 desired_position: Vector2::default(),
1999 children: Vec::new(),
2000 is_hit_test_visible: true,
2001 visibility: true,
2002 z_index: 0,
2003 allow_drag: false,
2004 allow_drop: false,
2005 user_data: None,
2006 draw_on_top: false,
2007 enabled: true,
2008 cursor: None,
2009 opacity: None,
2010 tooltip: Default::default(),
2011 tooltip_time: 0.1,
2012 context_menu: Default::default(),
2013 preview_messages: false,
2014 handle_os_events: false,
2015 need_update: false,
2016 layout_transform: Matrix3::identity(),
2017 render_transform: Matrix3::identity(),
2018 clip_to_bounds: true,
2019 id: Uuid::new_v4(),
2020 tab_index: None,
2021 tab_stop: false,
2022 accepts_input: false,
2023 material: Default::default(),
2024 style: DEFAULT_STYLE.resource.clone(),
2025 }
2026 }
2027
2028 /// Enables or disables message previewing of the widget. It basically defines whether the [`crate::Control::preview_message`] will
2029 /// be called or not.
2030 pub fn with_preview_messages(mut self, state: bool) -> Self {
2031 self.preview_messages = state;
2032 self
2033 }
2034
2035 /// Enables or disables OS event handling of the widget. It basically defines whether the [`crate::Control::handle_os_event`] will
2036 /// be called or not.
2037 pub fn with_handle_os_events(mut self, state: bool) -> Self {
2038 self.handle_os_events = state;
2039 self
2040 }
2041
2042 /// Enables or disables updating of the widget. It basically defines whether the [`crate::Control::update`] will
2043 /// be called or not.
2044 pub fn with_need_update(mut self, state: bool) -> Self {
2045 self.need_update = state;
2046 self
2047 }
2048
2049 /// Sets the desired width of the widget.
2050 pub fn with_width(mut self, width: f32) -> Self {
2051 self.width = width;
2052 self
2053 }
2054
2055 /// Sets the desired height of the widget.
2056 pub fn with_height(mut self, height: f32) -> Self {
2057 self.height = height;
2058 self
2059 }
2060
2061 /// Enables or disables clipping of widget's bound to its parent's bounds.
2062 pub fn with_clip_to_bounds(mut self, clip_to_bounds: bool) -> Self {
2063 self.clip_to_bounds = clip_to_bounds;
2064 self
2065 }
2066
2067 /// Enables or disables the widget.
2068 pub fn with_enabled(mut self, enabled: bool) -> Self {
2069 self.enabled = enabled;
2070 self
2071 }
2072
2073 /// Sets the desired vertical alignment of the widget.
2074 pub fn with_vertical_alignment(mut self, valign: VerticalAlignment) -> Self {
2075 self.vertical_alignment = valign;
2076 self
2077 }
2078
2079 /// Sets the desired horizontal alignment of the widget.
2080 pub fn with_horizontal_alignment(mut self, halign: HorizontalAlignment) -> Self {
2081 self.horizontal_alignment = halign;
2082 self
2083 }
2084
2085 /// Sets the max size of the widget.
2086 pub fn with_max_size(mut self, max_size: Vector2<f32>) -> Self {
2087 self.max_size = Some(max_size);
2088 self
2089 }
2090
2091 /// Sets the min size of the widget.
2092 pub fn with_min_size(mut self, min_size: Vector2<f32>) -> Self {
2093 self.min_size = Some(min_size);
2094 self
2095 }
2096
2097 /// Sets the desired background brush of the widget.
2098 pub fn with_background(mut self, brush: StyledProperty<Brush>) -> Self {
2099 self.background = Some(brush);
2100 self
2101 }
2102
2103 /// Sets the desired foreground brush of the widget.
2104 pub fn with_foreground(mut self, brush: StyledProperty<Brush>) -> Self {
2105 self.foreground = Some(brush);
2106 self
2107 }
2108
2109 /// Sets the desired row index of the widget.
2110 pub fn on_row(mut self, row: usize) -> Self {
2111 self.row = row;
2112 self
2113 }
2114
2115 /// Sets the desired column index of the widget.
2116 pub fn on_column(mut self, column: usize) -> Self {
2117 self.column = column;
2118 self
2119 }
2120
2121 /// Sets the desired margin of the widget.
2122 pub fn with_margin(mut self, margin: Thickness) -> Self {
2123 self.margin = margin;
2124 self
2125 }
2126
2127 /// Sets the desired, uniform margin of the widget.
2128 pub fn with_uniform_margin(mut self, margin: f32) -> Self {
2129 self.margin = Thickness::uniform(margin);
2130 self
2131 }
2132
2133 /// Sets the desired position of the widget.
2134 pub fn with_desired_position(mut self, desired_position: Vector2<f32>) -> Self {
2135 self.desired_position = desired_position;
2136 self
2137 }
2138
2139 /// Sets the desired layout transform of the widget.
2140 pub fn with_layout_transform(mut self, layout_transform: Matrix3<f32>) -> Self {
2141 self.layout_transform = layout_transform;
2142 self
2143 }
2144
2145 /// Sets the desired render transform of the widget.
2146 pub fn with_render_transform(mut self, render_transform: Matrix3<f32>) -> Self {
2147 self.render_transform = render_transform;
2148 self
2149 }
2150
2151 /// Sets the desired Z index of the widget.
2152 pub fn with_z_index(mut self, z_index: usize) -> Self {
2153 self.z_index = z_index;
2154 self
2155 }
2156
2157 /// Adds a child handle to the widget. [`Handle::NONE`] values are ignored.
2158 pub fn with_child(mut self, handle: Handle<UiNode>) -> Self {
2159 if handle.is_some() {
2160 self.children.push(handle);
2161 }
2162 self
2163 }
2164
2165 /// Enables or disables top-most widget drawing.
2166 pub fn with_draw_on_top(mut self, draw_on_top: bool) -> Self {
2167 self.draw_on_top = draw_on_top;
2168 self
2169 }
2170
2171 /// Sets the desired set of children nodes.
2172 pub fn with_children<I: IntoIterator<Item = Handle<UiNode>>>(mut self, children: I) -> Self {
2173 for child in children.into_iter() {
2174 if child.is_some() {
2175 self.children.push(child)
2176 }
2177 }
2178 self
2179 }
2180
2181 /// Sets the desired widget name.
2182 pub fn with_name(mut self, name: &str) -> Self {
2183 self.name = String::from(name);
2184 self
2185 }
2186
2187 /// Enables or disables hit test of the widget.
2188 pub fn with_hit_test_visibility(mut self, state: bool) -> Self {
2189 self.is_hit_test_visible = state;
2190 self
2191 }
2192
2193 /// Sets the desired widget visibility.
2194 pub fn with_visibility(mut self, visibility: bool) -> Self {
2195 self.visibility = visibility;
2196 self
2197 }
2198
2199 /// Enables or disables an ability to drop other widgets on this widget.
2200 pub fn with_allow_drop(mut self, allow_drop: bool) -> Self {
2201 self.allow_drop = allow_drop;
2202 self
2203 }
2204
2205 /// Enables or disables dragging of the widget.
2206 pub fn with_allow_drag(mut self, allow_drag: bool) -> Self {
2207 self.allow_drag = allow_drag;
2208 self
2209 }
2210
2211 /// Sets the desired widget user data.
2212 pub fn with_user_data(mut self, user_data: Arc<Mutex<dyn Any + Send>>) -> Self {
2213 self.user_data = Some(user_data);
2214 self
2215 }
2216
2217 /// Sets the desired widget cursor.
2218 pub fn with_cursor(mut self, cursor: Option<CursorIcon>) -> Self {
2219 self.cursor = cursor;
2220 self
2221 }
2222
2223 /// Sets the desired widget opacity.
2224 pub fn with_opacity(mut self, opacity: Option<f32>) -> Self {
2225 self.opacity = opacity;
2226 self
2227 }
2228
2229 /// Sets the desired widget id.
2230 pub fn with_id(mut self, id: Uuid) -> Self {
2231 self.id = id;
2232 self
2233 }
2234
2235 /// Sets the desired tooltip for the node.
2236 ///
2237 /// ## Important
2238 ///
2239 /// The widget will share the tooltip, which means that when widget will be deleted, the
2240 /// tooltip will be deleted only if there's no one use the tooltip anymore.
2241 pub fn with_tooltip(mut self, tooltip: RcUiNodeHandle) -> Self {
2242 self.tooltip = Some(tooltip);
2243 self
2244 }
2245
2246 /// Sets the desired tooltip for the node.
2247 ///
2248 /// ## Important
2249 ///
2250 /// The widget will share the tooltip, which means that when widget will be deleted, the
2251 /// tooltip will be deleted only if there's no one use the tooltip anymore.
2252 pub fn with_opt_tooltip(mut self, tooltip: Option<RcUiNodeHandle>) -> Self {
2253 self.tooltip = tooltip;
2254 self
2255 }
2256
2257 /// Sets the desired tooltip time.
2258 pub fn with_tooltip_time(mut self, tooltip_time: f32) -> Self {
2259 self.tooltip_time = tooltip_time;
2260 self
2261 }
2262
2263 /// The context menu receives `PopupMessage`s for being displayed, and so should support those.
2264 pub fn with_context_menu(mut self, context_menu: RcUiNodeHandle) -> Self {
2265 self.context_menu = Some(context_menu);
2266 self
2267 }
2268
2269 /// Sets the desired tab index.
2270 pub fn with_tab_index(mut self, tab_index: Option<usize>) -> Self {
2271 self.tab_index = tab_index;
2272 self
2273 }
2274
2275 /// Sets a flag, that defines whether the Tab key navigation is enabled or disabled for this widget.
2276 pub fn with_tab_stop(mut self, tab_stop: bool) -> Self {
2277 self.tab_stop = tab_stop;
2278 self
2279 }
2280
2281 /// Sets a flag, that indicates that the widget accepts user input.
2282 pub fn with_accepts_input(mut self, accepts_input: bool) -> Self {
2283 self.accepts_input = accepts_input;
2284 self
2285 }
2286
2287 /// Sets a material which will be used for rendering of this widget.
2288 pub fn with_material(mut self, material: WidgetMaterial) -> Self {
2289 self.material = material;
2290 self
2291 }
2292
2293 /// Finishes building of the base widget.
2294 pub fn build(self, ctx: &BuildContext) -> Widget {
2295 Widget {
2296 handle: Default::default(),
2297 name: self.name.into(),
2298 desired_local_position: self.desired_position.into(),
2299 width: self.width.into(),
2300 height: self.height.into(),
2301 desired_size: Cell::new(Vector2::default()),
2302 actual_local_position: Cell::new(Vector2::default()),
2303 actual_local_size: Cell::new(Vector2::default()),
2304 min_size: self.min_size.unwrap_or_default().into(),
2305 max_size: self
2306 .max_size
2307 .unwrap_or_else(|| Vector2::new(f32::INFINITY, f32::INFINITY))
2308 .into(),
2309 background: self
2310 .background
2311 .unwrap_or_else(|| ctx.style.property(Style::BRUSH_PRIMARY))
2312 .into(),
2313 foreground: self
2314 .foreground
2315 .unwrap_or_else(|| ctx.style.property(Style::BRUSH_FOREGROUND))
2316 .into(),
2317 row: self.row.into(),
2318 column: self.column.into(),
2319 vertical_alignment: self.vertical_alignment.into(),
2320 horizontal_alignment: self.horizontal_alignment.into(),
2321 margin: self.margin.into(),
2322 visibility: self.visibility.into(),
2323 global_visibility: true,
2324 prev_global_visibility: false,
2325 children: self.children,
2326 parent: Handle::NONE,
2327 command_indices: Default::default(),
2328 is_mouse_directly_over: false,
2329 measure_valid: Cell::new(false),
2330 arrange_valid: Cell::new(false),
2331 hit_test_visibility: self.is_hit_test_visible.into(),
2332 prev_measure: Default::default(),
2333 prev_arrange: Default::default(),
2334 z_index: self.z_index.into(),
2335 allow_drag: self.allow_drag.into(),
2336 allow_drop: self.allow_drop.into(),
2337 user_data: self.user_data.clone(),
2338 draw_on_top: self.draw_on_top.into(),
2339 enabled: self.enabled.into(),
2340 cursor: self.cursor.into(),
2341 clip_bounds: Cell::new(Default::default()),
2342 opacity: self.opacity.into(),
2343 tooltip: self.tooltip,
2344 tooltip_time: self.tooltip_time,
2345 context_menu: self.context_menu,
2346 preview_messages: self.preview_messages,
2347 handle_os_events: self.handle_os_events,
2348 tab_index: self.tab_index.into(),
2349 tab_stop: self.tab_stop.into(),
2350 need_update: self.need_update,
2351 ignore_layout_rounding: false,
2352 accepts_input: self.accepts_input,
2353 layout_events_sender: None,
2354 layout_transform: self.layout_transform,
2355 render_transform: self.render_transform,
2356 visual_transform: Matrix3::identity(),
2357 clip_to_bounds: self.clip_to_bounds.into(),
2358 id: self.id,
2359 is_resource_instance_root: false,
2360 resource: None,
2361 material: self.material.into(),
2362 original_handle_in_resource: Default::default(),
2363 style: Some(ctx.style.clone()),
2364 }
2365 }
2366}