1#![forbid(unsafe_code)]
6#![allow(irrefutable_let_patterns)]
7#![allow(clippy::float_cmp)]
8#![allow(clippy::upper_case_acronyms)]
9#![allow(clippy::from_over_into)]
10#![allow(clippy::new_without_default)]
11
12#[macro_use]
13extern crate lazy_static;
14
15pub use rg3d_core as core;
16
17pub mod border;
18pub mod brush;
19pub mod button;
20pub mod canvas;
21pub mod check_box;
22pub mod color;
23pub mod curve;
24pub mod decorator;
25pub mod dock;
26pub mod draw;
27pub mod dropdown_list;
28pub mod expander;
29pub mod file_browser;
30pub mod formatted_text;
31pub mod grid;
32pub mod image;
33pub mod inspector;
34pub mod list_view;
35pub mod menu;
36pub mod message;
37pub mod messagebox;
38pub mod numeric;
39pub mod popup;
40pub mod progress_bar;
41pub mod range;
42pub mod rect;
43pub mod scroll_bar;
44pub mod scroll_panel;
45pub mod scroll_viewer;
46pub mod stack_panel;
47pub mod tab_control;
48pub mod text;
49pub mod text_box;
50pub mod tree;
51pub mod ttf;
52pub mod utils;
53pub mod vec;
54pub mod vector_image;
55pub mod widget;
56pub mod window;
57pub mod wrap_panel;
58
59use crate::{
60 brush::Brush,
61 canvas::Canvas,
62 core::{
63 algebra::Vector2,
64 color::Color,
65 math::{clampf, Rect},
66 pool::{Handle, Pool},
67 scope_profile,
68 },
69 draw::{CommandTexture, Draw, DrawingContext},
70 message::{
71 ButtonState, CursorIcon, KeyboardModifiers, MessageDirection, MouseButton, OsEvent,
72 UiMessage,
73 },
74 popup::{Placement, PopupMessage},
75 ttf::{Font, SharedFont},
76 widget::{Widget, WidgetBuilder, WidgetMessage},
77};
78use copypasta::ClipboardContext;
79use fxhash::{FxHashMap, FxHashSet};
80use std::{
81 any::{Any, TypeId},
82 cell::Cell,
83 collections::VecDeque,
84 fmt::Debug,
85 ops::{Deref, DerefMut, Index, IndexMut},
86 sync::{
87 mpsc::{self, Receiver, Sender, TryRecvError},
88 Arc, Mutex,
89 },
90};
91
92pub const COLOR_DARKEST: Color = Color::opaque(20, 20, 20);
94pub const COLOR_DARKER: Color = Color::opaque(30, 30, 30);
95pub const COLOR_DARK: Color = Color::opaque(40, 40, 40);
96pub const COLOR_PRIMARY: Color = Color::opaque(50, 50, 50);
97pub const COLOR_LIGHT: Color = Color::opaque(65, 65, 65);
98pub const COLOR_LIGHTER: Color = Color::opaque(80, 80, 80);
99pub const COLOR_LIGHTEST: Color = Color::opaque(95, 95, 95);
100pub const COLOR_BRIGHT: Color = Color::opaque(130, 130, 130);
101pub const COLOR_BRIGHT_BLUE: Color = Color::opaque(80, 118, 178);
102pub const COLOR_TEXT: Color = Color::opaque(220, 220, 220);
103pub const COLOR_FOREGROUND: Color = Color::WHITE;
104
105pub const BRUSH_DARKEST: Brush = Brush::Solid(COLOR_DARKEST);
106pub const BRUSH_DARKER: Brush = Brush::Solid(COLOR_DARKER);
107pub const BRUSH_DARK: Brush = Brush::Solid(COLOR_DARK);
108pub const BRUSH_PRIMARY: Brush = Brush::Solid(COLOR_PRIMARY);
109pub const BRUSH_LIGHT: Brush = Brush::Solid(COLOR_LIGHT);
110pub const BRUSH_LIGHTER: Brush = Brush::Solid(COLOR_LIGHTER);
111pub const BRUSH_LIGHTEST: Brush = Brush::Solid(COLOR_LIGHTEST);
112pub const BRUSH_BRIGHT: Brush = Brush::Solid(COLOR_BRIGHT);
113pub const BRUSH_BRIGHT_BLUE: Brush = Brush::Solid(COLOR_BRIGHT_BLUE);
114pub const BRUSH_TEXT: Brush = Brush::Solid(COLOR_TEXT);
115pub const BRUSH_FOREGROUND: Brush = Brush::Solid(COLOR_FOREGROUND);
116
117#[derive(Copy, Clone, PartialEq, Debug)]
118pub enum HorizontalAlignment {
119 Stretch,
120 Left,
121 Center,
122 Right,
123}
124
125#[derive(Copy, Clone, PartialEq, Debug)]
126pub enum VerticalAlignment {
127 Stretch,
128 Top,
129 Center,
130 Bottom,
131}
132
133#[derive(Copy, Clone, PartialEq, Debug)]
134pub struct Thickness {
135 pub left: f32,
136 pub top: f32,
137 pub right: f32,
138 pub bottom: f32,
139}
140
141impl Default for Thickness {
142 fn default() -> Self {
143 Self::uniform(0.0)
144 }
145}
146
147#[derive(Copy, Clone, Debug, PartialEq)]
148pub enum Orientation {
149 Vertical,
150 Horizontal,
151}
152
153impl Thickness {
154 pub fn zero() -> Self {
155 Self {
156 left: 0.0,
157 top: 0.0,
158 right: 0.0,
159 bottom: 0.0,
160 }
161 }
162
163 pub fn uniform(v: f32) -> Self {
164 Self {
165 left: v,
166 top: v,
167 right: v,
168 bottom: v,
169 }
170 }
171
172 pub fn bottom(v: f32) -> Self {
173 Self {
174 left: 0.0,
175 top: 0.0,
176 right: 0.0,
177 bottom: v,
178 }
179 }
180
181 pub fn top(v: f32) -> Self {
182 Self {
183 left: 0.0,
184 top: v,
185 right: 0.0,
186 bottom: 0.0,
187 }
188 }
189
190 pub fn left(v: f32) -> Self {
191 Self {
192 left: v,
193 top: 0.0,
194 right: 0.0,
195 bottom: 0.0,
196 }
197 }
198
199 pub fn right(v: f32) -> Self {
200 Self {
201 left: 0.0,
202 top: 0.0,
203 right: v,
204 bottom: 0.0,
205 }
206 }
207
208 pub fn offset(&self) -> Vector2<f32> {
209 Vector2::new(self.left, self.top)
210 }
211
212 pub fn axes_margin(&self) -> Vector2<f32> {
214 Vector2::new(self.left + self.right, self.top + self.bottom)
215 }
216}
217
218type NodeHandle = Handle<UiNode>;
219
220#[derive(Default)]
221pub struct NodeHandleMapping {
222 hash_map: FxHashMap<NodeHandle, NodeHandle>,
223}
224
225impl NodeHandleMapping {
226 pub fn add_mapping(&mut self, old: Handle<UiNode>, new: Handle<UiNode>) {
227 self.hash_map.insert(old, new);
228 }
229
230 pub fn resolve(&self, old: &mut Handle<UiNode>) {
231 if old.is_some() {
233 if let Some(clone) = self.hash_map.get(old) {
234 *old = *clone;
235 }
236 }
237 }
238
239 pub fn resolve_cell(&self, old: &mut Cell<Handle<UiNode>>) {
240 if old.get().is_some() {
242 if let Some(clone) = self.hash_map.get(&old.get()) {
243 old.set(*clone)
244 }
245 }
246 }
247
248 pub fn resolve_slice(&self, slice: &mut [Handle<UiNode>]) {
249 for item in slice {
250 self.resolve(item);
251 }
252 }
253}
254
255pub trait BaseControl: 'static {
256 fn as_any(&self) -> &dyn Any;
257
258 fn as_any_mut(&mut self) -> &mut dyn Any;
259
260 fn clone_boxed(&self) -> Box<dyn Control>;
261}
262
263impl<T: Any + Clone + 'static + Control> BaseControl for T {
264 fn as_any(&self) -> &dyn Any {
265 self
266 }
267
268 fn as_any_mut(&mut self) -> &mut dyn Any {
269 self
270 }
271
272 fn clone_boxed(&self) -> Box<dyn Control> {
273 Box::new(self.clone())
274 }
275}
276
277pub trait Control: BaseControl + Deref<Target = Widget> + DerefMut {
279 fn query_component(&self, type_id: TypeId) -> Option<&dyn Any>;
287
288 fn resolve(&mut self, _node_map: &NodeHandleMapping) {}
289
290 fn on_remove(&self, _sender: &Sender<UiMessage>) {}
291
292 fn measure_override(&self, ui: &UserInterface, available_size: Vector2<f32>) -> Vector2<f32> {
293 scope_profile!();
294
295 self.deref().measure_override(ui, available_size)
296 }
297
298 fn arrange_override(&self, ui: &UserInterface, final_size: Vector2<f32>) -> Vector2<f32> {
299 scope_profile!();
300
301 self.deref().arrange_override(ui, final_size)
302 }
303
304 fn draw(&self, _drawing_context: &mut DrawingContext) {}
305
306 fn update(&mut self, _dt: f32, _sender: &Sender<UiMessage>) {}
307
308 fn handle_routed_message(&mut self, ui: &mut UserInterface, message: &mut UiMessage);
316
317 fn preview_message(&self, _ui: &UserInterface, _message: &mut UiMessage) {
337 }
339
340 fn handle_os_event(
349 &mut self,
350 _self_handle: Handle<UiNode>,
351 _ui: &mut UserInterface,
352 _event: &OsEvent,
353 ) {
354 }
355}
356
357pub struct DragContext {
358 is_dragging: bool,
359 drag_node: Handle<UiNode>,
360 click_pos: Vector2<f32>,
361 drag_preview: Handle<UiNode>,
362}
363
364impl Default for DragContext {
365 fn default() -> Self {
366 Self {
367 is_dragging: false,
368 drag_node: Default::default(),
369 click_pos: Vector2::new(0.0, 0.0),
370 drag_preview: Default::default(),
371 }
372 }
373}
374
375#[derive(Copy, Clone, Debug, Eq, PartialEq)]
376pub struct MouseState {
377 left: ButtonState,
378 right: ButtonState,
379 middle: ButtonState,
380 }
382
383impl Default for MouseState {
384 fn default() -> Self {
385 Self {
386 left: ButtonState::Released,
387 right: ButtonState::Released,
388 middle: ButtonState::Released,
389 }
390 }
391}
392
393pub struct UiNode(pub Box<dyn Control>);
394
395impl Deref for UiNode {
396 type Target = dyn Control;
397
398 fn deref(&self) -> &Self::Target {
399 self.0.deref()
400 }
401}
402
403impl DerefMut for UiNode {
404 fn deref_mut(&mut self) -> &mut Self::Target {
405 self.0.deref_mut()
406 }
407}
408
409impl UiNode {
410 pub fn new<T: Control>(widget: T) -> Self {
411 Self(Box::new(widget))
412 }
413
414 pub fn cast<T: Control>(&self) -> Option<&T> {
415 self.0.as_any().downcast_ref::<T>()
416 }
417
418 pub fn cast_mut<T: Control>(&mut self) -> Option<&mut T> {
419 self.0.as_any_mut().downcast_mut::<T>()
420 }
421}
422
423pub struct BuildContext<'a> {
424 ui: &'a mut UserInterface,
425}
426
427impl<'a> BuildContext<'a> {
428 pub fn add_node(&mut self, node: UiNode) -> Handle<UiNode> {
429 self.ui.add_node(node)
430 }
431
432 pub fn link(&mut self, child: Handle<UiNode>, parent: Handle<UiNode>) {
433 self.ui.link_nodes_internal(child, parent, false)
434 }
435
436 pub fn copy(&mut self, node: Handle<UiNode>) -> Handle<UiNode> {
437 self.ui.copy_node(node)
438 }
439}
440
441impl<'a> Index<Handle<UiNode>> for BuildContext<'a> {
442 type Output = UiNode;
443
444 fn index(&self, index: Handle<UiNode>) -> &Self::Output {
445 &self.ui.nodes[index]
446 }
447}
448
449impl<'a> IndexMut<Handle<UiNode>> for BuildContext<'a> {
450 fn index_mut(&mut self, index: Handle<UiNode>) -> &mut Self::Output {
451 &mut self.ui.nodes[index]
452 }
453}
454
455#[derive(Copy, Clone)]
456pub struct RestrictionEntry {
457 pub handle: Handle<UiNode>,
459
460 pub stop: bool,
468}
469
470struct TooltipEntry {
471 tooltip: Handle<UiNode>,
472 time: f32,
474 max_time: f32,
479}
480impl TooltipEntry {
481 fn new(tooltip: Handle<UiNode>, time: f32) -> TooltipEntry {
482 Self {
483 tooltip,
484 time,
485 max_time: time,
486 }
487 }
488
489 fn decrease(&mut self, amount: f32) {
490 self.time -= amount;
491 }
492
493 fn should_display(&self) -> bool {
494 self.time > 0.0
495 }
496}
497
498#[derive(Debug)]
499enum LayoutEvent {
500 MeasurementInvalidated(Handle<UiNode>),
501 ArrangementInvalidated(Handle<UiNode>),
502 VisibilityChanged(Handle<UiNode>),
503}
504
505pub struct UserInterface {
506 screen_size: Vector2<f32>,
507 nodes: Pool<UiNode>,
508 drawing_context: DrawingContext,
509 visual_debug: bool,
510 root_canvas: Handle<UiNode>,
511 picked_node: Handle<UiNode>,
512 prev_picked_node: Handle<UiNode>,
513 captured_node: Handle<UiNode>,
514 keyboard_focus_node: Handle<UiNode>,
515 cursor_position: Vector2<f32>,
516 receiver: Receiver<UiMessage>,
517 sender: Sender<UiMessage>,
518 stack: Vec<Handle<UiNode>>,
519 picking_stack: Vec<RestrictionEntry>,
520 bubble_queue: VecDeque<Handle<UiNode>>,
521 drag_context: DragContext,
522 mouse_state: MouseState,
523 keyboard_modifiers: KeyboardModifiers,
524 cursor_icon: CursorIcon,
525 active_tooltip: Option<TooltipEntry>,
526 preview_set: FxHashSet<Handle<UiNode>>,
527 clipboard: Option<ClipboardContext>,
528 layout_events_receiver: Receiver<LayoutEvent>,
529 layout_events_sender: Sender<LayoutEvent>,
530 need_update_global_transform: bool,
531}
532
533lazy_static! {
534 pub static ref DEFAULT_FONT: SharedFont = {
535 let font_bytes = std::include_bytes!("./built_in_font.ttf").to_vec();
536 let font = Font::from_memory(font_bytes, 16.0, Font::default_char_set()).unwrap();
537 Arc::new(Mutex::new(font)).into()
538 };
539}
540
541fn draw_node(
542 nodes: &Pool<UiNode>,
543 node_handle: Handle<UiNode>,
544 drawing_context: &mut DrawingContext,
545) {
546 scope_profile!();
547
548 let node = &nodes[node_handle];
549 if !node.is_globally_visible() {
550 return;
551 }
552
553 let bounds = node.screen_bounds();
558 let mut parent = node.parent();
559 while parent.is_some() {
560 let parent_node = nodes.borrow(parent);
561 if !parent_node.screen_bounds().intersects(bounds) {
562 return;
563 }
564 parent = parent_node.parent();
565 }
566
567 let start_index = drawing_context.get_commands().len();
568
569 let pushed = if !is_node_enabled(nodes, node_handle) {
570 drawing_context.push_opacity(0.4);
571 true
572 } else if let Some(opacity) = node.opacity() {
573 drawing_context.push_opacity(opacity);
574 true
575 } else {
576 false
577 };
578
579 node.draw(drawing_context);
580
581 let end_index = drawing_context.get_commands().len();
582 for i in start_index..end_index {
583 node.command_indices.borrow_mut().push(i);
584 }
585
586 for &child_node in node.children().iter() {
588 if !nodes[child_node].is_draw_on_top() {
590 draw_node(nodes, child_node, drawing_context);
591 }
592 }
593
594 if pushed {
595 drawing_context.pop_opacity();
596 }
597}
598
599fn is_node_enabled(nodes: &Pool<UiNode>, handle: Handle<UiNode>) -> bool {
600 let root_node = &nodes[handle];
601 let mut enabled = root_node.enabled();
602 let mut parent = root_node.parent();
603 while parent.is_some() {
604 let node = &nodes[parent];
605 if !node.enabled() {
606 enabled = false;
607 break;
608 }
609 parent = node.parent();
610 }
611 enabled
612}
613
614impl UserInterface {
615 pub fn new(screen_size: Vector2<f32>) -> UserInterface {
616 let (sender, receiver) = mpsc::channel();
617 let (layout_events_sender, layout_events_receiver) = mpsc::channel();
618 let mut ui = UserInterface {
619 screen_size,
620 sender,
621 receiver,
622 visual_debug: false,
623 captured_node: Handle::NONE,
624 root_canvas: Handle::NONE,
625 nodes: Pool::new(),
626 cursor_position: Vector2::new(0.0, 0.0),
627 drawing_context: DrawingContext::new(),
628 picked_node: Handle::NONE,
629 prev_picked_node: Handle::NONE,
630 keyboard_focus_node: Handle::NONE,
631 stack: Default::default(),
632 picking_stack: Default::default(),
633 bubble_queue: Default::default(),
634 drag_context: Default::default(),
635 mouse_state: Default::default(),
636 keyboard_modifiers: Default::default(),
637 cursor_icon: Default::default(),
638 active_tooltip: Default::default(),
639 preview_set: Default::default(),
640 clipboard: ClipboardContext::new().ok(),
641 layout_events_receiver,
642 layout_events_sender,
643 need_update_global_transform: Default::default(),
644 };
645 ui.root_canvas = ui.add_node(UiNode::new(Canvas::new(WidgetBuilder::new().build())));
646 ui
647 }
648
649 pub fn keyboard_modifiers(&self) -> KeyboardModifiers {
650 self.keyboard_modifiers
651 }
652
653 pub fn build_ctx(&mut self) -> BuildContext<'_> {
654 BuildContext { ui: self }
655 }
656
657 #[inline]
658 pub fn capture_mouse(&mut self, node: Handle<UiNode>) -> bool {
659 if self.captured_node.is_none() {
660 self.captured_node = node;
661 true
662 } else {
663 false
664 }
665 }
666
667 #[inline]
668 pub fn release_mouse_capture(&mut self) {
669 self.captured_node = Handle::NONE;
670 }
671
672 #[inline]
673 pub fn get_drawing_context(&self) -> &DrawingContext {
674 &self.drawing_context
675 }
676
677 #[inline]
678 pub fn get_drawing_context_mut(&mut self) -> &mut DrawingContext {
679 &mut self.drawing_context
680 }
681
682 pub fn is_node_enabled(&self, handle: Handle<UiNode>) -> bool {
683 is_node_enabled(&self.nodes, handle)
684 }
685
686 fn update_global_visibility(&mut self, from: Handle<UiNode>) {
687 scope_profile!();
688
689 self.stack.clear();
690 self.stack.push(from);
691 while let Some(node_handle) = self.stack.pop() {
692 let (widget, parent) = self
693 .nodes
694 .try_borrow_dependant_mut(node_handle, |n| n.parent());
695
696 if let Some(widget) = widget {
697 self.stack.extend_from_slice(widget.children());
698
699 let visibility = if let Some(parent) = parent {
700 widget.visibility() && parent.is_globally_visible()
701 } else {
702 widget.visibility()
703 };
704
705 if widget.prev_global_visibility != visibility {
706 let _ = self
707 .layout_events_sender
708 .send(LayoutEvent::MeasurementInvalidated(node_handle));
709 let _ = self
710 .layout_events_sender
711 .send(LayoutEvent::ArrangementInvalidated(node_handle));
712 }
713
714 widget.set_global_visibility(visibility);
715 }
716 }
717 }
718
719 fn update_transform(&mut self) {
720 scope_profile!();
721
722 self.stack.clear();
723 self.stack.push(self.root_canvas);
724 while let Some(node_handle) = self.stack.pop() {
725 let (widget, parent) = self
726 .nodes
727 .try_borrow_dependant_mut(node_handle, |n| n.parent());
728
729 let widget = widget.unwrap();
730
731 if widget.is_globally_visible() {
732 self.stack.extend_from_slice(widget.children());
733
734 let screen_position = if let Some(parent) = parent {
735 widget.actual_local_position() + parent.screen_position()
736 } else {
737 widget.actual_local_position()
738 };
739
740 widget.screen_position = screen_position;
741 }
742 }
743 }
744
745 pub fn screen_size(&self) -> Vector2<f32> {
746 self.screen_size
747 }
748
749 fn handle_layout_events(&mut self) {
750 fn invalidate_recursive_up(
751 nodes: &Pool<UiNode>,
752 node: Handle<UiNode>,
753 callback: fn(&UiNode),
754 ) {
755 if let Some(node_ref) = nodes.try_borrow(node) {
756 (callback)(node_ref);
757 if node_ref.parent().is_some() {
758 invalidate_recursive_up(nodes, node_ref.parent(), callback);
759 }
760 }
761 }
762
763 while let Ok(layout_event) = self.layout_events_receiver.try_recv() {
764 match layout_event {
765 LayoutEvent::MeasurementInvalidated(node) => {
766 invalidate_recursive_up(&self.nodes, node, |node_ref| {
767 node_ref.measure_valid.set(false)
768 });
769 }
770 LayoutEvent::ArrangementInvalidated(node) => {
771 invalidate_recursive_up(&self.nodes, node, |node_ref| {
772 node_ref.arrange_valid.set(false)
773 });
774 self.need_update_global_transform = true;
775 }
776 LayoutEvent::VisibilityChanged(node) => {
777 self.update_global_visibility(node);
778 }
779 }
780 }
781 }
782
783 pub fn update(&mut self, screen_size: Vector2<f32>, dt: f32) {
784 scope_profile!();
785
786 self.screen_size = screen_size;
787
788 self.handle_layout_events();
789
790 self.measure_node(self.root_canvas, screen_size);
791 self.arrange_node(
792 self.root_canvas,
793 &Rect::new(0.0, 0.0, screen_size.x, screen_size.y),
794 );
795
796 if self.need_update_global_transform {
797 self.update_transform();
798 self.need_update_global_transform = false;
799 }
800
801 let sender = self.sender.clone();
802 for node in self.nodes.iter_mut() {
803 node.update(dt, &sender)
804 }
805
806 self.update_tooltips(dt);
807
808 if !self.drag_context.is_dragging {
809 self.cursor_icon = CursorIcon::default();
812 let mut handle = self.picked_node;
813 while handle.is_some() {
814 let node = &self.nodes[handle];
815 if let Some(cursor) = node.cursor() {
816 self.cursor_icon = cursor;
817 break;
818 }
819 handle = node.parent();
820 }
821 }
822 }
823
824 pub fn cursor(&self) -> CursorIcon {
825 self.cursor_icon
826 }
827
828 pub fn draw(&mut self) -> &DrawingContext {
829 scope_profile!();
830
831 self.calculate_clip_bounds(
832 self.root_canvas,
833 Rect::new(0.0, 0.0, self.screen_size.x, self.screen_size.y),
834 );
835 self.drawing_context.clear();
836
837 for node in self.nodes.iter_mut() {
838 node.command_indices.borrow_mut().clear();
839 }
840
841 draw_node(&self.nodes, self.root_canvas, &mut self.drawing_context);
843
844 self.stack.clear();
847 self.stack.push(self.root());
848 while let Some(node_handle) = self.stack.pop() {
849 let node = &self.nodes[node_handle];
850 if node.is_draw_on_top() {
851 draw_node(&self.nodes, node_handle, &mut self.drawing_context);
852 }
853 for &child in node.children() {
854 self.stack.push(child);
855 }
856 }
857
858 if self.visual_debug {
860 if self.picked_node.is_some() {
861 let bounds = self.nodes.borrow(self.picked_node).screen_bounds();
862 self.drawing_context.push_rect(&bounds, 1.0);
863 self.drawing_context.commit(
864 bounds,
865 Brush::Solid(Color::WHITE),
866 CommandTexture::None,
867 None,
868 );
869 }
870
871 if self.keyboard_focus_node.is_some() {
872 let bounds = self.nodes.borrow(self.keyboard_focus_node).screen_bounds();
873 self.drawing_context.push_rect(&bounds, 1.0);
874 self.drawing_context.commit(
875 bounds,
876 Brush::Solid(Color::GREEN),
877 CommandTexture::None,
878 None,
879 );
880 }
881 }
882
883 &self.drawing_context
884 }
885
886 pub fn clipboard(&self) -> Option<&ClipboardContext> {
887 self.clipboard.as_ref()
888 }
889
890 pub fn clipboard_mut(&mut self) -> Option<&mut ClipboardContext> {
891 self.clipboard.as_mut()
892 }
893
894 pub fn arrange_node(&self, handle: Handle<UiNode>, final_rect: &Rect<f32>) -> bool {
895 scope_profile!();
896
897 let node = self.node(handle);
898
899 if node.is_arrange_valid() && node.prev_arrange.get() == *final_rect {
900 return false;
901 }
902
903 if node.visibility() {
904 node.prev_arrange.set(*final_rect);
905
906 let margin = node.margin().axes_margin();
907
908 let mut size = Vector2::new(
909 (final_rect.w() - margin.x).max(0.0),
910 (final_rect.h() - margin.y).max(0.0),
911 );
912
913 let available_size = size;
914
915 if node.horizontal_alignment() != HorizontalAlignment::Stretch {
916 size.x = size.x.min(node.desired_size().x - margin.x);
917 }
918 if node.vertical_alignment() != VerticalAlignment::Stretch {
919 size.y = size.y.min(node.desired_size().y - margin.y);
920 }
921
922 if node.width() > 0.0 {
923 size.x = node.width();
924 }
925 if node.height() > 0.0 {
926 size.y = node.height();
927 }
928
929 size = node.arrange_override(self, size);
930
931 size.x = size.x.min(final_rect.w());
932 size.y = size.y.min(final_rect.h());
933
934 let mut origin = final_rect.position + node.margin().offset();
935
936 match node.horizontal_alignment() {
937 HorizontalAlignment::Center | HorizontalAlignment::Stretch => {
938 origin.x += (available_size.x - size.x) * 0.5;
939 }
940 HorizontalAlignment::Right => origin.x += available_size.x - size.x,
941 _ => (),
942 }
943
944 match node.vertical_alignment() {
945 VerticalAlignment::Center | VerticalAlignment::Stretch => {
946 origin.y += (available_size.y - size.y) * 0.5;
947 }
948 VerticalAlignment::Bottom => origin.y += available_size.y - size.y,
949 _ => (),
950 }
951
952 node.commit_arrange(origin, size);
953 }
954
955 true
956 }
957
958 pub fn measure_node(&self, handle: Handle<UiNode>, available_size: Vector2<f32>) -> bool {
959 scope_profile!();
960
961 let node = self.node(handle);
962
963 if node.is_measure_valid() && node.prev_measure.get() == available_size {
964 return false;
965 }
966
967 if node.visibility() {
968 node.prev_measure.set(available_size);
969
970 let axes_margin = node.margin().axes_margin();
971 let mut inner_size = available_size - axes_margin;
972 inner_size.x = inner_size.x.max(0.0);
973 inner_size.y = inner_size.y.max(0.0);
974
975 let mut size = Vector2::new(
976 if node.width() > 0.0 {
977 node.width()
978 } else {
979 inner_size.x
980 },
981 if node.height() > 0.0 {
982 node.height()
983 } else {
984 inner_size.y
985 },
986 );
987
988 size.x = clampf(size.x, node.min_size().x, node.max_size().x);
989 size.y = clampf(size.y, node.min_size().y, node.max_size().y);
990
991 let mut desired_size = node.measure_override(self, size);
992
993 if !node.width().is_nan() {
994 desired_size.x = node.width();
995 }
996 if !node.height().is_nan() {
997 desired_size.y = node.height();
998 }
999
1000 desired_size.x = clampf(desired_size.x, node.min_size().x, node.max_size().x);
1001 desired_size.y = clampf(desired_size.y, node.min_size().y, node.max_size().y);
1002
1003 desired_size += axes_margin;
1004
1005 desired_size.x = desired_size.x.min(available_size.x);
1006 desired_size.y = desired_size.y.min(available_size.y);
1007
1008 node.commit_measure(desired_size);
1009 } else {
1010 node.commit_measure(Vector2::new(0.0, 0.0));
1011 }
1012
1013 true
1014 }
1015
1016 fn is_node_clipped(&self, node_handle: Handle<UiNode>, pt: Vector2<f32>) -> bool {
1017 scope_profile!();
1018
1019 let mut clipped = true;
1020
1021 let widget = self.nodes.borrow(node_handle);
1022
1023 if widget.is_globally_visible() {
1024 clipped = !widget.screen_bounds().contains(pt);
1025
1026 if !clipped {
1027 for command_index in widget.command_indices.borrow().iter() {
1028 if let Some(command) = self.drawing_context.get_commands().get(*command_index) {
1029 if let Some(geometry) = command.clipping_geometry.as_ref() {
1030 if geometry.is_contains_point(pt) {
1031 clipped = false;
1032 break;
1033 }
1034 }
1035 }
1036 }
1037 }
1038
1039 if !widget.parent().is_none() && !clipped {
1041 clipped |= self.is_node_clipped(widget.parent(), pt);
1042 }
1043 }
1044
1045 clipped
1046 }
1047
1048 fn is_node_contains_point(&self, node_handle: Handle<UiNode>, pt: Vector2<f32>) -> bool {
1049 scope_profile!();
1050
1051 let widget = self.nodes.borrow(node_handle);
1052
1053 if !widget.is_globally_visible() {
1054 return false;
1055 }
1056
1057 if !self.is_node_clipped(node_handle, pt) {
1058 for command_index in widget.command_indices.borrow().iter() {
1059 if let Some(command) = self.drawing_context.get_commands().get(*command_index) {
1060 if self.drawing_context.is_command_contains_point(command, pt) {
1061 return true;
1062 }
1063 }
1064 }
1065 }
1066
1067 false
1068 }
1069
1070 fn pick_node(
1071 &self,
1072 node_handle: Handle<UiNode>,
1073 pt: Vector2<f32>,
1074 level: &mut i32,
1075 ) -> Handle<UiNode> {
1076 scope_profile!();
1077
1078 let widget = self.nodes.borrow(node_handle);
1079
1080 if !widget.is_hit_test_visible()
1081 || !widget.enabled()
1082 || !widget.screen_bounds().intersects(Rect {
1083 position: Default::default(),
1084 size: self.screen_size,
1085 })
1086 {
1087 return Handle::NONE;
1088 }
1089
1090 let (mut picked, mut topmost_picked_level) = if self.is_node_contains_point(node_handle, pt)
1091 {
1092 (node_handle, *level)
1093 } else {
1094 (Handle::NONE, 0)
1095 };
1096
1097 for child_handle in widget.children() {
1098 *level += 1;
1099 let picked_child = self.pick_node(*child_handle, pt, level);
1100 if picked_child.is_some() && *level > topmost_picked_level {
1101 topmost_picked_level = *level;
1102 picked = picked_child;
1103 }
1104 }
1105
1106 picked
1107 }
1108
1109 pub fn cursor_position(&self) -> Vector2<f32> {
1110 self.cursor_position
1111 }
1112
1113 pub fn hit_test(&self, pt: Vector2<f32>) -> Handle<UiNode> {
1114 scope_profile!();
1115
1116 if self.nodes.is_valid_handle(self.captured_node) {
1117 self.captured_node
1118 } else if self.picking_stack.is_empty() {
1119 let mut level = 0;
1121 self.pick_node(self.root_canvas, pt, &mut level)
1122 } else {
1123 for root in self.picking_stack.iter().rev() {
1128 if self.nodes.is_valid_handle(root.handle) {
1129 let mut level = 0;
1130 let picked = self.pick_node(root.handle, pt, &mut level);
1131 if picked.is_some() {
1132 return picked;
1133 }
1134 }
1135 if root.stop {
1136 break;
1137 }
1138 }
1139 Handle::NONE
1140 }
1141 }
1142
1143 pub fn find_by_criteria_down<Func>(
1146 &self,
1147 node_handle: Handle<UiNode>,
1148 func: &Func,
1149 ) -> Handle<UiNode>
1150 where
1151 Func: Fn(&UiNode) -> bool,
1152 {
1153 let node = self.nodes.borrow(node_handle);
1154
1155 if func(node) {
1156 return node_handle;
1157 }
1158
1159 for child_handle in node.children() {
1160 let result = self.find_by_criteria_down(*child_handle, func);
1161
1162 if result.is_some() {
1163 return result;
1164 }
1165 }
1166
1167 Handle::NONE
1168 }
1169
1170 pub fn find_by_criteria_up<Func>(
1173 &self,
1174 node_handle: Handle<UiNode>,
1175 func: Func,
1176 ) -> Handle<UiNode>
1177 where
1178 Func: Fn(&UiNode) -> bool,
1179 {
1180 let node = self.nodes.borrow(node_handle);
1181
1182 if func(node) {
1183 return node_handle;
1184 }
1185
1186 if node.parent().is_some() {
1187 self.find_by_criteria_up(node.parent(), func)
1188 } else {
1189 Handle::NONE
1190 }
1191 }
1192
1193 pub fn is_node_child_of(
1196 &self,
1197 node_handle: Handle<UiNode>,
1198 root_handle: Handle<UiNode>,
1199 ) -> bool {
1200 self.nodes
1201 .borrow(root_handle)
1202 .has_descendant(node_handle, self)
1203 }
1204
1205 fn calculate_clip_bounds(&self, node: Handle<UiNode>, parent_bounds: Rect<f32>) {
1207 let node = &self.nodes[node];
1208 node.clip_bounds
1209 .set(node.screen_bounds().clip_by(parent_bounds));
1210 for &child in node.children() {
1211 self.calculate_clip_bounds(child, node.clip_bounds.get());
1212 }
1213 }
1214
1215 pub fn is_node_direct_child_of(
1217 &self,
1218 node_handle: Handle<UiNode>,
1219 root_handle: Handle<UiNode>,
1220 ) -> bool {
1221 for child_handle in self.nodes.borrow(root_handle).children() {
1222 if *child_handle == node_handle {
1223 return true;
1224 }
1225 }
1226 false
1227 }
1228
1229 pub fn find_by_name_up(&self, node_handle: Handle<UiNode>, name: &str) -> Handle<UiNode> {
1231 self.find_by_criteria_up(node_handle, |node| node.name() == name)
1232 }
1233
1234 pub fn find_by_name_down(&self, node_handle: Handle<UiNode>, name: &str) -> Handle<UiNode> {
1236 self.find_by_criteria_down(node_handle, &|node| node.name() == name)
1237 }
1238
1239 pub fn borrow_by_name_up(&self, start_node_handle: Handle<UiNode>, name: &str) -> &UiNode {
1241 self.nodes
1242 .borrow(self.find_by_name_up(start_node_handle, name))
1243 }
1244
1245 pub fn borrow_by_name_down(&self, start_node_handle: Handle<UiNode>, name: &str) -> &UiNode {
1247 self.nodes
1248 .borrow(self.find_by_name_down(start_node_handle, name))
1249 }
1250
1251 pub fn borrow_by_criteria_up<Func>(
1258 &self,
1259 start_node_handle: Handle<UiNode>,
1260 func: Func,
1261 ) -> &UiNode
1262 where
1263 Func: Fn(&UiNode) -> bool,
1264 {
1265 self.nodes
1266 .borrow(self.find_by_criteria_up(start_node_handle, func))
1267 }
1268
1269 pub fn try_borrow_by_criteria_up<Func>(
1270 &self,
1271 start_node_handle: Handle<UiNode>,
1272 func: Func,
1273 ) -> Option<&UiNode>
1274 where
1275 Func: Fn(&UiNode) -> bool,
1276 {
1277 self.nodes
1278 .try_borrow(self.find_by_criteria_up(start_node_handle, func))
1279 }
1280
1281 pub fn try_borrow_by_type_up<T>(
1282 &self,
1283 node_handle: Handle<UiNode>,
1284 ) -> Option<(Handle<UiNode>, &T)>
1285 where
1286 T: Control,
1287 {
1288 let node = self.nodes.borrow(node_handle);
1289
1290 let casted = node.cast::<T>();
1291 if let Some(casted) = casted {
1292 return Some((node_handle, casted));
1293 }
1294
1295 if node.parent().is_some() {
1296 self.try_borrow_by_type_up(node.parent())
1297 } else {
1298 None
1299 }
1300 }
1301
1302 pub fn sender(&self) -> Sender<UiMessage> {
1305 self.sender.clone()
1306 }
1307
1308 pub fn send_message(&self, message: UiMessage) {
1309 self.sender.send(message).unwrap()
1310 }
1311
1312 fn make_topmost(&mut self, node: Handle<UiNode>) {
1320 let parent = self.node(node).parent();
1321 if parent.is_some() {
1322 let parent = &mut self.nodes[parent];
1323 parent.remove_child(node);
1324 parent.add_child(node, false);
1325 }
1326 }
1327
1328 fn bubble_message(&mut self, message: &mut UiMessage) {
1329 scope_profile!();
1330
1331 self.bubble_queue.clear();
1335 self.bubble_queue.push_back(message.destination());
1336 let mut parent = self.nodes[message.destination()].parent();
1337 while parent.is_some() && self.nodes.is_valid_handle(parent) {
1338 self.bubble_queue.push_back(parent);
1339 parent = self.nodes[parent].parent();
1340 }
1341
1342 while let Some(handle) = self.bubble_queue.pop_front() {
1343 let (ticket, mut node) = self.nodes.take_reserve(handle);
1344 node.handle_routed_message(self, message);
1345 self.nodes.put_back(ticket, node);
1346 }
1347 }
1348
1349 pub fn poll_message(&mut self) -> Option<UiMessage> {
1354 match self.receiver.try_recv() {
1355 Ok(mut message) => {
1356 if !self.nodes.is_valid_handle(message.destination()) {
1359 return None;
1360 }
1361
1362 if message.need_perform_layout() {
1363 self.update(self.screen_size, 0.0);
1364 }
1365
1366 for &handle in self.preview_set.iter() {
1367 if let Some(node_ref) = self.nodes.try_borrow(handle) {
1368 node_ref.preview_message(self, &mut message);
1369 }
1370 }
1371
1372 self.bubble_message(&mut message);
1373
1374 if let Some(msg) = message.data::<WidgetMessage>() {
1375 match msg {
1376 WidgetMessage::ZIndex(_) => {
1377 let parent = self.node(message.destination()).parent();
1380 if parent.is_some() {
1381 self.stack.clear();
1382 for child in self.nodes.borrow(parent).children() {
1383 self.stack.push(*child);
1384 }
1385
1386 let nodes = &mut self.nodes;
1387 self.stack.sort_by(|a, b| {
1388 let z_a = nodes.borrow(*a).z_index();
1389 let z_b = nodes.borrow(*b).z_index();
1390 z_a.cmp(&z_b)
1391 });
1392
1393 let parent = self.nodes.borrow_mut(parent);
1394 parent.clear_children();
1395 for child in self.stack.iter() {
1396 parent.add_child(*child, false);
1397 }
1398 }
1399 }
1400 WidgetMessage::TopMost => {
1401 if message.destination().is_some() {
1402 self.make_topmost(message.destination());
1403 }
1404 }
1405 WidgetMessage::Unlink => {
1406 if message.destination().is_some() {
1407 self.unlink_node(message.destination());
1408
1409 let node = &self.nodes[message.destination()];
1410 let new_position = node.screen_position;
1411 self.send_message(WidgetMessage::desired_position(
1412 message.destination(),
1413 MessageDirection::ToWidget,
1414 new_position,
1415 ));
1416 }
1417 }
1418 &WidgetMessage::LinkWith(parent) => {
1419 if message.destination().is_some() {
1420 self.link_nodes_internal(message.destination(), parent, false);
1421 }
1422 }
1423 &WidgetMessage::LinkWithReverse(parent) => {
1424 if message.destination().is_some() {
1425 self.link_nodes_internal(message.destination(), parent, true);
1426 }
1427 }
1428 WidgetMessage::Remove => {
1429 if message.destination().is_some() {
1430 self.remove_node(message.destination());
1431 }
1432 }
1433 WidgetMessage::Center => {
1434 if message.destination().is_some() {
1435 let node = self.node(message.destination());
1436 let size = node.actual_size();
1437 let parent = node.parent();
1438 let parent_size = if parent.is_some() {
1439 if parent == self.root_canvas {
1440 self.screen_size
1441 } else {
1442 self.node(parent).actual_size()
1443 }
1444 } else {
1445 self.screen_size
1446 };
1447
1448 self.send_message(WidgetMessage::desired_position(
1449 message.destination(),
1450 MessageDirection::ToWidget,
1451 (parent_size - size).scale(0.5),
1452 ));
1453 }
1454 }
1455 WidgetMessage::MouseDown { button, .. } => {
1456 if *button == MouseButton::Right {
1457 if let Some(picked) = self.nodes.try_borrow(self.picked_node) {
1458 let (context_menu, target) = if picked.context_menu().is_some()
1460 {
1461 (picked.context_menu(), self.picked_node)
1462 } else {
1463 let parent_handle = picked.find_by_criteria_up(self, |n| {
1464 n.context_menu().is_some()
1465 });
1466
1467 if let Some(parent) = self.nodes.try_borrow(parent_handle) {
1468 (parent.context_menu(), parent_handle)
1469 } else {
1470 (Handle::NONE, Handle::NONE)
1471 }
1472 };
1473
1474 if context_menu.is_some() {
1476 self.send_message(PopupMessage::placement(
1477 context_menu,
1478 MessageDirection::ToWidget,
1479 Placement::Cursor(target),
1480 ));
1481 self.send_message(PopupMessage::open(
1482 context_menu,
1483 MessageDirection::ToWidget,
1484 ));
1485 }
1486 }
1487 }
1488 }
1489 _ => {}
1490 }
1491 }
1492
1493 Some(message)
1494 }
1495 Err(e) => match e {
1496 TryRecvError::Empty => None,
1497 TryRecvError::Disconnected => unreachable!(),
1498 },
1499 }
1500 }
1501
1502 fn show_tooltip(&self, tooltip: Handle<UiNode>) {
1503 self.send_message(WidgetMessage::visibility(
1504 tooltip,
1505 MessageDirection::ToWidget,
1506 true,
1507 ));
1508 self.send_message(WidgetMessage::topmost(tooltip, MessageDirection::ToWidget));
1509 self.send_message(WidgetMessage::desired_position(
1510 tooltip,
1511 MessageDirection::ToWidget,
1512 self.cursor_position() + Vector2::new(0.0, 16.0),
1513 ));
1514 }
1515
1516 fn replace_or_update_tooltip(&mut self, tooltip: Handle<UiNode>, time: f32) {
1517 if let Some(entry) = self.active_tooltip.as_mut() {
1518 if entry.tooltip == tooltip {
1519 entry.time = time;
1521 } else {
1522 let old_tooltip = entry.tooltip;
1523
1524 entry.tooltip = tooltip;
1525 self.show_tooltip(tooltip);
1526
1527 self.send_message(WidgetMessage::visibility(
1529 old_tooltip,
1530 MessageDirection::ToWidget,
1531 false,
1532 ));
1533 }
1534 } else {
1535 self.show_tooltip(tooltip);
1536 self.active_tooltip = Some(TooltipEntry::new(tooltip, time));
1537 }
1538 }
1539
1540 fn update_tooltips(&mut self, dt: f32) {
1543 let sender = &self.sender;
1544 if let Some(entry) = self.active_tooltip.as_mut() {
1545 entry.decrease(dt);
1546 if !entry.should_display() {
1547 sender
1550 .send(WidgetMessage::visibility(
1551 entry.tooltip,
1552 MessageDirection::ToWidget,
1553 false,
1554 ))
1555 .unwrap();
1556
1557 self.active_tooltip = None;
1558 }
1559 }
1560
1561 let mut handle = self.picked_node;
1563 while let Some(node) = self.nodes.try_borrow(handle) {
1564 let parent = node.parent();
1567
1568 if node.tooltip().is_some() {
1569 let tooltip = node.tooltip();
1571 let tooltip_time = node.tooltip_time();
1572 self.replace_or_update_tooltip(tooltip, tooltip_time);
1573 break;
1574 } else if let Some(entry) = self.active_tooltip.as_mut() {
1575 if entry.tooltip == handle {
1576 entry.time = entry.max_time;
1579 break;
1580 }
1581 }
1582
1583 handle = parent;
1584 }
1585 }
1586
1587 pub fn captured_node(&self) -> Handle<UiNode> {
1588 self.captured_node
1589 }
1590
1591 pub fn process_os_event(&mut self, event: &OsEvent) -> bool {
1595 let mut event_processed = false;
1596
1597 match event {
1598 &OsEvent::MouseInput { button, state, .. } => {
1599 match button {
1600 MouseButton::Left => self.mouse_state.left = state,
1601 MouseButton::Right => self.mouse_state.right = state,
1602 MouseButton::Middle => self.mouse_state.middle = state,
1603 _ => {}
1604 }
1605
1606 match state {
1607 ButtonState::Pressed => {
1608 self.picked_node = self.hit_test(self.cursor_position);
1609
1610 if self.picked_node.is_some() {
1612 self.stack.clear();
1613 self.stack.push(self.picked_node);
1614 while let Some(handle) = self.stack.pop() {
1615 let node = &self.nodes[handle];
1616 if node.is_drag_allowed() {
1617 self.drag_context.drag_node = handle;
1618 self.stack.clear();
1619 break;
1620 } else if node.parent().is_some() {
1621 self.stack.push(node.parent());
1622 }
1623 }
1624 self.drag_context.click_pos = self.cursor_position;
1625 }
1626
1627 if self.keyboard_focus_node != self.picked_node {
1628 if self.keyboard_focus_node.is_some() {
1629 self.send_message(WidgetMessage::lost_focus(
1630 self.keyboard_focus_node,
1631 MessageDirection::FromWidget,
1632 ));
1633 }
1634
1635 self.keyboard_focus_node = self.picked_node;
1636
1637 if self.keyboard_focus_node.is_some() {
1638 self.send_message(WidgetMessage::got_focus(
1639 self.keyboard_focus_node,
1640 MessageDirection::FromWidget,
1641 ));
1642 }
1643 }
1644
1645 if self.picked_node.is_some() {
1646 self.send_message(WidgetMessage::mouse_down(
1647 self.picked_node,
1648 MessageDirection::FromWidget,
1649 self.cursor_position,
1650 button,
1651 ));
1652 event_processed = true;
1653 }
1654 }
1655 ButtonState::Released => {
1656 if self.picked_node.is_some() {
1657 if self.drag_context.is_dragging {
1658 self.drag_context.is_dragging = false;
1659 self.cursor_icon = CursorIcon::Default;
1660
1661 self.stack.clear();
1663 self.stack.push(self.picked_node);
1664 while let Some(handle) = self.stack.pop() {
1665 let node = &self.nodes[handle];
1666 if node.is_drop_allowed() {
1667 self.send_message(WidgetMessage::drop(
1668 handle,
1669 MessageDirection::FromWidget,
1670 self.drag_context.drag_node,
1671 ));
1672 self.stack.clear();
1673 break;
1674 } else if node.parent().is_some() {
1675 self.stack.push(node.parent());
1676 }
1677 }
1678 }
1679 self.drag_context.drag_node = Handle::NONE;
1680 if self.nodes.is_valid_handle(self.drag_context.drag_preview) {
1681 self.remove_node(self.drag_context.drag_preview);
1682 self.drag_context.drag_preview = Default::default();
1683 }
1684
1685 self.send_message(WidgetMessage::mouse_up(
1686 self.picked_node,
1687 MessageDirection::FromWidget,
1688 self.cursor_position,
1689 button,
1690 ));
1691 event_processed = true;
1692 }
1693 }
1694 }
1695 }
1696 OsEvent::CursorMoved { position } => {
1697 self.cursor_position = *position;
1698 self.picked_node = self.hit_test(self.cursor_position);
1699
1700 if !self.drag_context.is_dragging
1701 && self.mouse_state.left == ButtonState::Pressed
1702 && self.picked_node.is_some()
1703 && self.drag_context.drag_node.is_some()
1704 && (self.drag_context.click_pos - *position).norm() > 5.0
1705 {
1706 self.drag_context.drag_preview =
1707 self.copy_node_with_limit(self.drag_context.drag_node, Some(30));
1708 self.nodes[self.drag_context.drag_preview].set_opacity(Some(0.5));
1709
1710 self.drag_context.is_dragging = true;
1711
1712 self.send_message(WidgetMessage::drag_started(
1713 self.picked_node,
1714 MessageDirection::FromWidget,
1715 self.drag_context.drag_node,
1716 ));
1717
1718 self.cursor_icon = CursorIcon::Crosshair;
1719 }
1720
1721 if self.drag_context.is_dragging
1722 && self.nodes.is_valid_handle(self.drag_context.drag_preview)
1723 {
1724 self.send_message(WidgetMessage::desired_position(
1725 self.drag_context.drag_preview,
1726 MessageDirection::ToWidget,
1727 *position,
1728 ));
1729 }
1730
1731 if self.picked_node != self.prev_picked_node && self.prev_picked_node.is_some() {
1733 let prev_picked_node = self.nodes.borrow_mut(self.prev_picked_node);
1734 if prev_picked_node.is_mouse_directly_over {
1735 prev_picked_node.is_mouse_directly_over = false;
1736 self.send_message(WidgetMessage::mouse_leave(
1737 self.prev_picked_node,
1738 MessageDirection::FromWidget,
1739 ));
1740 }
1741 }
1742
1743 if self.picked_node.is_some() {
1744 let picked_node = self.nodes.borrow_mut(self.picked_node);
1745 if !picked_node.is_mouse_directly_over {
1746 picked_node.is_mouse_directly_over = true;
1747 self.send_message(WidgetMessage::mouse_enter(
1748 self.picked_node,
1749 MessageDirection::FromWidget,
1750 ));
1751 }
1752
1753 self.send_message(WidgetMessage::mouse_move(
1755 self.picked_node,
1756 MessageDirection::FromWidget,
1757 self.cursor_position,
1758 self.mouse_state,
1759 ));
1760
1761 if self.drag_context.is_dragging {
1762 self.send_message(WidgetMessage::drag_over(
1763 self.picked_node,
1764 MessageDirection::FromWidget,
1765 self.drag_context.drag_node,
1766 ));
1767 }
1768
1769 event_processed = true;
1770 }
1771 }
1772 OsEvent::MouseWheel(_, y) => {
1773 if self.picked_node.is_some() {
1774 self.send_message(WidgetMessage::mouse_wheel(
1775 self.picked_node,
1776 MessageDirection::FromWidget,
1777 self.cursor_position,
1778 *y,
1779 ));
1780
1781 event_processed = true;
1782 }
1783 }
1784 OsEvent::KeyboardInput { button, state } => {
1785 if self.keyboard_focus_node.is_some() {
1786 self.send_message(match state {
1787 ButtonState::Pressed => WidgetMessage::key_down(
1788 self.keyboard_focus_node,
1789 MessageDirection::FromWidget,
1790 *button,
1791 ),
1792 ButtonState::Released => WidgetMessage::key_up(
1793 self.keyboard_focus_node,
1794 MessageDirection::FromWidget,
1795 *button,
1796 ),
1797 });
1798
1799 event_processed = true;
1800 }
1801 }
1802 OsEvent::Character(unicode) => {
1803 if self.keyboard_focus_node.is_some() {
1804 self.send_message(WidgetMessage::text(
1805 self.keyboard_focus_node,
1806 MessageDirection::FromWidget,
1807 *unicode,
1808 ));
1809
1810 event_processed = true;
1811 }
1812 }
1813 &OsEvent::KeyboardModifiers(modifiers) => {
1814 self.keyboard_modifiers = modifiers;
1816 }
1817 }
1818
1819 self.prev_picked_node = self.picked_node;
1820
1821 for i in 0..self.nodes.get_capacity() {
1822 let handle = self.nodes.handle_from_index(i);
1823
1824 if let Some(node_ref) = self.nodes.try_borrow(handle) {
1825 if node_ref.handle_os_events {
1826 let (ticket, mut node) = self.nodes.take_reserve(handle);
1827
1828 node.handle_os_event(handle, self, event);
1829
1830 self.nodes.put_back(ticket, node);
1831 }
1832 }
1833 }
1834
1835 event_processed
1836 }
1837
1838 pub fn nodes(&self) -> &Pool<UiNode> {
1839 &self.nodes
1840 }
1841
1842 pub fn root(&self) -> Handle<UiNode> {
1843 self.root_canvas
1844 }
1845
1846 pub fn add_node(&mut self, mut node: UiNode) -> Handle<UiNode> {
1847 let children = node.children().to_vec();
1848 node.clear_children();
1849 let node_handle = self.nodes.spawn(node);
1850 if self.root_canvas.is_some() {
1851 self.link_nodes_internal(node_handle, self.root_canvas, false);
1852 }
1853 for child in children {
1854 self.link_nodes_internal(child, node_handle, false)
1855 }
1856 let node = self.nodes[node_handle].deref_mut();
1857 node.layout_events_sender = Some(self.layout_events_sender.clone());
1858 if node.preview_messages {
1859 self.preview_set.insert(node_handle);
1860 }
1861 node.handle = node_handle;
1862 node_handle
1863 }
1864
1865 pub fn push_picking_restriction(&mut self, restriction: RestrictionEntry) {
1866 if let Some(top) = self.top_picking_restriction() {
1867 assert_ne!(top.handle, restriction.handle);
1868 }
1869 self.picking_stack.push(restriction);
1870 }
1871
1872 pub fn remove_picking_restriction(&mut self, node: Handle<UiNode>) {
1873 if let Some(pos) = self.picking_stack.iter().position(|h| h.handle == node) {
1874 self.picking_stack.remove(pos);
1875 }
1876 }
1877
1878 pub fn picking_restriction_stack(&self) -> &[RestrictionEntry] {
1879 &self.picking_stack
1880 }
1881
1882 pub fn drop_picking_restrictions(&mut self) {
1884 self.picking_stack.clear();
1885 }
1886
1887 pub fn top_picking_restriction(&self) -> Option<RestrictionEntry> {
1888 self.picking_stack.last().cloned()
1889 }
1890
1891 fn remove_node(&mut self, node: Handle<UiNode>) {
1893 self.unlink_node_internal(node);
1894
1895 let mut tooltips = Vec::new();
1896 let sender = self.sender.clone();
1897 let mut stack = vec![node];
1898 while let Some(handle) = stack.pop() {
1899 if self.prev_picked_node == handle {
1900 self.prev_picked_node = Handle::NONE;
1901 }
1902 if self.picked_node == handle {
1903 self.picked_node = Handle::NONE;
1904 }
1905 if self.captured_node == handle {
1906 self.captured_node = Handle::NONE;
1907 }
1908 if self.keyboard_focus_node == handle {
1909 self.keyboard_focus_node = Handle::NONE;
1910 }
1911 self.remove_picking_restriction(handle);
1912
1913 let node_ref = self.nodes.borrow(handle);
1914 stack.extend_from_slice(node_ref.children());
1915
1916 if node_ref.tooltip().is_some() {
1919 tooltips.push(node_ref.tooltip());
1920 }
1921
1922 node_ref.on_remove(&sender);
1925
1926 self.nodes.free(handle);
1927 }
1928
1929 for tooltip in tooltips {
1930 self.remove_node(tooltip);
1931 }
1932
1933 self.preview_set.remove(&node);
1934 }
1935
1936 #[inline]
1938 fn link_nodes_internal(
1939 &mut self,
1940 child_handle: Handle<UiNode>,
1941 parent_handle: Handle<UiNode>,
1942 in_front: bool,
1943 ) {
1944 assert_ne!(child_handle, parent_handle);
1945 self.unlink_node_internal(child_handle);
1946 self.nodes[child_handle].set_parent(parent_handle);
1947 self.nodes[parent_handle].add_child(child_handle, in_front);
1948 }
1949
1950 #[inline]
1952 fn unlink_node_internal(&mut self, node_handle: Handle<UiNode>) {
1953 let node = self.nodes.borrow_mut(node_handle);
1955 let parent_handle = node.parent();
1956 if parent_handle.is_some() {
1957 node.set_parent(Handle::NONE);
1958
1959 self.nodes[parent_handle].remove_child(node_handle);
1961 }
1962 }
1963
1964 #[inline]
1969 fn unlink_node(&mut self, node_handle: Handle<UiNode>) {
1970 self.unlink_node_internal(node_handle);
1971 self.link_nodes_internal(node_handle, self.root_canvas, false);
1972 }
1973
1974 #[inline]
1975 pub fn node(&self, node_handle: Handle<UiNode>) -> &UiNode {
1976 self.nodes.borrow(node_handle)
1977 }
1978
1979 #[inline]
1980 pub fn try_get_node(&self, node_handle: Handle<UiNode>) -> Option<&UiNode> {
1981 self.nodes.try_borrow(node_handle)
1982 }
1983
1984 pub fn copy_node(&mut self, node: Handle<UiNode>) -> Handle<UiNode> {
1985 let mut map = NodeHandleMapping::default();
1986
1987 let root = self.copy_node_recursive(node, &mut map);
1988
1989 for &node_handle in map.hash_map.values() {
1990 self.nodes[node_handle].resolve(&map);
1991 }
1992
1993 root
1994 }
1995
1996 fn copy_node_recursive(
1997 &mut self,
1998 node_handle: Handle<UiNode>,
1999 map: &mut NodeHandleMapping,
2000 ) -> Handle<UiNode> {
2001 let node = self.nodes.borrow(node_handle);
2002 let mut cloned = UiNode(node.clone_boxed());
2003
2004 let mut cloned_children = Vec::new();
2005 for child in node.children().to_vec() {
2006 cloned_children.push(self.copy_node_recursive(child, map));
2007 }
2008
2009 cloned.set_children(cloned_children);
2010 let copy_handle = self.add_node(cloned);
2011 map.add_mapping(node_handle, copy_handle);
2012 copy_handle
2013 }
2014
2015 pub fn copy_node_with_limit(
2016 &mut self,
2017 node: Handle<UiNode>,
2018 limit: Option<usize>,
2019 ) -> Handle<UiNode> {
2020 let mut map = NodeHandleMapping::default();
2021 let mut counter = 0;
2022
2023 let root = self.copy_node_recursive_with_limit(node, &mut map, limit, &mut counter);
2024
2025 for &node_handle in map.hash_map.values() {
2026 self.nodes[node_handle].resolve(&map);
2027 }
2028
2029 root
2030 }
2031
2032 fn copy_node_recursive_with_limit(
2033 &mut self,
2034 node_handle: Handle<UiNode>,
2035 map: &mut NodeHandleMapping,
2036 limit: Option<usize>,
2037 counter: &mut usize,
2038 ) -> Handle<UiNode> {
2039 if let Some(limit) = limit {
2040 if *counter >= limit {
2041 return Default::default();
2042 }
2043 }
2044
2045 let node = self.nodes.borrow(node_handle);
2046 let mut cloned = UiNode(node.clone_boxed());
2047
2048 let mut cloned_children = Vec::new();
2049 for child in node.children().to_vec() {
2050 let cloned_child = self.copy_node_recursive_with_limit(child, map, limit, counter);
2051 if cloned_child.is_some() {
2052 cloned_children.push(cloned_child);
2053 } else {
2054 break;
2055 }
2056 }
2057
2058 cloned.set_children(cloned_children);
2059 let copy_handle = self.add_node(cloned);
2060 map.add_mapping(node_handle, copy_handle);
2061
2062 *counter += 1;
2063
2064 copy_handle
2065 }
2066}
2067
2068#[cfg(test)]
2069mod test {
2070 use crate::{
2071 border::BorderBuilder,
2072 core::algebra::Vector2,
2073 message::MessageDirection,
2074 widget::{WidgetBuilder, WidgetMessage},
2075 UserInterface,
2076 };
2077
2078 #[test]
2079 fn center() {
2080 let screen_size = Vector2::new(1000.0, 1000.0);
2081 let widget_size = Vector2::new(100.0, 100.0);
2082 let mut ui = UserInterface::new(screen_size);
2083 let widget = BorderBuilder::new(
2084 WidgetBuilder::new()
2085 .with_width(widget_size.x)
2086 .with_height(widget_size.y),
2087 )
2088 .build(&mut ui.build_ctx());
2089 ui.update(screen_size, 0.0); ui.send_message(WidgetMessage::center(widget, MessageDirection::ToWidget));
2091 while ui.poll_message().is_some() {}
2092 ui.update(screen_size, 0.0);
2093 let expected_position = (screen_size - widget_size).scale(0.5);
2094 let actual_position = ui.node(widget).actual_local_position();
2095 assert_eq!(actual_position, expected_position);
2096 }
2097}