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