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#[derive(Debug, Clone, PartialEq)]
19pub enum WidgetMessage {
20 MouseDown {
24 pos: Vector2<f32>,
26 button: MouseButton,
28 },
29
30 MouseUp {
34 pos: Vector2<f32>,
36 button: MouseButton,
38 },
39
40 MouseMove {
44 pos: Vector2<f32>,
46 state: MouseState,
48 },
49
50 MouseWheel {
54 pos: Vector2<f32>,
56 amount: f32,
58 },
59
60 MouseLeave,
64
65 MouseEnter,
69
70 Text(char),
74
75 KeyDown(KeyCode),
79
80 KeyUp(KeyCode),
84
85 GotFocus,
90
91 DragStarted(Handle<UiNode>),
95
96 DragOver(Handle<UiNode>),
100
101 Drop(Handle<UiNode>),
105
106 LostFocus,
110
111 TopMost,
116
117 Unlink,
121
122 Remove,
127
128 LinkWith(Handle<UiNode>),
132
133 LinkWithReverse(Handle<UiNode>),
137
138 Background(Brush),
142
143 Foreground(Brush),
147
148 Name(String),
152
153 Width(f32),
158
159 Height(f32),
164
165 VerticalAlignment(VerticalAlignment),
170
171 HorizontalAlignment(HorizontalAlignment),
176
177 MaxSize(Vector2<f32>),
183
184 MinSize(Vector2<f32>),
190
191 Row(usize),
200
201 Column(usize),
210
211 Margin(Thickness),
216
217 HitTestVisibility(bool),
222
223 Visibility(bool),
228
229 ZIndex(usize),
235
236 DesiredPosition(Vector2<f32>),
242
243 Enabled(bool),
248
249 Center,
253
254 Cursor(Option<CursorIcon>),
258
259 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 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_local_position: Vector2<f32>,
315 width: f32,
317 height: f32,
319 pub(in crate) screen_position: Vector2<f32>,
321 min_size: Vector2<f32>,
323 max_size: Vector2<f32>,
325 background: Brush,
326 foreground: Brush,
327 row: usize,
329 column: usize,
331 vertical_alignment: VerticalAlignment,
333 horizontal_alignment: HorizontalAlignment,
335 margin: Thickness,
337 visibility: bool,
339 global_visibility: bool,
340 children: Vec<Handle<UiNode>>,
341 parent: Handle<UiNode>,
342 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 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 pub(in crate) desired_size: Cell<Vector2<f32>>,
369 pub(in crate) actual_local_position: Cell<Vector2<f32>>,
371 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 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 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 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 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}