rg3d_ui/
widget.rs

1use crate::{
2    brush::Brush,
3    core::{algebra::Vector2, math::Rect, pool::Handle},
4    define_constructor,
5    message::{CursorIcon, KeyCode, MessageDirection, UiMessage},
6    HorizontalAlignment, LayoutEvent, MouseButton, MouseState, Thickness, UiNode, UserInterface,
7    VerticalAlignment, BRUSH_FOREGROUND, BRUSH_PRIMARY,
8};
9use std::{
10    any::Any,
11    cell::{Cell, RefCell},
12    rc::Rc,
13    sync::mpsc::Sender,
14};
15
16/// A set of messages for any kind of widgets (including user controls). These messages provides basic
17/// communication elements of the UI library.
18#[derive(Debug, Clone, PartialEq)]
19pub enum WidgetMessage {
20    /// Initiated when user clicks on a widget's geometry.
21    ///
22    /// Direction: **From UI**.
23    MouseDown {
24        /// Position of cursor.
25        pos: Vector2<f32>,
26        /// A button that was pressed.
27        button: MouseButton,
28    },
29
30    /// Initiated when user releases mouse button while cursor is over widget's geometry.
31    ///
32    /// Direction: **From UI**.
33    MouseUp {
34        /// Position of cursor.
35        pos: Vector2<f32>,
36        /// A button that was released.
37        button: MouseButton,
38    },
39
40    /// Initiated when user moves cursor over widget's geometry.
41    ///
42    /// Direction: **From/To UI**.
43    MouseMove {
44        /// New position of cursor in screen coordinates.
45        pos: Vector2<f32>,
46        /// State of mouse buttons.
47        state: MouseState,
48    },
49
50    /// Initiated when user scrolls mouse wheel while cursor is over widget's geometry.
51    ///
52    /// Direction: **From/To UI**.
53    MouseWheel {
54        /// Position of cursor.
55        pos: Vector2<f32>,
56        /// Amount of lines per mouse wheel turn.
57        amount: f32,
58    },
59
60    /// Initiated when cursor leaves geometry of a widget.
61    ///
62    /// Direction: **From UI**.
63    MouseLeave,
64
65    /// Initiated when cursor enters geometry of a widget.
66    ///
67    /// Direction: **From UI**.
68    MouseEnter,
69
70    /// Initiated when widget is in focus and user types something on a keyboard.
71    ///
72    /// Direction: **From/To UI**.
73    Text(char),
74
75    /// Initiated when widget is in focus and user presses a button on a keyboard.
76    ///
77    /// Direction: **From UI**.
78    KeyDown(KeyCode),
79
80    /// Initiated when widget is in focus and user releases a button on a keyboard.
81    ///
82    /// Direction: **From UI**.
83    KeyUp(KeyCode),
84
85    /// Initiated when widget received focus. In most cases focus is received by clicking on
86    /// widget.
87    ///
88    /// Direction: **From UI**.
89    GotFocus,
90
91    /// Initiated when dragging of a widget has started.
92    ///
93    /// Direction: **From UI**.
94    DragStarted(Handle<UiNode>),
95
96    /// Initiated when user drags a widget over some other widget.
97    ///
98    /// Direction: **From UI**.
99    DragOver(Handle<UiNode>),
100
101    /// Initiated when user drops a widget onto some other widget.
102    ///
103    /// Direction: **From UI**.
104    Drop(Handle<UiNode>),
105
106    /// Initiated when widget has lost its focus.
107    ///
108    /// Direction: **From UI**.
109    LostFocus,
110
111    /// A request to make widget topmost. Widget can be made topmost only in the same hierarchy
112    /// level only!
113    ///
114    /// Direction: **From/To UI**.
115    TopMost,
116
117    /// A request to detach widget from its current parent and attach to root canvas.
118    ///
119    /// Direction: **From/To UI**.
120    Unlink,
121
122    /// A request to delete widget with all its children widgets. All handles to a node and its
123    /// children will be invalid after processing such message!
124    ///
125    /// Direction: **From/To UI**.
126    Remove,
127
128    /// A request to link initiator with specified widget.
129    ///
130    /// Direction: **From/To UI**.
131    LinkWith(Handle<UiNode>),
132
133    /// A request to link initiator with specified widget and put it in front of children list.
134    ///
135    /// Direction: **From/To UI**.
136    LinkWithReverse(Handle<UiNode>),
137
138    /// A request to change background brush of a widget. Background brushes are used to fill volume of widgets.
139    ///
140    /// Direction: **From/To UI**
141    Background(Brush),
142
143    /// A request to change foreground brush of a widget. Foreground brushes are used for text, borders and so on.
144    ///
145    /// Direction: **From/To UI**
146    Foreground(Brush),
147
148    /// A request to change name of a widget. Name is given to widget mostly for debugging purposes.
149    ///
150    /// Direction: **From/To UI**
151    Name(String),
152
153    /// A request to set width of a widget. In most cases there is no need to explicitly set width of a widget,
154    /// because rg3d-ui uses automatic layout engine which will correctly calculate desired width of a widget.
155    ///
156    /// Direction: **From/To UI**
157    Width(f32),
158
159    /// A request to set height of a widget. In most cases there is no need to explicitly set height of a widget,
160    /// because rg3d-ui uses automatic layout engine which will correctly calculate desired height of a widget.
161    ///
162    /// Direction: **From/To UI**
163    Height(f32),
164
165    /// A request to set vertical alignment of a widget. Vertical alignment tells where to put widget in the parent
166    /// widget's bounds in vertical direction.
167    ///
168    /// Direction: **From/To UI**
169    VerticalAlignment(VerticalAlignment),
170
171    /// A request to set horizontal alignment of a widget. Horizontal alignment tells where to put widget in the parent
172    /// widget's bounds in horizontal direction.
173    ///
174    /// Direction: **From/To UI**
175    HorizontalAlignment(HorizontalAlignment),
176
177    /// A request to set maximum size of widget. Maximum size restricts size of a widget during layout pass. For example
178    /// you can set maximum size to a button which was placed into a grid's cell, if maximum size wouldn't be set, button
179    /// would be stretched to fill entire cell.
180    ///
181    /// Direction: **From/To UI**
182    MaxSize(Vector2<f32>),
183
184    /// A request to set minimum size of widget. Minimum size restricts size of a widget during layout pass. For example
185    /// you can set minimum size to a button which was placed into a grid's cell, if minimum size wouldn't be set, button
186    /// would be compressed to fill entire cell.
187    ///
188    /// Direction: **From/To UI**
189    MinSize(Vector2<f32>),
190
191    /// A request to set row number of a grid to which widget should belong to.
192    ///
193    /// Direction: **From/To UI**
194    ///
195    /// # Notes
196    ///
197    /// This is bad API and it should be changed in future. Grid should have explicit list of pairs (row, child) instead
198    /// of this indirect attachment.
199    Row(usize),
200
201    /// A request to set column number of a grid to which widget should belong to.
202    ///
203    /// Direction: **From/To UI**
204    ///
205    /// # Notes
206    ///
207    /// This is bad API and it should be changed in future. Grid should have explicit list of pairs (column, child) instead
208    /// of this indirect attachment.
209    Column(usize),
210
211    /// A request to set new margin of widget. Margin could be used to add some free space around widget to make UI look less
212    /// dense.
213    ///
214    /// Direction: **From/To UI**
215    Margin(Thickness),
216
217    /// A request to set new state hit test visibility. If set to false, widget will become "non-clickable". It is useful for
218    /// decorations which should be transparent for mouse events.
219    ///
220    /// Direction: **From/To UI**
221    HitTestVisibility(bool),
222
223    /// A request to set new visibility of a widget. Widget can be either visible or not. Invisible widgets does not take space
224    /// in layout pass and collapsed to a point.
225    ///
226    /// Direction: **From/To UI**
227    Visibility(bool),
228
229    /// 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
230    /// only in same hierarchy level, which means that it is impossible to set z index to 9999 (or similar huge value) to force
231    /// widget to be drawn on top of everything.
232    ///
233    /// Direction: **From/To UI**
234    ZIndex(usize),
235
236    /// A request to set new desired position of a widget. It is called "desired" because layout system may ignore it and set
237    /// some other position. Desired position works with a combination of a layout panel that supports direct coordinated
238    /// (Canvas for example).
239    ///
240    /// Direction: **From/To UI**
241    DesiredPosition(Vector2<f32>),
242
243    /// A request to enable or disable widget. Disabled widget won't receive mouse events and may look differently (it is defined
244    /// by internal styling).
245    ///
246    /// Direction: **From/To UI**
247    Enabled(bool),
248
249    /// A request to set desired position at center in local coordinates.
250    ///
251    /// Direction: **From/To UI**
252    Center,
253
254    /// A request to set new cursor icon for widget.
255    ///
256    /// Direction: **From/To UI**
257    Cursor(Option<CursorIcon>),
258
259    /// A request to set new opacity for widget.
260    ///
261    /// Direction: **From/To UI**
262    Opacity(Option<f32>),
263}
264
265impl WidgetMessage {
266    define_constructor!(WidgetMessage:Remove => fn remove(), layout: false);
267    define_constructor!(WidgetMessage:Unlink => fn unlink(), layout: false);
268    define_constructor!(WidgetMessage:LinkWith => fn link(Handle<UiNode>), layout: false);
269    define_constructor!(WidgetMessage:LinkWithReverse => fn link_reverse(Handle<UiNode>), layout: false);
270    define_constructor!(WidgetMessage:Background => fn background(Brush), layout: false);
271    define_constructor!(WidgetMessage:Foreground => fn foreground(Brush), layout: false);
272    define_constructor!(WidgetMessage:Visibility => fn visibility(bool), layout: false);
273    define_constructor!(WidgetMessage:Width => fn width(f32), layout: false);
274    define_constructor!(WidgetMessage:Height => fn height(f32), layout: false);
275    define_constructor!(WidgetMessage:DesiredPosition => fn desired_position(Vector2<f32>), layout: false);
276    define_constructor!(WidgetMessage:Center => fn center(), layout: true);
277    define_constructor!(WidgetMessage:TopMost => fn topmost(), layout: false);
278    define_constructor!(WidgetMessage:Enabled => fn enabled(bool), layout: false);
279    define_constructor!(WidgetMessage:Name => fn name(String), layout: false);
280    define_constructor!(WidgetMessage:Row => fn row(usize), layout: false);
281    define_constructor!(WidgetMessage:Column => fn column(usize), layout: false);
282    define_constructor!(WidgetMessage:Cursor => fn cursor(Option<CursorIcon>), layout: false);
283    define_constructor!(WidgetMessage:ZIndex => fn z_index(usize), layout: false);
284    define_constructor!(WidgetMessage:HitTestVisibility => fn hit_test_visibility(bool), layout: false);
285    define_constructor!(WidgetMessage:Margin => fn margin(Thickness), layout: false);
286    define_constructor!(WidgetMessage:MinSize => fn min_size(Vector2<f32>), layout: false);
287    define_constructor!(WidgetMessage:MaxSize => fn max_size(Vector2<f32>), layout: false);
288    define_constructor!(WidgetMessage:HorizontalAlignment => fn horizontal_alignment(HorizontalAlignment), layout: false);
289    define_constructor!(WidgetMessage:VerticalAlignment => fn vertical_alignment(VerticalAlignment), layout: false);
290    define_constructor!(WidgetMessage:Opacity => fn opacity(Option<f32>), layout: false);
291
292    // Internal messages. Do not use.
293    define_constructor!(WidgetMessage:GotFocus => fn got_focus(), layout: false);
294    define_constructor!(WidgetMessage:LostFocus => fn lost_focus(), layout: false);
295    define_constructor!(WidgetMessage:MouseDown => fn mouse_down(pos: Vector2<f32>, button: MouseButton), layout: false);
296    define_constructor!(WidgetMessage:MouseUp => fn mouse_up(pos: Vector2<f32>, button: MouseButton), layout: false);
297    define_constructor!(WidgetMessage:MouseMove => fn mouse_move(pos: Vector2<f32>, state: MouseState), layout: false);
298    define_constructor!(WidgetMessage:MouseWheel => fn mouse_wheel(pos: Vector2<f32>, amount: f32), layout: false);
299    define_constructor!(WidgetMessage:MouseLeave => fn mouse_leave(), layout: false);
300    define_constructor!(WidgetMessage:MouseEnter => fn mouse_enter(), layout: false);
301    define_constructor!(WidgetMessage:Text => fn text(char), layout: false);
302    define_constructor!(WidgetMessage:KeyDown => fn key_down(KeyCode), layout: false);
303    define_constructor!(WidgetMessage:KeyUp => fn key_up(KeyCode), layout: false);
304    define_constructor!(WidgetMessage:DragStarted => fn drag_started(Handle<UiNode>), layout: false);
305    define_constructor!(WidgetMessage:DragOver => fn drag_over(Handle<UiNode>), layout: false);
306    define_constructor!(WidgetMessage:Drop => fn drop(Handle<UiNode>), layout: false);
307}
308
309#[derive(Debug, Clone)]
310pub struct Widget {
311    pub(in crate) handle: Handle<UiNode>,
312    name: String,
313    /// Desired position relative to parent node
314    desired_local_position: Vector2<f32>,
315    /// Explicit width for node or automatic if NaN (means value is undefined). Default is NaN
316    width: f32,
317    /// Explicit height for node or automatic if NaN (means value is undefined). Default is NaN
318    height: f32,
319    /// Screen position of the node
320    pub(in crate) screen_position: Vector2<f32>,
321    /// Minimum width and height
322    min_size: Vector2<f32>,
323    /// Maximum width and height
324    max_size: Vector2<f32>,
325    background: Brush,
326    foreground: Brush,
327    /// Index of row to which this node belongs
328    row: usize,
329    /// Index of column to which this node belongs
330    column: usize,
331    /// Vertical alignment
332    vertical_alignment: VerticalAlignment,
333    /// Horizontal alignment
334    horizontal_alignment: HorizontalAlignment,
335    /// Margin (four sides)
336    margin: Thickness,
337    /// Current visibility state
338    visibility: bool,
339    global_visibility: bool,
340    children: Vec<Handle<UiNode>>,
341    parent: Handle<UiNode>,
342    /// Indices of commands in command buffer emitted by the node.
343    pub(in crate) command_indices: RefCell<Vec<usize>>,
344    pub(in crate) is_mouse_directly_over: bool,
345    hit_test_visibility: bool,
346    z_index: usize,
347    allow_drag: bool,
348    allow_drop: bool,
349    pub user_data: Option<Rc<dyn Any>>,
350    draw_on_top: bool,
351    enabled: bool,
352    cursor: Option<CursorIcon>,
353    opacity: Option<f32>,
354    tooltip: Handle<UiNode>,
355    tooltip_time: f32,
356    context_menu: Handle<UiNode>,
357    pub(in crate) preview_messages: bool,
358    pub(in crate) handle_os_events: bool,
359    pub(in crate) layout_events_sender: Option<Sender<LayoutEvent>>,
360
361    /// Layout. Interior mutability is a must here because layout performed in
362    /// a series of recursive calls.
363    pub(in crate) measure_valid: Cell<bool>,
364    pub(in crate) arrange_valid: Cell<bool>,
365    pub(in crate) prev_measure: Cell<Vector2<f32>>,
366    pub(in crate) prev_arrange: Cell<Rect<f32>>,
367    /// Desired size of the node after Measure pass.
368    pub(in crate) desired_size: Cell<Vector2<f32>>,
369    /// Actual node local position after Arrange pass.
370    pub(in crate) actual_local_position: Cell<Vector2<f32>>,
371    /// Actual size of the node after Arrange pass.
372    pub(in crate) actual_size: Cell<Vector2<f32>>,
373    pub(in crate) prev_global_visibility: bool,
374    pub(in crate) clip_bounds: Cell<Rect<f32>>,
375}
376
377impl Widget {
378    #[inline]
379    pub fn handle(&self) -> Handle<UiNode> {
380        self.handle
381    }
382
383    #[inline]
384    pub fn name(&self) -> &str {
385        self.name.as_str()
386    }
387
388    #[inline]
389    pub fn set_name<P: AsRef<str>>(&mut self, name: P) -> &mut Self {
390        self.name = name.as_ref().to_owned();
391        self
392    }
393
394    #[inline]
395    pub fn actual_size(&self) -> Vector2<f32> {
396        self.actual_size.get()
397    }
398
399    #[inline]
400    pub fn set_min_size(&mut self, value: Vector2<f32>) -> &mut Self {
401        self.min_size = value;
402        self
403    }
404
405    #[inline]
406    pub fn set_min_width(&mut self, value: f32) -> &mut Self {
407        self.min_size.x = value;
408        self
409    }
410
411    #[inline]
412    pub fn set_min_height(&mut self, value: f32) -> &mut Self {
413        self.min_size.y = value;
414        self
415    }
416
417    #[inline]
418    pub fn min_size(&self) -> Vector2<f32> {
419        self.min_size
420    }
421
422    #[inline]
423    pub fn min_width(&self) -> f32 {
424        self.min_size.x
425    }
426
427    #[inline]
428    pub fn min_height(&self) -> f32 {
429        self.min_size.y
430    }
431
432    #[inline]
433    pub fn is_drag_allowed(&self) -> bool {
434        self.allow_drag
435    }
436
437    #[inline]
438    pub fn is_drop_allowed(&self) -> bool {
439        self.allow_drop
440    }
441
442    #[inline]
443    pub fn invalidate_layout(&self) {
444        self.invalidate_measure();
445        self.invalidate_arrange();
446    }
447
448    #[inline]
449    pub fn invalidate_measure(&self) {
450        self.measure_valid.set(false);
451
452        if let Some(layout_events_sender) = self.layout_events_sender.as_ref() {
453            let _ = layout_events_sender.send(LayoutEvent::MeasurementInvalidated(self.handle));
454        }
455    }
456
457    #[inline]
458    pub fn invalidate_arrange(&self) {
459        self.arrange_valid.set(false);
460
461        if let Some(layout_events_sender) = self.layout_events_sender.as_ref() {
462            let _ = layout_events_sender.send(LayoutEvent::ArrangementInvalidated(self.handle));
463        }
464    }
465
466    #[inline]
467    pub fn is_hit_test_visible(&self) -> bool {
468        self.hit_test_visibility
469    }
470
471    #[inline]
472    pub fn set_max_size(&mut self, value: Vector2<f32>) -> &mut Self {
473        self.max_size = value;
474        self
475    }
476
477    #[inline]
478    pub fn max_size(&self) -> Vector2<f32> {
479        self.max_size
480    }
481
482    #[inline]
483    pub fn max_width(&self) -> f32 {
484        self.max_size.x
485    }
486
487    #[inline]
488    pub fn max_height(&self) -> f32 {
489        self.max_size.y
490    }
491
492    #[inline]
493    pub fn set_z_index(&mut self, z_index: usize) -> &mut Self {
494        self.z_index = z_index;
495        self
496    }
497
498    #[inline]
499    pub fn z_index(&self) -> usize {
500        self.z_index
501    }
502
503    #[inline]
504    pub fn set_background(&mut self, brush: Brush) -> &mut Self {
505        self.background = brush;
506        self
507    }
508
509    #[inline]
510    pub fn background(&self) -> Brush {
511        self.background.clone()
512    }
513
514    #[inline]
515    pub fn set_foreground(&mut self, brush: Brush) -> &mut Self {
516        self.foreground = brush;
517        self
518    }
519
520    #[inline]
521    pub fn foreground(&self) -> Brush {
522        self.foreground.clone()
523    }
524
525    #[inline]
526    pub fn set_width(&mut self, width: f32) -> &mut Self {
527        self.width = width.max(self.min_size.x).min(self.max_size.x);
528        self
529    }
530
531    #[inline]
532    pub fn width(&self) -> f32 {
533        self.width
534    }
535
536    pub fn is_draw_on_top(&self) -> bool {
537        self.draw_on_top
538    }
539
540    #[inline]
541    pub fn set_height(&mut self, height: f32) -> &mut Self {
542        self.height = height.max(self.min_size.y).min(self.max_size.y);
543        self
544    }
545
546    #[inline]
547    pub fn height(&self) -> f32 {
548        self.height
549    }
550
551    #[inline]
552    pub fn set_desired_local_position(&mut self, pos: Vector2<f32>) -> &mut Self {
553        self.desired_local_position = pos;
554        self
555    }
556
557    #[inline]
558    pub fn screen_position(&self) -> Vector2<f32> {
559        self.screen_position
560    }
561
562    #[inline]
563    pub(in crate) fn add_child(&mut self, child: Handle<UiNode>, in_front: bool) {
564        self.invalidate_layout();
565        if in_front && !self.children.is_empty() {
566            self.children.insert(0, child)
567        } else {
568            self.children.push(child)
569        }
570    }
571
572    #[inline(always)]
573    pub fn children(&self) -> &[Handle<UiNode>] {
574        &self.children
575    }
576
577    #[inline]
578    pub(in crate) fn clear_children(&mut self) {
579        self.invalidate_layout();
580        self.children.clear();
581    }
582
583    #[inline]
584    pub(in crate) fn remove_child(&mut self, child: Handle<UiNode>) {
585        if let Some(i) = self.children.iter().position(|h| *h == child) {
586            self.children.remove(i);
587            self.invalidate_layout();
588        }
589    }
590
591    #[inline]
592    pub fn parent(&self) -> Handle<UiNode> {
593        self.parent
594    }
595
596    #[inline]
597    pub fn set_parent(&mut self, parent: Handle<UiNode>) {
598        self.parent = parent;
599    }
600
601    #[inline]
602    pub fn column(&self) -> usize {
603        self.column
604    }
605
606    #[inline]
607    pub fn set_row(&mut self, row: usize) -> &mut Self {
608        self.row = row;
609        self
610    }
611
612    #[inline]
613    pub fn row(&self) -> usize {
614        self.row
615    }
616
617    #[inline]
618    pub fn desired_size(&self) -> Vector2<f32> {
619        self.desired_size.get()
620    }
621
622    #[inline]
623    pub fn desired_local_position(&self) -> Vector2<f32> {
624        self.desired_local_position
625    }
626
627    #[inline]
628    pub fn screen_bounds(&self) -> Rect<f32> {
629        Rect::new(
630            self.screen_position.x,
631            self.screen_position.y,
632            self.actual_size.get().x,
633            self.actual_size.get().y,
634        )
635    }
636
637    pub fn has_descendant(&self, node_handle: Handle<UiNode>, ui: &UserInterface) -> bool {
638        for child_handle in self.children.iter() {
639            if *child_handle == node_handle {
640                return true;
641            }
642
643            let result = ui
644                .nodes
645                .borrow(*child_handle)
646                .has_descendant(node_handle, ui);
647            if result {
648                return true;
649            }
650        }
651        false
652    }
653
654    /// Searches a node up on tree starting from given root that matches a criteria
655    /// defined by a given func.
656    pub fn find_by_criteria_up<Func: Fn(&UiNode) -> bool>(
657        &self,
658        ui: &UserInterface,
659        func: Func,
660    ) -> Handle<UiNode> {
661        let mut parent_handle = self.parent;
662        while parent_handle.is_some() {
663            let parent_node = ui.nodes.borrow(parent_handle);
664            if func(parent_node) {
665                return parent_handle;
666            }
667            parent_handle = parent_node.parent;
668        }
669        Handle::NONE
670    }
671
672    pub fn handle_routed_message(&mut self, _ui: &mut UserInterface, msg: &mut UiMessage) {
673        if msg.destination() == self.handle() && msg.direction() == MessageDirection::ToWidget {
674            if let Some(msg) = msg.data::<WidgetMessage>() {
675                match msg {
676                    &WidgetMessage::Opacity(opacity) => self.opacity = opacity,
677                    WidgetMessage::Background(background) => self.background = background.clone(),
678                    WidgetMessage::Foreground(foreground) => self.foreground = foreground.clone(),
679                    WidgetMessage::Name(name) => self.name = name.clone(),
680                    &WidgetMessage::Width(width) => {
681                        if self.width != width {
682                            self.width = width;
683                            self.invalidate_layout();
684                        }
685                    }
686                    &WidgetMessage::Height(height) => {
687                        if self.height != height {
688                            self.height = height;
689                            self.invalidate_layout();
690                        }
691                    }
692                    WidgetMessage::VerticalAlignment(vertical_alignment) => {
693                        if self.vertical_alignment != *vertical_alignment {
694                            self.vertical_alignment = *vertical_alignment;
695                            self.invalidate_layout();
696                        }
697                    }
698                    WidgetMessage::HorizontalAlignment(horizontal_alignment) => {
699                        if self.horizontal_alignment != *horizontal_alignment {
700                            self.horizontal_alignment = *horizontal_alignment;
701                            self.invalidate_layout();
702                        }
703                    }
704                    WidgetMessage::MaxSize(max_size) => {
705                        if self.max_size != *max_size {
706                            self.max_size = *max_size;
707                            self.invalidate_layout();
708                        }
709                    }
710                    WidgetMessage::MinSize(min_size) => {
711                        if self.min_size != *min_size {
712                            self.min_size = *min_size;
713                            self.invalidate_layout();
714                        }
715                    }
716                    &WidgetMessage::Row(row) => {
717                        if self.row != row {
718                            self.row = row;
719                            self.invalidate_layout();
720                        }
721                    }
722                    &WidgetMessage::Column(column) => {
723                        if self.column != column {
724                            self.column = column;
725                            self.invalidate_layout();
726                        }
727                    }
728                    &WidgetMessage::Margin(margin) => {
729                        if self.margin != margin {
730                            self.margin = margin;
731                            self.invalidate_layout();
732                        }
733                    }
734                    WidgetMessage::HitTestVisibility(hit_test_visibility) => {
735                        self.hit_test_visibility = *hit_test_visibility
736                    }
737                    &WidgetMessage::Visibility(visibility) => {
738                        self.set_visibility(visibility);
739                    }
740                    &WidgetMessage::DesiredPosition(pos) => {
741                        if self.desired_local_position != pos {
742                            self.desired_local_position = pos;
743                            self.invalidate_layout();
744                        }
745                    }
746                    &WidgetMessage::Enabled(enabled) => {
747                        self.enabled = enabled;
748                    }
749                    &WidgetMessage::Cursor(icon) => {
750                        self.cursor = icon;
751                    }
752                    _ => (),
753                }
754            }
755        }
756    }
757
758    #[inline]
759    pub fn set_vertical_alignment(&mut self, vertical_alignment: VerticalAlignment) -> &mut Self {
760        self.vertical_alignment = vertical_alignment;
761        self
762    }
763
764    #[inline]
765    pub fn vertical_alignment(&self) -> VerticalAlignment {
766        self.vertical_alignment
767    }
768
769    #[inline]
770    pub fn set_horizontal_alignment(
771        &mut self,
772        horizontal_alignment: HorizontalAlignment,
773    ) -> &mut Self {
774        self.horizontal_alignment = horizontal_alignment;
775        self
776    }
777
778    #[inline]
779    pub fn horizontal_alignment(&self) -> HorizontalAlignment {
780        self.horizontal_alignment
781    }
782
783    #[inline]
784    pub fn set_column(&mut self, column: usize) -> &mut Self {
785        self.column = column;
786        self
787    }
788
789    #[inline]
790    pub fn set_margin(&mut self, margin: Thickness) -> &mut Self {
791        self.margin = margin;
792        self
793    }
794
795    #[inline]
796    pub fn margin(&self) -> Thickness {
797        self.margin
798    }
799
800    #[inline]
801    pub fn measure_override(
802        &self,
803        ui: &UserInterface,
804        available_size: Vector2<f32>,
805    ) -> Vector2<f32> {
806        let mut size: Vector2<f32> = Vector2::default();
807
808        for &child in self.children.iter() {
809            ui.measure_node(child, available_size);
810            let desired_size = ui.node(child).desired_size();
811            size.x = size.x.max(desired_size.x);
812            size.y = size.y.max(desired_size.y);
813        }
814
815        size
816    }
817
818    #[inline]
819    pub fn arrange_override(&self, ui: &UserInterface, final_size: Vector2<f32>) -> Vector2<f32> {
820        let final_rect = Rect::new(0.0, 0.0, final_size.x, final_size.y);
821
822        for &child in self.children.iter() {
823            ui.arrange_node(child, &final_rect);
824        }
825
826        final_size
827    }
828
829    #[inline]
830    pub(in crate) fn commit_arrange(&self, position: Vector2<f32>, size: Vector2<f32>) {
831        self.actual_size.set(size);
832        self.actual_local_position.set(position);
833        self.arrange_valid.set(true);
834    }
835
836    #[inline]
837    pub(in crate) fn set_children(&mut self, children: Vec<Handle<UiNode>>) {
838        self.invalidate_layout();
839        self.children = children;
840    }
841
842    #[inline(always)]
843    pub fn is_arrange_valid(&self) -> bool {
844        self.arrange_valid.get()
845    }
846
847    #[inline]
848    pub(in crate) fn commit_measure(&self, desired_size: Vector2<f32>) {
849        self.desired_size.set(desired_size);
850        self.measure_valid.set(true);
851    }
852
853    #[inline(always)]
854    pub fn is_measure_valid(&self) -> bool {
855        self.measure_valid.get()
856    }
857
858    #[inline]
859    pub fn actual_local_position(&self) -> Vector2<f32> {
860        self.actual_local_position.get()
861    }
862
863    #[inline]
864    pub(in crate) fn set_global_visibility(&mut self, value: bool) {
865        self.prev_global_visibility = self.global_visibility;
866        self.global_visibility = value;
867    }
868
869    #[inline]
870    pub fn is_globally_visible(&self) -> bool {
871        self.global_visibility
872    }
873
874    #[inline]
875    pub fn set_visibility(&mut self, visibility: bool) -> &mut Self {
876        if self.visibility != visibility {
877            self.visibility = visibility;
878            self.invalidate_layout();
879            if let Some(layout_events_sender) = self.layout_events_sender.as_ref() {
880                let _ = layout_events_sender.send(LayoutEvent::VisibilityChanged(self.handle));
881            }
882        }
883        self
884    }
885
886    #[inline]
887    pub fn visibility(&self) -> bool {
888        self.visibility
889    }
890
891    #[inline]
892    pub fn set_enabled(&mut self, enabled: bool) -> &mut Self {
893        self.enabled = enabled;
894        self
895    }
896
897    #[inline]
898    pub fn enabled(&self) -> bool {
899        self.enabled
900    }
901
902    #[inline]
903    pub fn set_cursor(&mut self, cursor: Option<CursorIcon>) {
904        self.cursor = cursor;
905    }
906
907    #[inline]
908    pub fn cursor(&self) -> Option<CursorIcon> {
909        self.cursor
910    }
911
912    #[inline]
913    pub fn user_data_ref<T: 'static>(&self) -> Option<&T> {
914        self.user_data.as_ref().and_then(|v| v.downcast_ref::<T>())
915    }
916
917    #[inline]
918    pub fn clip_bounds(&self) -> Rect<f32> {
919        self.clip_bounds.get()
920    }
921
922    #[inline]
923    pub fn set_opacity(&mut self, opacity: Option<f32>) -> &mut Self {
924        self.opacity = opacity;
925        self
926    }
927
928    #[inline]
929    pub fn opacity(&self) -> Option<f32> {
930        self.opacity
931    }
932
933    #[inline]
934    pub fn tooltip(&self) -> Handle<UiNode> {
935        self.tooltip
936    }
937
938    #[inline]
939    pub fn set_tooltip(&mut self, tooltip: Handle<UiNode>) -> &mut Self {
940        self.tooltip = tooltip;
941        self
942    }
943
944    #[inline]
945    pub fn tooltip_time(&self) -> f32 {
946        self.tooltip_time
947    }
948
949    #[inline]
950    pub fn set_tooltip_time(&mut self, tooltip_time: f32) -> &mut Self {
951        self.tooltip_time = tooltip_time;
952        self
953    }
954
955    #[inline]
956    pub fn context_menu(&self) -> Handle<UiNode> {
957        self.context_menu
958    }
959
960    #[inline]
961    /// The context menu receives `PopupMessage`s for being displayed, and so should support those.
962    pub fn set_context_menu(&mut self, context_menu: Handle<UiNode>) -> &mut Self {
963        self.context_menu = context_menu;
964        self
965    }
966}
967
968#[macro_export]
969macro_rules! define_widget_deref {
970    ($ty: ty) => {
971        impl Deref for $ty {
972            type Target = Widget;
973
974            fn deref(&self) -> &Self::Target {
975                &self.widget
976            }
977        }
978
979        impl DerefMut for $ty {
980            fn deref_mut(&mut self) -> &mut Self::Target {
981                &mut self.widget
982            }
983        }
984    };
985}
986
987pub struct WidgetBuilder {
988    pub name: String,
989    pub width: f32,
990    pub height: f32,
991    pub desired_position: Vector2<f32>,
992    pub vertical_alignment: VerticalAlignment,
993    pub horizontal_alignment: HorizontalAlignment,
994    pub max_size: Option<Vector2<f32>>,
995    pub min_size: Option<Vector2<f32>>,
996    pub background: Option<Brush>,
997    pub foreground: Option<Brush>,
998    pub row: usize,
999    pub column: usize,
1000    pub margin: Thickness,
1001    pub children: Vec<Handle<UiNode>>,
1002    pub is_hit_test_visible: bool,
1003    pub visibility: bool,
1004    pub z_index: usize,
1005    pub allow_drag: bool,
1006    pub allow_drop: bool,
1007    pub user_data: Option<Rc<dyn Any>>,
1008    pub draw_on_top: bool,
1009    pub enabled: bool,
1010    pub cursor: Option<CursorIcon>,
1011    pub opacity: Option<f32>,
1012    pub tooltip: Handle<UiNode>,
1013    pub tooltip_time: f32,
1014    pub context_menu: Handle<UiNode>,
1015    pub preview_messages: bool,
1016    pub handle_os_events: bool,
1017}
1018
1019impl Default for WidgetBuilder {
1020    fn default() -> Self {
1021        Self::new()
1022    }
1023}
1024
1025impl WidgetBuilder {
1026    pub fn new() -> Self {
1027        Self {
1028            name: Default::default(),
1029            width: f32::NAN,
1030            height: f32::NAN,
1031            vertical_alignment: VerticalAlignment::Stretch,
1032            horizontal_alignment: HorizontalAlignment::Stretch,
1033            max_size: None,
1034            min_size: None,
1035            background: None,
1036            foreground: None,
1037            row: 0,
1038            column: 0,
1039            margin: Thickness::zero(),
1040            desired_position: Vector2::default(),
1041            children: Vec::new(),
1042            is_hit_test_visible: true,
1043            visibility: true,
1044            z_index: 0,
1045            allow_drag: false,
1046            allow_drop: false,
1047            user_data: None,
1048            draw_on_top: false,
1049            enabled: true,
1050            cursor: None,
1051            opacity: None,
1052            tooltip: Handle::default(),
1053            tooltip_time: 0.1,
1054            context_menu: Handle::default(),
1055            preview_messages: false,
1056            handle_os_events: false,
1057        }
1058    }
1059
1060    pub fn with_preview_messages(mut self, state: bool) -> Self {
1061        self.preview_messages = state;
1062        self
1063    }
1064
1065    pub fn with_handle_os_events(mut self, state: bool) -> Self {
1066        self.handle_os_events = state;
1067        self
1068    }
1069
1070    pub fn with_width(mut self, width: f32) -> Self {
1071        self.width = width;
1072        self
1073    }
1074
1075    pub fn with_height(mut self, height: f32) -> Self {
1076        self.height = height;
1077        self
1078    }
1079
1080    pub fn with_enabled(mut self, enabled: bool) -> Self {
1081        self.enabled = enabled;
1082        self
1083    }
1084
1085    pub fn with_vertical_alignment(mut self, valign: VerticalAlignment) -> Self {
1086        self.vertical_alignment = valign;
1087        self
1088    }
1089
1090    pub fn with_horizontal_alignment(mut self, halign: HorizontalAlignment) -> Self {
1091        self.horizontal_alignment = halign;
1092        self
1093    }
1094
1095    pub fn with_max_size(mut self, max_size: Vector2<f32>) -> Self {
1096        self.max_size = Some(max_size);
1097        self
1098    }
1099
1100    pub fn with_min_size(mut self, min_size: Vector2<f32>) -> Self {
1101        self.min_size = Some(min_size);
1102        self
1103    }
1104
1105    pub fn with_background(mut self, brush: Brush) -> Self {
1106        self.background = Some(brush);
1107        self
1108    }
1109
1110    pub fn with_foreground(mut self, brush: Brush) -> Self {
1111        self.foreground = Some(brush);
1112        self
1113    }
1114
1115    pub fn on_row(mut self, row: usize) -> Self {
1116        self.row = row;
1117        self
1118    }
1119
1120    pub fn on_column(mut self, column: usize) -> Self {
1121        self.column = column;
1122        self
1123    }
1124
1125    pub fn with_margin(mut self, margin: Thickness) -> Self {
1126        self.margin = margin;
1127        self
1128    }
1129
1130    pub fn with_desired_position(mut self, desired_position: Vector2<f32>) -> Self {
1131        self.desired_position = desired_position;
1132        self
1133    }
1134
1135    pub fn with_z_index(mut self, z_index: usize) -> Self {
1136        self.z_index = z_index;
1137        self
1138    }
1139
1140    pub fn with_child(mut self, handle: Handle<UiNode>) -> Self {
1141        if handle.is_some() {
1142            self.children.push(handle);
1143        }
1144        self
1145    }
1146
1147    pub fn with_draw_on_top(mut self, draw_on_top: bool) -> Self {
1148        self.draw_on_top = draw_on_top;
1149        self
1150    }
1151
1152    pub fn with_children<I: IntoIterator<Item = Handle<UiNode>>>(mut self, children: I) -> Self {
1153        for child in children.into_iter() {
1154            if child.is_some() {
1155                self.children.push(child)
1156            }
1157        }
1158        self
1159    }
1160
1161    pub fn with_name(mut self, name: &str) -> Self {
1162        self.name = String::from(name);
1163        self
1164    }
1165
1166    pub fn with_hit_test_visibility(mut self, state: bool) -> Self {
1167        self.is_hit_test_visible = state;
1168        self
1169    }
1170
1171    pub fn with_visibility(mut self, visibility: bool) -> Self {
1172        self.visibility = visibility;
1173        self
1174    }
1175
1176    pub fn with_allow_drop(mut self, allow_drop: bool) -> Self {
1177        self.allow_drop = allow_drop;
1178        self
1179    }
1180
1181    pub fn with_allow_drag(mut self, allow_drag: bool) -> Self {
1182        self.allow_drag = allow_drag;
1183        self
1184    }
1185
1186    pub fn with_user_data(mut self, user_data: Rc<dyn Any>) -> Self {
1187        self.user_data = Some(user_data);
1188        self
1189    }
1190
1191    pub fn with_cursor(mut self, cursor: Option<CursorIcon>) -> Self {
1192        self.cursor = cursor;
1193        self
1194    }
1195
1196    pub fn with_opacity(mut self, opacity: Option<f32>) -> Self {
1197        self.opacity = opacity;
1198        self
1199    }
1200
1201    /// Sets the desired tooltip for the node.
1202    ///
1203    /// ## Important
1204    ///
1205    /// The widget will **own** the tooltip, which means that when widget will be deleted, the
1206    /// tooltip will be deleted too.
1207    pub fn with_tooltip(mut self, tooltip: Handle<UiNode>) -> Self {
1208        if tooltip.is_some() {
1209            self.tooltip = tooltip;
1210        }
1211        self
1212    }
1213
1214    pub fn with_tooltip_time(mut self, tooltip_time: f32) -> Self {
1215        self.tooltip_time = tooltip_time;
1216        self
1217    }
1218
1219    /// The context menu receives `PopupMessage`s for being displayed, and so should support those.
1220    pub fn with_context_menu(mut self, context_menu: Handle<UiNode>) -> Self {
1221        if context_menu.is_some() {
1222            self.context_menu = context_menu;
1223        }
1224        self
1225    }
1226
1227    pub fn build(self) -> Widget {
1228        Widget {
1229            handle: Default::default(),
1230            name: self.name,
1231            desired_local_position: self.desired_position,
1232            width: self.width,
1233            height: self.height,
1234            screen_position: Vector2::default(),
1235            desired_size: Cell::new(Vector2::default()),
1236            actual_local_position: Cell::new(Vector2::default()),
1237            actual_size: Cell::new(Vector2::default()),
1238            min_size: self.min_size.unwrap_or_default(),
1239            max_size: self
1240                .max_size
1241                .unwrap_or_else(|| Vector2::new(f32::INFINITY, f32::INFINITY)),
1242            background: self.background.unwrap_or_else(|| BRUSH_PRIMARY.clone()),
1243            foreground: self.foreground.unwrap_or_else(|| BRUSH_FOREGROUND.clone()),
1244            row: self.row,
1245            column: self.column,
1246            vertical_alignment: self.vertical_alignment,
1247            horizontal_alignment: self.horizontal_alignment,
1248            margin: self.margin,
1249            visibility: self.visibility,
1250            global_visibility: true,
1251            prev_global_visibility: false,
1252            children: self.children,
1253            parent: Handle::NONE,
1254            command_indices: Default::default(),
1255            is_mouse_directly_over: false,
1256            measure_valid: Cell::new(false),
1257            arrange_valid: Cell::new(false),
1258            hit_test_visibility: self.is_hit_test_visible,
1259            prev_measure: Default::default(),
1260            prev_arrange: Default::default(),
1261            z_index: self.z_index,
1262            allow_drag: self.allow_drag,
1263            allow_drop: self.allow_drop,
1264            user_data: self.user_data.clone(),
1265            draw_on_top: self.draw_on_top,
1266            enabled: self.enabled,
1267            cursor: self.cursor,
1268            clip_bounds: Cell::new(Default::default()),
1269            opacity: self.opacity,
1270            tooltip: self.tooltip,
1271            tooltip_time: self.tooltip_time,
1272            context_menu: self.context_menu,
1273            preview_messages: self.preview_messages,
1274            handle_os_events: self.handle_os_events,
1275            layout_events_sender: None,
1276        }
1277    }
1278}