1#![forbid(unsafe_code)]
212#![allow(irrefutable_let_patterns)]
213#![allow(clippy::float_cmp)]
214#![allow(clippy::upper_case_acronyms)]
215#![allow(clippy::from_over_into)]
216#![allow(clippy::new_without_default)]
217#![allow(clippy::too_many_arguments)]
218#![allow(clippy::type_complexity)]
219#![allow(clippy::doc_lazy_continuation)]
220#![allow(clippy::mutable_key_type)]
221#![allow(mismatched_lifetime_syntaxes)]
222
223pub use bbcode::*;
224pub use copypasta;
225pub use fyrox_core as core;
226use message::TouchPhase;
227
228pub mod absm;
229mod alignment;
230pub mod animation;
231mod bbcode;
232pub mod bit;
233pub mod border;
234pub mod brush;
235mod build;
236pub mod button;
237pub mod canvas;
238pub mod check_box;
239pub mod color;
240mod control;
241pub mod curve;
242pub mod decorator;
243pub mod dock;
244pub mod draw;
245pub mod dropdown_list;
246pub mod dropdown_menu;
247pub mod expander;
248pub mod file_browser;
249pub mod font;
250pub mod formatted_text;
251pub mod grid;
252pub mod image;
253pub mod inspector;
254pub mod key;
255pub mod list_view;
256pub mod loader;
257pub mod log;
258pub mod matrix;
259pub mod menu;
260pub mod message;
261pub mod messagebox;
262pub mod navigation;
263pub mod nine_patch;
264mod node;
265pub mod numeric;
266pub mod path;
267pub mod popup;
268pub mod progress_bar;
269pub mod range;
270pub mod rect;
271pub mod resources;
272pub mod screen;
273pub mod scroll_bar;
274pub mod scroll_panel;
275pub mod scroll_viewer;
276pub mod searchbar;
277pub mod selector;
278pub mod stack_panel;
279pub mod style;
280pub mod tab_control;
281pub mod test;
282pub mod text;
283pub mod text_box;
284mod thickness;
285pub mod thumb;
286pub mod toggle;
287pub mod tree;
288pub mod utils;
289pub mod uuid;
290pub mod vec;
291pub mod vector_image;
292pub mod widget;
293pub mod window;
294pub mod wrap_panel;
295
296use crate::{
297 brush::Brush,
298 canvas::Canvas,
299 constructor::WidgetConstructorContainer,
300 container::WidgetContainer,
301 core::{
302 algebra::{Matrix3, Vector2},
303 color::Color,
304 futures::future::join_all,
305 log::Log,
306 math::Rect,
307 parking_lot::Mutex,
308 pool::{Handle, ObjectOrVariant, Pool, Ticket},
309 reflect::prelude::*,
310 uuid::{uuid, Uuid},
311 uuid_provider,
312 visitor::prelude::*,
313 SafeLock, TypeUuidProvider,
314 },
315 draw::{CommandTexture, Draw, DrawingContext},
316 font::{FontResource, BUILT_IN_FONT},
317 message::{
318 ButtonState, CursorIcon, KeyboardModifiers, MessageDirection, MouseButton, OsEvent,
319 UiMessage,
320 },
321 message::{DeliveryMode, MessageData, RoutingStrategy},
322 popup::{Placement, PopupMessage},
323 style::{
324 resource::{StyleResource, StyleResourceExt},
325 Style, DEFAULT_STYLE,
326 },
327 widget::{Widget, WidgetBuilder, WidgetMaterial, WidgetMessage},
328};
329use copypasta::ClipboardContext;
330use fxhash::{FxHashMap, FxHashSet};
331pub use fyrox_animation as generic_animation;
332use fyrox_graph::{NodeHandleMap, NodeMapping, PrefabData, SceneGraph, SceneGraphNode};
333use fyrox_resource::{
334 io::{FsResourceIo, ResourceIo},
335 manager::ResourceManager,
336 untyped::{ResourceKind, UntypedResource},
337 Resource, ResourceData,
338};
339use fyrox_texture::TextureResource;
340use serde::{Deserialize, Serialize};
341use std::{
342 any::TypeId,
343 cell::{Ref, RefCell, RefMut},
344 collections::{btree_set::BTreeSet, hash_map::Entry, VecDeque},
345 error::Error,
346 fmt::{Debug, Formatter, Write},
347 ops::{Deref, DerefMut, Index, IndexMut},
348 path::Path,
349 sync::{
350 mpsc::{self, Receiver, Sender},
351 Arc,
352 },
353};
354use strum_macros::{AsRefStr, EnumString, VariantNames};
355
356pub use alignment::*;
357pub use build::*;
358pub use control::*;
359use fyrox_core::dyntype::{DynTypeConstructorContainer, DynTypeContainer};
360use fyrox_core::pool::PoolError;
361pub use fyrox_texture as texture;
362pub use node::*;
363pub use thickness::*;
364
365#[derive(Default, Clone, Reflect, Debug)]
366pub(crate) struct RcUiNodeHandleInner {
367 handle: Handle<UiNode>,
368 #[reflect(hidden)]
369 sender: Option<Sender<UiMessage>>,
370}
371
372impl Visit for RcUiNodeHandleInner {
373 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
374 self.handle.visit(name, visitor)?;
375
376 if visitor.is_reading() {
377 self.sender = Some(
378 visitor
379 .blackboard
380 .get::<Sender<UiMessage>>()
381 .expect("Ui message sender must be provided for correct deserialization!")
382 .clone(),
383 );
384 }
385
386 Ok(())
387 }
388}
389
390impl Drop for RcUiNodeHandleInner {
391 fn drop(&mut self) {
392 if let Some(sender) = self.sender.as_ref() {
393 let _ = sender.send(UiMessage::for_widget(self.handle, WidgetMessage::Remove));
394 } else {
395 Log::warn(format!(
396 "There's no message sender for shared handle {}. The object \
397 won't be destroyed.",
398 self.handle
399 ))
400 }
401 }
402}
403
404#[derive(Clone, Default, Visit, Reflect, TypeUuidProvider)]
408#[type_uuid(id = "9111a53b-05dc-4c75-aab1-71d5b1c93311")]
409pub struct RcUiNodeHandle(Arc<Mutex<RcUiNodeHandleInner>>);
410
411impl Debug for RcUiNodeHandle {
412 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
413 let handle = self.0.safe_lock().handle;
414
415 writeln!(
416 f,
417 "RcUiNodeHandle - {}:{} with {} uses",
418 handle.index(),
419 handle.generation(),
420 Arc::strong_count(&self.0)
421 )
422 }
423}
424
425impl PartialEq for RcUiNodeHandle {
426 fn eq(&self, other: &Self) -> bool {
427 let a = self.0.safe_lock().handle;
428 let b = other.0.safe_lock().handle;
429 a == b
430 }
431}
432
433impl RcUiNodeHandle {
434 #[inline]
436 pub fn new(handle: Handle<impl ObjectOrVariant<UiNode>>, sender: Sender<UiMessage>) -> Self {
437 Self(Arc::new(Mutex::new(RcUiNodeHandleInner {
438 handle: handle.to_base(),
439 sender: Some(sender),
440 })))
441 }
442
443 #[inline]
445 pub fn handle(&self) -> Handle<UiNode> {
446 self.0.safe_lock().handle
447 }
448}
449
450#[derive(
452 Copy,
453 Clone,
454 Debug,
455 PartialEq,
456 Eq,
457 Visit,
458 Reflect,
459 Default,
460 Serialize,
461 Deserialize,
462 AsRefStr,
463 EnumString,
464 VariantNames,
465)]
466pub enum Orientation {
467 #[default]
469 Vertical,
470 Horizontal,
472}
473
474uuid_provider!(Orientation = "1c6ad1b0-3f4c-48be-87dd-6929cb3577bf");
475
476#[derive(Default, Clone)]
477pub struct NodeStatistics(pub FxHashMap<&'static str, isize>);
478
479impl NodeStatistics {
480 pub fn new(ui: &UserInterface) -> NodeStatistics {
481 let mut statistics = Self::default();
482 for node in ui.nodes.iter() {
483 statistics
484 .0
485 .entry(BaseControl::type_name(&*node.0))
486 .and_modify(|counter| *counter += 1)
487 .or_insert(1);
488 }
489 statistics
490 }
491
492 fn unite_type_names(&self, prev_stats: &NodeStatistics) -> BTreeSet<&'static str> {
493 let mut union = BTreeSet::default();
494 for stats in [self, prev_stats] {
495 for &type_name in stats.0.keys() {
496 union.insert(type_name);
497 }
498 }
499 union
500 }
501
502 fn count_of(&self, type_name: &str) -> isize {
503 self.0.get(type_name).cloned().unwrap_or_default()
504 }
505
506 pub fn print_diff(&self, prev_stats: &NodeStatistics, show_unchanged: bool) {
507 println!("**** Diff UI Node Statistics ****");
508 for type_name in self.unite_type_names(prev_stats) {
509 let count = self.count_of(type_name);
510 let prev_count = prev_stats.count_of(type_name);
511 let delta = count - prev_count;
512 if delta != 0 || show_unchanged {
513 println!("{type_name}: \x1b[93m{delta}\x1b[0m");
514 }
515 }
516 }
517
518 pub fn print_changed(&self, prev_stats: &NodeStatistics) {
519 println!("**** Changed UI Node Statistics ****");
520 for type_name in self.unite_type_names(prev_stats) {
521 let count = self.count_of(type_name);
522 let prev_count = prev_stats.count_of(type_name);
523 if count - prev_count != 0 {
524 println!("{type_name}: \x1b[93m{count}\x1b[0m");
525 }
526 }
527 }
528}
529
530#[derive(Visit, Reflect, Debug, Clone)]
531pub struct DragContext {
532 pub is_dragging: bool,
533 pub drag_node: Handle<UiNode>,
534 pub click_pos: Vector2<f32>,
535 pub drag_preview: Handle<UiNode>,
536}
537
538impl Default for DragContext {
539 fn default() -> Self {
540 Self {
541 is_dragging: false,
542 drag_node: Default::default(),
543 click_pos: Vector2::new(0.0, 0.0),
544 drag_preview: Default::default(),
545 }
546 }
547}
548
549#[derive(Copy, Clone, Debug, Eq, PartialEq, Visit, Reflect)]
550pub struct MouseState {
551 pub left: ButtonState,
552 pub right: ButtonState,
553 pub middle: ButtonState,
554 }
556
557impl Default for MouseState {
558 fn default() -> Self {
559 Self {
560 left: ButtonState::Released,
561 right: ButtonState::Released,
562 middle: ButtonState::Released,
563 }
564 }
565}
566
567#[derive(Copy, Clone, Visit, Reflect, Debug, Default)]
568pub struct RestrictionEntry {
569 pub handle: Handle<UiNode>,
571
572 pub stop: bool,
580}
581
582#[derive(Clone, Debug)]
583pub struct TooltipEntry {
584 pub tooltip: RcUiNodeHandle,
585 pub appear_timer: f32,
586 pub shown: bool,
587 pub disappear_timer: f32,
589 pub max_time: f32,
594}
595
596impl TooltipEntry {
597 fn new(tooltip: RcUiNodeHandle, appear_timeout: f32, disappear_timeout: f32) -> TooltipEntry {
598 Self {
599 tooltip,
600 appear_timer: appear_timeout,
601 shown: false,
602 disappear_timer: disappear_timeout,
603 max_time: disappear_timeout,
604 }
605 }
606}
607
608#[derive(Debug)]
609pub enum LayoutEvent {
610 MeasurementInvalidated(Handle<UiNode>),
611 ArrangementInvalidated(Handle<UiNode>),
612 VisualInvalidated(Handle<UiNode>),
613 VisibilityChanged(Handle<UiNode>),
614 ZIndexChanged(Handle<UiNode>),
615 TransformChanged(Handle<UiNode>),
616}
617
618#[derive(Clone, Debug, Visit, Reflect, Default)]
619struct DoubleClickEntry {
620 timer: f32,
621 click_count: u32,
622}
623
624struct Clipboard(Option<RefCell<ClipboardContext>>);
625
626impl Debug for Clipboard {
627 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
628 write!(f, "Clipboard")
629 }
630}
631
632#[derive(Default, Debug, Clone)]
633struct WidgetMethodsRegistry {
634 preview_message: FxHashSet<Handle<UiNode>>,
635 on_update: FxHashSet<Handle<UiNode>>,
636 handle_os_event: FxHashSet<Handle<UiNode>>,
637}
638
639impl WidgetMethodsRegistry {
640 fn register<T: Control + ?Sized>(&mut self, node: &T) {
641 let node_handle = node.handle();
642
643 if node.preview_messages && !self.preview_message.insert(node_handle) {
644 Log::warn(format!(
645 "Widget {node_handle} `preview_message` method is already registered!"
646 ));
647 }
648 if node.handle_os_events && !self.handle_os_event.insert(node_handle) {
649 Log::warn(format!(
650 "Widget {node_handle} `handle_os_event` method is already registered!"
651 ));
652 }
653 if node.need_update && !self.on_update.insert(node_handle) {
654 Log::warn(format!(
655 "Widget {node_handle} `on_update` method is already registered!"
656 ));
657 }
658 }
659
660 fn unregister<T: Control + ?Sized>(&mut self, node: &T) {
661 let node_handle = node.handle();
662
663 self.preview_message.remove(&node_handle);
664 self.on_update.remove(&node_handle);
665 self.handle_os_event.remove(&node_handle);
666 }
667}
668
669#[derive(Clone, PartialEq, Eq, Default)]
671pub struct UiUpdateSwitches {
672 pub node_overrides: Option<FxHashSet<Handle<UiNode>>>,
674}
675
676pub type WidgetPool = Pool<UiNode, WidgetContainer>;
677
678#[derive(Default, Debug, Clone, Reflect, Visit)]
679pub enum RenderMode {
680 #[default]
682 EveryFrame,
683 OnChanges,
687}
688
689#[derive(Reflect)]
690pub struct UserInterface {
691 screen_size: Vector2<f32>,
692 nodes: WidgetPool,
693 #[reflect(hidden)]
694 pub drawing_context: DrawingContext,
695 visual_debug: bool,
696 root_canvas: Handle<UiNode>,
697 picked_node: Handle<UiNode>,
698 prev_picked_node: Handle<UiNode>,
699 captured_node: Handle<UiNode>,
700 keyboard_focus_node: Handle<UiNode>,
701 cursor_position: Vector2<f32>,
702 pub style: StyleResource,
703 #[reflect(hidden)]
704 receiver: Receiver<UiMessage>,
705 #[reflect(hidden)]
706 sender: Sender<UiMessage>,
707 stack: Vec<Handle<UiNode>>,
708 picking_stack: Vec<RestrictionEntry>,
709 #[reflect(hidden)]
710 bubble_queue: VecDeque<Handle<UiNode>>,
711 drag_context: DragContext,
712 mouse_state: MouseState,
713 keyboard_modifiers: KeyboardModifiers,
714 cursor_icon: CursorIcon,
715 #[reflect(hidden)]
716 active_tooltip: Option<TooltipEntry>,
717 #[reflect(hidden)]
718 methods_registry: WidgetMethodsRegistry,
719 #[reflect(hidden)]
720 clipboard: Clipboard,
721 #[reflect(hidden)]
722 layout_events_receiver: Receiver<LayoutEvent>,
723 #[reflect(hidden)]
724 layout_events_sender: Sender<LayoutEvent>,
725 #[reflect(hidden)]
726 z_index_update_set: FxHashSet<Handle<UiNode>>,
727 #[reflect(hidden)]
728 pub default_font: FontResource,
729 #[reflect(hidden)]
730 double_click_entries: FxHashMap<MouseButton, DoubleClickEntry>,
731 pub double_click_time_slice: f32,
732 pub tooltip_appear_delay: f32,
733 pub standard_material: WidgetMaterial,
734 pub render_target: Option<TextureResource>,
737 pub render_mode: RenderMode,
739 pub need_render: bool,
742 pub user_data: DynTypeContainer,
743}
744
745impl Debug for UserInterface {
746 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
747 f.debug_struct("UserInterface")
748 .field("screen_size", &self.screen_size)
749 .field("drawing_context", &self.drawing_context)
750 .field("visual_debug", &self.visual_debug)
751 .field("root_canvas", &self.root_canvas)
752 .field("picked_node", &self.picked_node)
753 .field("prev_picked_node", &self.prev_picked_node)
754 .field("captured_node", &self.captured_node)
755 .field("keyboard_focus_node", &self.keyboard_focus_node)
756 .field("cursor_position", &self.cursor_position)
757 .field("style", &self.style)
758 .field("receiver", &self.receiver)
759 .field("sender", &self.sender)
760 .field("stack", &self.stack)
761 .field("picking_stack", &self.picking_stack)
762 .field("bubble_queue", &self.bubble_queue)
763 .field("drag_context", &self.drag_context)
764 .field("mouse_state", &self.mouse_state)
765 .field("keyboard_modifiers", &self.keyboard_modifiers)
766 .field("cursor_icon", &self.cursor_icon)
767 .field("active_tooltip", &self.active_tooltip)
768 .field("methods_registry", &self.methods_registry)
769 .field("clipboard", &self.clipboard)
770 .field("layout_events_receiver", &self.layout_events_receiver)
771 .field("layout_events_sender", &self.layout_events_sender)
772 .field("z_index_update_set", &self.z_index_update_set)
773 .field("default_font", &self.default_font)
774 .field("double_click_entries", &self.double_click_entries)
775 .field("double_click_time_slice", &self.double_click_time_slice)
776 .field("tooltip_appear_delay", &self.tooltip_appear_delay)
777 .field("standard_material", &self.standard_material)
778 .field("render_target", &self.render_target)
779 .field("render_mode", &self.render_mode)
780 .field("need_render", &self.need_render)
781 .field("user_data", &self.user_data)
782 .finish()?;
783 f.write_char('\n')?;
784 f.write_str(&self.summary())
785 }
786}
787
788impl Visit for UserInterface {
789 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
790 let mut region = visitor.enter_region(name)?;
791
792 if region.is_reading() {
793 self.nodes.clear();
794 self.root_canvas = Handle::NONE;
795 self.methods_registry = Default::default();
796 }
797
798 self.screen_size.visit("ScreenSize", &mut region)?;
799 self.nodes.visit("Nodes", &mut region)?;
800 self.visual_debug.visit("VisualDebug", &mut region)?;
801 self.root_canvas.visit("RootCanvas", &mut region)?;
802 self.picked_node.visit("PickedNode", &mut region)?;
803 self.prev_picked_node.visit("PrevPickedNode", &mut region)?;
804 self.captured_node.visit("CapturedNode", &mut region)?;
805 self.keyboard_focus_node
806 .visit("KeyboardFocusNode", &mut region)?;
807 self.cursor_position.visit("CursorPosition", &mut region)?;
808 self.picking_stack.visit("PickingStack", &mut region)?;
809 self.drag_context.visit("DragContext", &mut region)?;
810 self.mouse_state.visit("MouseState", &mut region)?;
811 self.keyboard_modifiers
812 .visit("KeyboardModifiers", &mut region)?;
813 self.cursor_icon.visit("CursorIcon", &mut region)?;
814 self.double_click_time_slice
815 .visit("DoubleClickTimeSlice", &mut region)?;
816 self.tooltip_appear_delay
817 .visit("TooltipAppearDelay", &mut region)?;
818 self.standard_material
819 .visit("StandardMaterial", &mut region)?;
820 self.render_mode.visit("RenderMode", &mut region)?;
821 Log::verify(self.user_data.visit("UserData", &mut region));
822
823 if region.is_reading() {
824 for node in self.nodes.iter() {
825 self.methods_registry.register(node.deref());
826 }
827 }
828
829 Ok(())
830 }
831}
832
833impl Clone for UserInterface {
834 fn clone(&self) -> Self {
835 let (sender, receiver) = mpsc::channel();
836 let (layout_events_sender, layout_events_receiver) = mpsc::channel();
837 let mut nodes = Pool::new();
838 for (handle, node) in self.nodes.pair_iter() {
839 let mut clone = node.clone_boxed();
840 clone.layout_events_sender = Some(layout_events_sender.clone());
841 nodes.spawn_at_handle(handle, UiNode(clone)).unwrap();
842 }
843
844 Self {
845 screen_size: self.screen_size,
846 nodes,
847 drawing_context: self.drawing_context.clone(),
848 visual_debug: self.visual_debug,
849 root_canvas: self.root_canvas,
850 picked_node: self.picked_node,
851 prev_picked_node: self.prev_picked_node,
852 captured_node: self.captured_node,
853 keyboard_focus_node: self.keyboard_focus_node,
854 cursor_position: self.cursor_position,
855 style: StyleResource::new_ok(
856 Uuid::new_v4(),
857 ResourceKind::Embedded,
858 Style::dark_style(),
859 ),
860 receiver,
861 sender,
862 stack: self.stack.clone(),
863 picking_stack: self.picking_stack.clone(),
864 bubble_queue: self.bubble_queue.clone(),
865 drag_context: self.drag_context.clone(),
866 mouse_state: self.mouse_state,
867 keyboard_modifiers: self.keyboard_modifiers,
868 cursor_icon: self.cursor_icon,
869 active_tooltip: self.active_tooltip.clone(),
870 methods_registry: self.methods_registry.clone(),
871 clipboard: Clipboard(ClipboardContext::new().ok().map(RefCell::new)),
872 layout_events_receiver,
873 layout_events_sender,
874 z_index_update_set: self.z_index_update_set.clone(),
875 default_font: self.default_font.clone(),
876 double_click_entries: self.double_click_entries.clone(),
877 double_click_time_slice: self.double_click_time_slice,
878 tooltip_appear_delay: self.tooltip_appear_delay,
879 standard_material: Default::default(),
880 render_target: None,
881 render_mode: Default::default(),
882 need_render: self.need_render,
883 user_data: self.user_data.clone(),
884 }
885 }
886}
887
888impl Default for UserInterface {
889 fn default() -> Self {
890 Self::new(Vector2::new(100.0, 100.0))
891 }
892}
893
894#[inline(always)]
895fn invalidate_recursive_up(
896 nodes: &Pool<UiNode, WidgetContainer>,
897 node: Handle<UiNode>,
898 callback: fn(&UiNode),
899) {
900 if let Ok(node_ref) = nodes.try_borrow(node) {
901 callback(node_ref);
902 if node_ref.parent().is_some() {
903 invalidate_recursive_up(nodes, node_ref.parent(), callback);
904 }
905 }
906}
907
908#[derive(Default)]
909pub struct UiContainer {
910 pool: Pool<UserInterface>,
911}
912
913impl UiContainer {
914 pub fn new() -> Self {
916 Self::default()
917 }
918
919 pub fn new_with_ui(ui: UserInterface) -> Self {
921 let mut pool = Pool::new();
922 let _ = pool.spawn(ui);
923 Self { pool }
924 }
925
926 pub fn first(&self) -> &UserInterface {
929 self.pool
930 .first_ref()
931 .expect("The container must have at least one user interface.")
932 }
933
934 pub fn first_mut(&mut self) -> &mut UserInterface {
937 self.pool
938 .first_mut()
939 .expect("The container must have at least one user interface.")
940 }
941
942 pub fn is_valid_handle(&self, handle: Handle<UserInterface>) -> bool {
944 self.pool.is_valid_handle(handle)
945 }
946
947 pub fn pair_iter(&self) -> impl Iterator<Item = (Handle<UserInterface>, &UserInterface)> {
949 self.pool.pair_iter()
950 }
951
952 pub fn pair_iter_mut(
954 &mut self,
955 ) -> impl Iterator<Item = (Handle<UserInterface>, &mut UserInterface)> {
956 self.pool.pair_iter_mut()
957 }
958
959 pub fn try_get(&self, handle: Handle<UserInterface>) -> Result<&UserInterface, PoolError> {
961 self.pool.try_borrow(handle)
962 }
963
964 pub fn try_get_mut(
966 &mut self,
967 handle: Handle<UserInterface>,
968 ) -> Result<&mut UserInterface, PoolError> {
969 self.pool.try_borrow_mut(handle)
970 }
971
972 #[inline]
974 pub fn iter(&self) -> impl Iterator<Item = &UserInterface> {
975 self.pool.iter()
976 }
977
978 #[inline]
980 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut UserInterface> {
981 self.pool.iter_mut()
982 }
983
984 #[inline]
986 pub fn add(&mut self, scene: UserInterface) -> Handle<UserInterface> {
987 self.pool.spawn(scene)
988 }
989
990 #[inline]
992 pub fn clear(&mut self) {
993 self.pool.clear()
994 }
995
996 #[inline]
999 pub fn remove(&mut self, handle: Handle<UserInterface>) {
1000 self.pool.free(handle);
1001 }
1002
1003 pub fn take_reserve(
1007 &mut self,
1008 handle: Handle<UserInterface>,
1009 ) -> (Ticket<UserInterface>, UserInterface) {
1010 self.pool.take_reserve(handle)
1011 }
1012
1013 pub fn put_back(
1015 &mut self,
1016 ticket: Ticket<UserInterface>,
1017 scene: UserInterface,
1018 ) -> Handle<UserInterface> {
1019 self.pool.put_back(ticket, scene)
1020 }
1021
1022 pub fn forget_ticket(&mut self, ticket: Ticket<UserInterface>) {
1024 self.pool.forget_ticket(ticket)
1025 }
1026}
1027
1028impl<T: ObjectOrVariant<UiNode>> Index<Handle<T>> for UserInterface {
1029 type Output = T;
1030
1031 #[inline]
1032 fn index(&self, index: Handle<T>) -> &Self::Output {
1033 self.try_get(index).unwrap()
1034 }
1035}
1036
1037impl<T: ObjectOrVariant<UiNode>> IndexMut<Handle<T>> for UserInterface {
1038 #[inline]
1039 fn index_mut(&mut self, index: Handle<T>) -> &mut Self::Output {
1040 self.try_get_mut(index).unwrap()
1041 }
1042}
1043
1044impl Index<Handle<UserInterface>> for UiContainer {
1045 type Output = UserInterface;
1046
1047 #[inline]
1048 fn index(&self, index: Handle<UserInterface>) -> &Self::Output {
1049 &self.pool[index]
1050 }
1051}
1052
1053impl IndexMut<Handle<UserInterface>> for UiContainer {
1054 #[inline]
1055 fn index_mut(&mut self, index: Handle<UserInterface>) -> &mut Self::Output {
1056 &mut self.pool[index]
1057 }
1058}
1059
1060fn is_on_screen(node: &UiNode, nodes: &Pool<UiNode, WidgetContainer>) -> bool {
1061 let bounds = node.clip_bounds();
1066 let mut parent = node.parent();
1067 while parent.is_some() {
1068 let parent_node = nodes.borrow(parent);
1069 if !parent_node.clip_bounds().intersects(bounds) {
1070 return false;
1071 }
1072 parent = parent_node.parent();
1073 }
1074 true
1075}
1076
1077fn draw_node(
1078 nodes: &Pool<UiNode, WidgetContainer>,
1079 node_handle: Handle<UiNode>,
1080 drawing_context: &mut DrawingContext,
1081) {
1082 let node = &nodes[node_handle];
1083 if node.visual_valid.get() {
1084 return;
1085 }
1086
1087 let pushed = if !is_node_enabled(nodes, node_handle) {
1088 drawing_context.push_opacity(0.4);
1089 true
1090 } else if let Some(opacity) = node.opacity() {
1091 drawing_context.push_opacity(opacity);
1092 true
1093 } else {
1094 false
1095 };
1096
1097 drawing_context.transform_stack.push(node.visual_transform);
1098
1099 {
1101 node.draw(drawing_context);
1102 node.render_data_set.borrow_mut().draw_result = drawing_context.take_render_data();
1103 }
1104
1105 for &child_node in node.children().iter() {
1107 draw_node(nodes, child_node, drawing_context);
1108 }
1109
1110 {
1112 node.post_draw(drawing_context);
1113 node.render_data_set.borrow_mut().post_draw_result = drawing_context.take_render_data();
1114 }
1115
1116 drawing_context.transform_stack.pop();
1117
1118 if pushed {
1119 drawing_context.pop_opacity();
1120 }
1121
1122 node.visual_valid.set(true);
1123}
1124
1125fn is_node_enabled(nodes: &Pool<UiNode, WidgetContainer>, handle: Handle<UiNode>) -> bool {
1126 let root_node = &nodes[handle];
1127 let mut enabled = root_node.enabled();
1128 let mut parent = root_node.parent();
1129 while parent.is_some() {
1130 let node = &nodes[parent];
1131 if !node.enabled() {
1132 enabled = false;
1133 break;
1134 }
1135 parent = node.parent();
1136 }
1137 enabled
1138}
1139
1140#[derive(Debug)]
1141pub struct SubGraph {
1142 pub root: (Ticket<UiNode>, UiNode),
1143
1144 pub descendants: Vec<(Ticket<UiNode>, UiNode)>,
1145
1146 pub parent: Handle<UiNode>,
1147}
1148
1149fn remap_handles(old_new_mapping: &NodeHandleMap<UiNode>, ui: &mut UserInterface) {
1150 for (_, &new_node_handle) in old_new_mapping.inner().iter() {
1152 old_new_mapping.remap_handles(
1153 &mut ui.nodes[new_node_handle],
1154 &[TypeId::of::<UntypedResource>()],
1155 );
1156 }
1157}
1158
1159struct VisualTransformUpdateData {
1160 roots: FxHashSet<Handle<UiNode>>,
1161 visited: Vec<bool>,
1162}
1163
1164pub struct PollResult {
1165 pub processed_messages: usize,
1166 pub message: Option<UiMessage>,
1167}
1168
1169impl UserInterface {
1170 pub fn new(screen_size: Vector2<f32>) -> UserInterface {
1171 let (sender, receiver) = mpsc::channel();
1172 Self::new_with_channel(sender, receiver, screen_size)
1173 }
1174
1175 pub fn new_with_channel(
1176 sender: Sender<UiMessage>,
1177 receiver: Receiver<UiMessage>,
1178 screen_size: Vector2<f32>,
1179 ) -> UserInterface {
1180 let (layout_events_sender, layout_events_receiver) = mpsc::channel();
1181 let style =
1182 StyleResource::new_ok(Uuid::new_v4(), ResourceKind::Embedded, Style::dark_style());
1183 let mut ui = UserInterface {
1184 screen_size,
1185 sender,
1186 receiver,
1187 visual_debug: false,
1188 captured_node: Handle::NONE,
1189 root_canvas: Handle::NONE,
1190 nodes: Pool::new(),
1191 cursor_position: Vector2::new(0.0, 0.0),
1192 drawing_context: DrawingContext::new(style.clone()),
1193 picked_node: Handle::NONE,
1194 prev_picked_node: Handle::NONE,
1195 style,
1196 keyboard_focus_node: Handle::NONE,
1197 stack: Default::default(),
1198 picking_stack: Default::default(),
1199 bubble_queue: Default::default(),
1200 drag_context: Default::default(),
1201 mouse_state: Default::default(),
1202 keyboard_modifiers: Default::default(),
1203 cursor_icon: Default::default(),
1204 active_tooltip: Default::default(),
1205 methods_registry: Default::default(),
1206 clipboard: Clipboard(ClipboardContext::new().ok().map(RefCell::new)),
1207 layout_events_receiver,
1208 layout_events_sender,
1209 z_index_update_set: Default::default(),
1210 default_font: BUILT_IN_FONT.resource(),
1211 double_click_entries: Default::default(),
1212 double_click_time_slice: 0.5, tooltip_appear_delay: 0.55,
1214 standard_material: Default::default(),
1215 render_target: None,
1216 render_mode: Default::default(),
1217 need_render: true,
1218 user_data: Default::default(),
1219 };
1220 let root_node = UiNode::new(Canvas {
1221 widget: WidgetBuilder::new().build(&ui.build_ctx()),
1222 });
1223 ui.root_canvas = ui.add_node(root_node);
1224 ui.keyboard_focus_node = ui.root_canvas;
1225 ui
1226 }
1227
1228 fn recursive_summary(&self, indent: usize, current: Handle<UiNode>, result: &mut String) {
1229 for _ in 0..indent {
1230 result.push_str(" ");
1231 }
1232 let Ok(node) = self.try_get(current) else {
1233 use std::fmt::Write;
1234 writeln!(result, "{}: Failed to get", current).unwrap();
1235 return;
1236 };
1237 result.push_str(&node.summary());
1238 result.push('\n');
1239 for child in node.children() {
1240 self.recursive_summary(indent + 1, *child, result);
1241 }
1242 }
1243
1244 pub fn set_tooltip_appear_delay(&mut self, appear_delay: f32) {
1245 self.tooltip_appear_delay = appear_delay;
1246 }
1247
1248 pub fn tooltip_appear_delay(&self) -> f32 {
1249 self.tooltip_appear_delay
1250 }
1251
1252 pub fn active_tooltip(&self) -> Option<&TooltipEntry> {
1253 self.active_tooltip.as_ref()
1254 }
1255
1256 pub fn keyboard_modifiers(&self) -> KeyboardModifiers {
1257 self.keyboard_modifiers
1258 }
1259
1260 pub fn build_ctx(&mut self) -> BuildContext<'_> {
1261 self.into()
1262 }
1263
1264 #[inline]
1265 pub fn capture_mouse(&mut self, node: Handle<impl ObjectOrVariant<UiNode>>) -> bool {
1266 let node = node.to_base();
1267 if self.captured_node.is_none() {
1268 self.captured_node = node;
1269 true
1270 } else {
1271 false
1272 }
1273 }
1274
1275 #[inline]
1276 pub fn release_mouse_capture(&mut self) {
1277 self.captured_node = Handle::NONE;
1278 }
1279
1280 pub fn is_node_enabled(&self, handle: Handle<UiNode>) -> bool {
1281 is_node_enabled(&self.nodes, handle)
1282 }
1283
1284 fn update_global_visibility(&mut self, from: Handle<UiNode>) {
1285 self.stack.clear();
1286 self.stack.push(from);
1287 while let Some(node_handle) = self.stack.pop() {
1288 let (widget, parent) = self
1289 .nodes
1290 .try_borrow_dependant_mut(node_handle, |n| n.parent());
1291
1292 if let Ok(widget) = widget {
1293 self.stack.extend_from_slice(widget.children());
1294
1295 let visibility = if let Ok(parent) = parent {
1296 widget.visibility() && parent.is_globally_visible()
1297 } else {
1298 widget.visibility()
1299 };
1300
1301 if widget.prev_global_visibility != visibility {
1302 let _ = self
1303 .layout_events_sender
1304 .send(LayoutEvent::MeasurementInvalidated(node_handle));
1305 let _ = self
1306 .layout_events_sender
1307 .send(LayoutEvent::ArrangementInvalidated(node_handle));
1308 }
1309
1310 widget.set_global_visibility(visibility);
1311 }
1312 }
1313 }
1314
1315 fn update_visual_transform(&mut self, from: Handle<UiNode>) {
1316 invalidate_recursive_up(&self.nodes, from, |n| n.visual_valid.set(false));
1317
1318 self.stack.clear();
1319 self.stack.push(from);
1320 while let Some(node_handle) = self.stack.pop() {
1321 let (widget, parent) = self
1322 .nodes
1323 .try_borrow_dependant_mut(node_handle, |n| n.parent());
1324
1325 if let Ok(widget) = widget {
1326 if widget.is_globally_visible() {
1327 self.stack.extend_from_slice(widget.children());
1328
1329 let mut layout_transform = *widget.layout_transform();
1330
1331 layout_transform[6] = widget.actual_local_position().x;
1332 layout_transform[7] = widget.actual_local_position().y;
1333
1334 let visual_transform = if let Ok(parent) = parent {
1335 parent.visual_transform() * layout_transform * widget.render_transform()
1336 } else {
1337 layout_transform * widget.render_transform()
1338 };
1339
1340 let old_transform =
1341 std::mem::replace(&mut widget.visual_transform, visual_transform);
1342 widget.on_visual_transform_changed(&old_transform, &visual_transform);
1343 widget.visual_valid.set(false);
1344 }
1345 }
1346 }
1347 }
1348
1349 pub fn screen_size(&self) -> Vector2<f32> {
1350 self.screen_size
1351 }
1352
1353 pub fn set_screen_size(&mut self, screen_size: Vector2<f32>) {
1354 self.screen_size = screen_size;
1355 }
1356
1357 fn handle_layout_events(&mut self, data: &mut VisualTransformUpdateData) {
1358 while let Ok(layout_event) = self.layout_events_receiver.try_recv() {
1359 match layout_event {
1360 LayoutEvent::MeasurementInvalidated(node) => {
1361 invalidate_recursive_up(&self.nodes, node, |node_ref| {
1362 node_ref.measure_valid.set(false);
1363 });
1364 }
1365 LayoutEvent::ArrangementInvalidated(node) => {
1366 invalidate_recursive_up(&self.nodes, node, |node_ref| {
1367 node_ref.arrange_valid.set(false);
1368 });
1369 }
1370 LayoutEvent::VisualInvalidated(node) => {
1371 invalidate_recursive_up(&self.nodes, node, |node_ref| {
1372 node_ref.visual_valid.set(false);
1373 });
1374 }
1375 LayoutEvent::VisibilityChanged(node) => {
1376 self.update_global_visibility(node);
1377 }
1378 LayoutEvent::ZIndexChanged(node) => {
1379 if let Ok(node_ref) = self.nodes.try_borrow(node) {
1380 self.z_index_update_set.insert(node_ref.parent);
1384 }
1385 }
1386 LayoutEvent::TransformChanged(node) => {
1387 let is_visited = &mut data.visited[node.index() as usize];
1388
1389 if *is_visited {
1390 continue;
1391 }
1392
1393 *is_visited = true;
1394
1395 data.roots.insert(node);
1396
1397 fn traverse_recursive(
1399 graph: &UserInterface,
1400 from: Handle<UiNode>,
1401 func: &mut impl FnMut(Handle<UiNode>),
1402 ) {
1403 func(from);
1404 if let Ok(node) = graph.try_get_node(from) {
1405 for &child in node.children() {
1406 traverse_recursive(graph, child, func)
1407 }
1408 }
1409 }
1410
1411 traverse_recursive(self, node, &mut |h| {
1412 data.visited[h.index() as usize] = true;
1413
1414 if h != node && data.roots.contains(&h) {
1416 data.roots.remove(&h);
1417 }
1418 })
1419 }
1420 }
1421 }
1422
1423 for node_handle in self.z_index_update_set.drain() {
1425 invalidate_recursive_up(&self.nodes, node_handle, |node_ref| {
1426 node_ref.visual_valid.set(false);
1427 });
1428
1429 let mbc = self.nodes.begin_multi_borrow();
1430 if let Ok(mut node) = mbc.try_get_mut(node_handle) {
1431 node.children.sort_by_key(|handle| {
1432 mbc.try_get(*handle).map(|c| *c.z_index).unwrap_or_default()
1433 });
1434 };
1435 }
1436 }
1437
1438 pub fn invalidate_layout(&mut self) {
1439 for node in self.nodes.iter_mut() {
1440 node.invalidate_layout();
1441 }
1442 }
1443
1444 pub fn update_layout(&mut self, screen_size: Vector2<f32>) {
1445 self.screen_size = screen_size;
1446
1447 let mut data = VisualTransformUpdateData {
1448 roots: Default::default(),
1449 visited: vec![false; self.nodes.get_capacity() as usize],
1450 };
1451
1452 self.handle_layout_events(&mut data);
1453
1454 self.measure_node(self.root_canvas, screen_size);
1455 self.arrange_node(
1456 self.root_canvas,
1457 &Rect::new(0.0, 0.0, screen_size.x, screen_size.y),
1458 );
1459
1460 self.handle_layout_events(&mut data);
1462
1463 for root in data.roots {
1464 self.update_visual_transform(root);
1465
1466 if let Ok(root_ref) = self.try_get_node(root) {
1468 self.calculate_clip_bounds(
1469 root,
1470 self.try_get_node(root_ref.parent())
1471 .ok()
1472 .map(|c| c.clip_bounds())
1473 .unwrap_or_else(|| {
1474 Rect::new(0.0, 0.0, self.screen_size.x, self.screen_size.y)
1475 }),
1476 );
1477 }
1478 }
1479 }
1480
1481 pub fn update(&mut self, screen_size: Vector2<f32>, dt: f32, switches: &UiUpdateSwitches) {
1482 for entry in self.double_click_entries.values_mut() {
1483 entry.timer -= dt;
1484 }
1485
1486 self.update_layout(screen_size);
1487
1488 if let Some(node_overrides) = switches.node_overrides.as_ref() {
1489 for &handle in node_overrides.iter() {
1490 let (ticket, mut node) = self.nodes.take_reserve(handle);
1491 node.update(dt, self);
1492 self.nodes.put_back(ticket, node);
1493 }
1494 } else {
1495 let update_subs = std::mem::take(&mut self.methods_registry.on_update);
1496 for &handle in update_subs.iter() {
1497 let (ticket, mut node) = self.nodes.take_reserve(handle);
1498 node.update(dt, self);
1499 self.nodes.put_back(ticket, node);
1500 }
1501 self.methods_registry.on_update = update_subs;
1502 }
1503
1504 self.update_tooltips(dt);
1505
1506 self.cursor_icon = CursorIcon::default();
1509 let mut handle = self.picked_node;
1510 while handle.is_some() {
1511 let node = &self.nodes[handle];
1512 if self.drag_context.is_dragging {
1513 if handle != self.drag_context.drag_node {
1514 if node.accepts_drop(self.drag_context.drag_node, self) {
1515 self.cursor_icon = CursorIcon::Crosshair;
1516 break;
1517 } else {
1518 self.cursor_icon = CursorIcon::NoDrop;
1519 }
1520 }
1521 } else if let Some(cursor) = node.cursor() {
1522 self.cursor_icon = cursor;
1523 break;
1524 }
1525 handle = node.parent();
1526 }
1527
1528 self.draw();
1529 }
1530
1531 pub fn style(&self) -> &StyleResource {
1532 &self.style
1533 }
1534
1535 pub fn set_style(&mut self, style: StyleResource) {
1536 self.style = style;
1537
1538 fn notify_depth_first(node: Handle<UiNode>, ui: &UserInterface) {
1539 if let Ok(node_ref) = ui.try_get_node(node) {
1540 for child in node_ref.children.iter() {
1541 notify_depth_first(*child, ui);
1542 }
1543
1544 ui.send(node, WidgetMessage::Style(ui.style.clone()));
1545 }
1546 }
1547
1548 notify_depth_first(self.root_canvas, self);
1549 }
1550
1551 pub fn cursor(&self) -> CursorIcon {
1552 self.cursor_icon
1553 }
1554
1555 pub fn set_time(&mut self, elapsed_time: f32) {
1556 self.drawing_context.elapsed_time = elapsed_time;
1557 }
1558
1559 fn draw(&mut self) {
1560 self.drawing_context.clear();
1561 draw_node(&self.nodes, self.root_canvas, &mut self.drawing_context);
1562
1563 fn merge_recursively<F>(
1565 node_handle: Handle<UiNode>,
1566 nodes: &Pool<UiNode, WidgetContainer>,
1567 drawing_context: &mut DrawingContext,
1568 filter: &mut F,
1569 ) where
1570 F: FnMut(&UiNode) -> bool,
1571 {
1572 let node = &nodes[node_handle];
1573
1574 if !filter(node) {
1575 return;
1576 }
1577
1578 if !node.is_globally_visible() || !is_on_screen(node, nodes) {
1579 return;
1580 }
1581
1582 assert!(node.visual_valid.get());
1583
1584 drawing_context.append(&node.render_data_set.borrow().draw_result);
1585
1586 for child in node.children() {
1587 merge_recursively(*child, nodes, drawing_context, filter);
1588 }
1589
1590 drawing_context.append(&node.render_data_set.borrow().post_draw_result);
1591 }
1592
1593 self.drawing_context.clear();
1594
1595 let mut topmost_nodes = Vec::new();
1596 merge_recursively(
1597 self.root_canvas,
1598 &self.nodes,
1599 &mut self.drawing_context,
1600 &mut |node| {
1601 if node.is_draw_on_top() {
1603 topmost_nodes.push(node.handle);
1604 false
1605 } else {
1606 true
1607 }
1608 },
1609 );
1610
1611 for topmost_node in topmost_nodes.drain(..) {
1612 merge_recursively(
1613 topmost_node,
1614 &self.nodes,
1615 &mut self.drawing_context,
1616 &mut |_| true,
1617 );
1618 }
1619
1620 if self.visual_debug {
1622 if self.picked_node.is_some() {
1623 let bounds = self.nodes.borrow(self.picked_node).screen_bounds();
1624 self.drawing_context.push_rect(&bounds, 1.0);
1625 self.drawing_context.commit(
1626 bounds,
1627 Brush::Solid(Color::WHITE),
1628 CommandTexture::None,
1629 &self.standard_material,
1630 None,
1631 );
1632 }
1633
1634 if self.keyboard_focus_node.is_some() {
1635 let bounds = self.nodes.borrow(self.keyboard_focus_node).screen_bounds();
1636 self.drawing_context.push_rect(&bounds, 1.0);
1637 self.drawing_context.commit(
1638 bounds,
1639 Brush::Solid(Color::GREEN),
1640 CommandTexture::None,
1641 &self.standard_material,
1642 None,
1643 );
1644 }
1645 }
1646
1647 if let Ok(keyboard_focus_node) = self.nodes.try_borrow(self.keyboard_focus_node) {
1648 if keyboard_focus_node.global_visibility && keyboard_focus_node.accepts_input {
1649 let bounds = keyboard_focus_node
1650 .screen_bounds()
1651 .clip_by(keyboard_focus_node.clip_bounds())
1652 .unwrap_or_default()
1653 .inflate(1.0, 1.0);
1654 self.drawing_context.push_rounded_rect(&bounds, 1.0, 2.0, 6);
1655 self.drawing_context.commit(
1656 bounds,
1657 DEFAULT_STYLE
1658 .resource
1659 .get_or_default(Style::BRUSH_HIGHLIGHT),
1660 CommandTexture::None,
1661 &self.standard_material,
1662 None,
1663 );
1664 }
1665 }
1666 }
1667
1668 pub fn clipboard(&self) -> Option<Ref<ClipboardContext>> {
1669 self.clipboard.0.as_ref().map(|v| v.borrow())
1670 }
1671
1672 pub fn clipboard_mut(&self) -> Option<RefMut<ClipboardContext>> {
1673 self.clipboard.0.as_ref().map(|v| v.borrow_mut())
1674 }
1675
1676 pub fn arrange_node(
1677 &self,
1678 handle: Handle<impl ObjectOrVariant<UiNode>>,
1679 final_rect: &Rect<f32>,
1680 ) -> bool {
1681 let handle = handle.to_base();
1682 let node = self.node(handle);
1683
1684 if node.is_arrange_valid() && node.prev_arrange.get() == *final_rect {
1685 return false;
1686 }
1687
1688 if node.visibility() {
1689 node.prev_arrange.set(*final_rect);
1690
1691 let margin = node.margin().axes_margin();
1692
1693 let mut size = Vector2::new(
1694 (final_rect.w() - margin.x).max(0.0),
1695 (final_rect.h() - margin.y).max(0.0),
1696 );
1697
1698 let available_size = size;
1699
1700 if node.horizontal_alignment() != HorizontalAlignment::Stretch {
1701 size.x = size.x.min(node.desired_size().x - margin.x);
1702 }
1703 if node.vertical_alignment() != VerticalAlignment::Stretch {
1704 size.y = size.y.min(node.desired_size().y - margin.y);
1705 }
1706
1707 if node.width() > 0.0 {
1708 size.x = node.width();
1709 }
1710 if node.height() > 0.0 {
1711 size.y = node.height();
1712 }
1713
1714 size = transform_size(size, node.layout_transform());
1715
1716 if !node.ignore_layout_rounding {
1717 size.x = size.x.ceil();
1718 size.y = size.y.ceil();
1719 }
1720
1721 size = node.arrange_override(self, size);
1722
1723 size.x = size.x.min(final_rect.w());
1724 size.y = size.y.min(final_rect.h());
1725
1726 let transformed_rect =
1727 Rect::new(0.0, 0.0, size.x, size.y).transform(node.layout_transform());
1728
1729 size = transformed_rect.size;
1730
1731 let mut origin =
1732 final_rect.position - transformed_rect.position + node.margin().offset();
1733
1734 match node.horizontal_alignment() {
1735 HorizontalAlignment::Center | HorizontalAlignment::Stretch => {
1736 origin.x += (available_size.x - size.x) * 0.5;
1737 }
1738 HorizontalAlignment::Right => origin.x += available_size.x - size.x,
1739 _ => (),
1740 }
1741
1742 match node.vertical_alignment() {
1743 VerticalAlignment::Center | VerticalAlignment::Stretch => {
1744 origin.y += (available_size.y - size.y) * 0.5;
1745 }
1746 VerticalAlignment::Bottom => origin.y += available_size.y - size.y,
1747 _ => (),
1748 }
1749
1750 if !node.ignore_layout_rounding {
1751 origin.x = origin.x.floor();
1752 origin.y = origin.y.floor();
1753 }
1754
1755 node.commit_arrange(origin, size);
1756 }
1757
1758 true
1759 }
1760
1761 pub fn measure_node(
1762 &self,
1763 handle: Handle<impl ObjectOrVariant<UiNode>>,
1764 available_size: Vector2<f32>,
1765 ) -> bool {
1766 let handle = handle.to_base();
1767 let node = self.node(handle);
1768
1769 if node.is_measure_valid() && node.prev_measure.get() == available_size {
1770 return false;
1771 }
1772
1773 if node.visibility() {
1774 node.prev_measure.set(available_size);
1775
1776 let axes_margin = node.margin().axes_margin();
1777 let mut inner_size = available_size - axes_margin;
1778 inner_size.x = inner_size.x.max(0.0);
1779 inner_size.y = inner_size.y.max(0.0);
1780
1781 let mut size = Vector2::new(
1782 if node.width() > 0.0 {
1783 node.width()
1784 } else {
1785 inner_size.x
1786 },
1787 if node.height() > 0.0 {
1788 node.height()
1789 } else {
1790 inner_size.y
1791 },
1792 );
1793
1794 size = transform_size(size, node.layout_transform());
1795
1796 if size.x.is_finite() {
1797 size.x = size.x.clamp(node.min_size().x, node.max_size().x);
1798 }
1799 if size.y.is_finite() {
1800 size.y = size.y.clamp(node.min_size().y, node.max_size().y);
1801 }
1802
1803 let mut desired_size = node.measure_override(self, size);
1804
1805 desired_size = Rect::new(0.0, 0.0, desired_size.x, desired_size.y)
1806 .transform(node.layout_transform())
1807 .size;
1808
1809 if !node.width().is_nan() {
1810 desired_size.x = node.width();
1811 }
1812 if !node.height().is_nan() {
1813 desired_size.y = node.height();
1814 }
1815
1816 desired_size.x = desired_size.x.clamp(node.min_size().x, node.max_size().x);
1817 desired_size.y = desired_size.y.clamp(node.min_size().y, node.max_size().y);
1818
1819 desired_size += axes_margin;
1820
1821 if node.ignore_layout_rounding {
1822 desired_size.x = desired_size.x.min(available_size.x);
1823 desired_size.y = desired_size.y.min(available_size.y);
1824 } else {
1825 desired_size.x = desired_size.x.min(available_size.x).ceil();
1826 desired_size.y = desired_size.y.min(available_size.y).ceil();
1827 }
1828
1829 node.commit_measure(desired_size);
1830 } else {
1831 node.commit_measure(Vector2::new(0.0, 0.0));
1832 }
1833
1834 true
1835 }
1836
1837 fn is_node_clipped(&self, node_handle: Handle<UiNode>, pt: Vector2<f32>) -> bool {
1838 let mut clipped = true;
1839
1840 let widget = self.nodes.borrow(node_handle);
1841 let render_data_set = widget.render_data_set.borrow();
1842
1843 if widget.is_globally_visible() {
1844 clipped = !widget.clip_bounds().contains(pt);
1845
1846 if !clipped {
1847 for command in render_data_set.draw_result.command_buffer.iter() {
1849 if let Some(geometry) = command.clipping_geometry.as_ref() {
1850 if geometry.is_contains_point(pt) {
1851 clipped = false;
1852 break;
1853 }
1854 }
1855 }
1856 }
1857
1858 if !widget.parent().is_none() && !clipped {
1860 clipped |= self.is_node_clipped(widget.parent(), pt);
1861 }
1862 }
1863
1864 clipped
1865 }
1866
1867 fn is_node_contains_point(&self, node_handle: Handle<UiNode>, pt: Vector2<f32>) -> bool {
1868 let widget = self.nodes.borrow(node_handle);
1869
1870 if !widget.is_globally_visible() {
1871 return false;
1872 }
1873
1874 let render_data_set = widget.render_data_set.borrow();
1875
1876 if !self.is_node_clipped(node_handle, pt) {
1877 for command in render_data_set.draw_result.command_buffer.iter() {
1879 if render_data_set
1880 .draw_result
1881 .is_command_contains_point(command, pt)
1882 {
1883 return true;
1884 }
1885 }
1886 }
1887
1888 false
1889 }
1890
1891 fn pick_node(
1892 &self,
1893 node_handle: Handle<UiNode>,
1894 pt: Vector2<f32>,
1895 level: &mut i32,
1896 ) -> Handle<UiNode> {
1897 let widget = self.nodes.borrow(node_handle);
1898
1899 if !widget.is_hit_test_visible()
1900 || !widget.enabled()
1901 || !widget.clip_bounds().intersects(Rect {
1902 position: Default::default(),
1903 size: self.screen_size,
1904 })
1905 {
1906 return Handle::NONE;
1907 }
1908
1909 let (mut picked, mut topmost_picked_level) = if self.is_node_contains_point(node_handle, pt)
1910 {
1911 (node_handle, *level)
1912 } else {
1913 (Handle::NONE, 0)
1914 };
1915
1916 for child_handle in widget.children() {
1917 *level += 1;
1918 let picked_child = self.pick_node(*child_handle, pt, level);
1919 if picked_child.is_some() && *level > topmost_picked_level {
1920 topmost_picked_level = *level;
1921 picked = picked_child;
1922 }
1923 }
1924
1925 picked
1926 }
1927
1928 pub fn cursor_position(&self) -> Vector2<f32> {
1930 self.cursor_position
1931 }
1932
1933 pub fn hit_test_unrestricted(&self, pt: Vector2<f32>) -> Handle<UiNode> {
1934 let mut level = 0;
1936 self.pick_node(self.root_canvas, pt, &mut level)
1937 }
1938
1939 pub fn hit_test(&self, pt: Vector2<f32>) -> Handle<UiNode> {
1940 if self.nodes.is_valid_handle(self.captured_node) {
1941 self.captured_node
1942 } else if self.picking_stack.is_empty() {
1943 self.hit_test_unrestricted(pt)
1944 } else {
1945 for root in self.picking_stack.iter().rev() {
1950 if self.nodes.is_valid_handle(root.handle) {
1951 let mut level = 0;
1952 let picked = self.pick_node(root.handle, pt, &mut level);
1953 if picked.is_some() {
1954 return picked;
1955 }
1956 }
1957 if root.stop {
1958 break;
1959 }
1960 }
1961 Handle::NONE
1962 }
1963 }
1964
1965 pub fn is_node_child_of(
1968 &self,
1969 node_handle: Handle<impl ObjectOrVariant<UiNode>>,
1970 root_handle: Handle<impl ObjectOrVariant<UiNode>>,
1971 ) -> bool {
1972 self.nodes
1973 .borrow(root_handle.to_base())
1974 .has_descendant(node_handle.to_base(), self)
1975 }
1976
1977 pub fn has_descendant_or_equal(
1980 &self,
1981 node_handle: Handle<impl ObjectOrVariant<UiNode>>,
1982 root_handle: Handle<impl ObjectOrVariant<UiNode>>,
1983 ) -> bool {
1984 root_handle.to_base() == node_handle.to_base()
1985 || self.is_node_child_of(node_handle, root_handle)
1986 }
1987
1988 fn calculate_clip_bounds(&self, node: Handle<UiNode>, parent_bounds: Rect<f32>) {
1990 let node = &self.nodes[node];
1991
1992 let screen_bounds = if *node.clip_to_bounds {
1993 node.screen_bounds()
1994 } else {
1995 Rect::new(0.0, 0.0, self.screen_size.x, self.screen_size.y)
1996 };
1997
1998 node.clip_bounds.set(
1999 screen_bounds
2000 .clip_by(parent_bounds)
2001 .unwrap_or(screen_bounds),
2002 );
2003
2004 for &child in node.children() {
2005 self.calculate_clip_bounds(child, node.clip_bounds.get());
2006 }
2007 }
2008
2009 pub fn sender(&self) -> Sender<UiMessage> {
2012 self.sender.clone()
2013 }
2014
2015 pub fn send_message(&self, message: UiMessage) {
2016 self.sender.send(message).unwrap()
2017 }
2018
2019 pub fn send_messages<const N: usize>(&self, messages: [UiMessage; N]) {
2020 for message in messages {
2021 self.send_message(message)
2022 }
2023 }
2024
2025 pub fn send(&self, handle: Handle<impl ObjectOrVariant<UiNode>>, data: impl MessageData) {
2026 self.sender
2027 .send(
2028 UiMessage::with_data(data)
2029 .with_destination(handle.transmute())
2030 .with_direction(MessageDirection::ToWidget),
2031 )
2032 .unwrap()
2033 }
2034
2035 pub fn send_handled(
2036 &self,
2037 handle: Handle<impl ObjectOrVariant<UiNode>>,
2038 data: impl MessageData,
2039 ) {
2040 self.sender
2041 .send(
2042 UiMessage::with_data(data)
2043 .with_destination(handle.transmute())
2044 .with_direction(MessageDirection::ToWidget)
2045 .with_handled(true),
2046 )
2047 .unwrap()
2048 }
2049
2050 pub fn send_sync(&self, handle: Handle<impl ObjectOrVariant<UiNode>>, data: impl MessageData) {
2051 self.sender
2052 .send(
2053 UiMessage::with_data(data)
2054 .with_destination(handle.transmute())
2055 .with_direction(MessageDirection::ToWidget)
2056 .with_delivery_mode(DeliveryMode::SyncOnly),
2057 )
2058 .unwrap()
2059 }
2060
2061 pub fn send_with_flags<T: MessageData>(
2062 &self,
2063 handle: Handle<impl ObjectOrVariant<UiNode>>,
2064 flags: u64,
2065 data: T,
2066 ) {
2067 self.sender
2068 .send(
2069 UiMessage::with_data(data)
2070 .with_destination(handle.transmute())
2071 .with_direction(MessageDirection::ToWidget)
2072 .with_flags(flags),
2073 )
2074 .unwrap()
2075 }
2076
2077 pub fn send_many<const N: usize, T: MessageData>(
2078 &self,
2079 handle: Handle<impl ObjectOrVariant<UiNode>>,
2080 payload: [T; N],
2081 ) {
2082 for data in payload {
2083 self.send(handle, data)
2084 }
2085 }
2086
2087 pub fn send_sync_many<const N: usize, T: MessageData>(
2088 &self,
2089 handle: Handle<impl ObjectOrVariant<UiNode>>,
2090 payload: [T; N],
2091 ) {
2092 for data in payload {
2093 self.send_sync(handle, data)
2094 }
2095 }
2096
2097 pub fn post<T: MessageData>(&self, handle: Handle<impl ObjectOrVariant<UiNode>>, data: T) {
2098 self.sender
2099 .send(
2100 UiMessage::with_data(data)
2101 .with_destination(handle.transmute())
2102 .with_direction(MessageDirection::FromWidget),
2103 )
2104 .unwrap()
2105 }
2106
2107 pub fn post_many<const N: usize, T: MessageData>(
2108 &self,
2109 handle: Handle<impl ObjectOrVariant<UiNode>>,
2110 payload: [T; N],
2111 ) {
2112 for data in payload {
2113 self.post(handle, data)
2114 }
2115 }
2116
2117 fn make_topmost(&mut self, node: Handle<UiNode>) {
2125 let parent = self.node(node).parent();
2126 if parent.is_some() {
2127 let parent = &mut self.nodes[parent];
2128 parent.remove_child(node);
2129 parent.add_child(node, false);
2130 }
2131 }
2132
2133 fn make_lowermost(&mut self, node: Handle<UiNode>) {
2134 let parent = self.node(node).parent();
2135 if parent.is_some() {
2136 let parent = &mut self.nodes[parent];
2137 parent.remove_child(node);
2138 parent.add_child(node, true);
2139 }
2140 }
2141
2142 fn bubble_message(&mut self, message: &mut UiMessage) {
2143 self.bubble_queue.clear();
2147 self.bubble_queue.push_back(message.destination());
2148 let mut parent = self.nodes[message.destination()].parent();
2149 while parent.is_some() && self.nodes.is_valid_handle(parent) {
2150 self.bubble_queue.push_back(parent);
2151 parent = self.nodes[parent].parent();
2152 }
2153
2154 while let Some(handle) = self.bubble_queue.pop_front() {
2155 let (ticket, mut node) = self.nodes.take_reserve(handle);
2156 node.handle_routed_message(self, message);
2157 self.nodes.put_back(ticket, node);
2158 }
2159 }
2160
2161 pub fn poll_message_queue(&mut self) -> PollResult {
2221 let mut poll_result = PollResult {
2222 processed_messages: 0,
2223 message: None,
2224 };
2225
2226 while let Ok(message) = self.receiver.try_recv() {
2227 poll_result.processed_messages += 1;
2228 if let Some(message) = self.poll_single_message(message) {
2229 poll_result.message = Some(message);
2230 break;
2231 }
2232 }
2233
2234 poll_result
2235 }
2236
2237 pub fn poll_message(&mut self) -> Option<UiMessage> {
2240 self.poll_message_queue().message
2241 }
2242
2243 fn poll_single_message(&mut self, mut message: UiMessage) -> Option<UiMessage> {
2244 if !self.nodes.is_valid_handle(message.destination()) {
2247 return Some(message);
2248 }
2249
2250 if let RenderMode::OnChanges = self.render_mode {
2251 self.need_render = true;
2252 }
2253
2254 if message.need_perform_layout() {
2255 self.update_layout(self.screen_size);
2256 }
2257
2258 for &handle in self.methods_registry.preview_message.iter() {
2259 if let Ok(node_ref) = self.nodes.try_borrow(handle) {
2260 node_ref.preview_message(self, &mut message);
2261 }
2262 }
2263
2264 match message.routing_strategy {
2265 RoutingStrategy::BubbleUp => self.bubble_message(&mut message),
2266 RoutingStrategy::Direct => {
2267 let (ticket, mut node) = self.nodes.take_reserve(message.destination());
2268 node.handle_routed_message(self, &mut message);
2269 self.nodes.put_back(ticket, node);
2270 }
2271 }
2272
2273 if let Some(msg) = message.data::<WidgetMessage>() {
2274 match msg {
2275 WidgetMessage::Focus => {
2276 if self.nodes.is_valid_handle(message.destination())
2277 && message.direction() == MessageDirection::ToWidget
2278 {
2279 self.request_focus(message.destination());
2280 }
2281 }
2282 WidgetMessage::Unfocus => {
2283 if self.nodes.is_valid_handle(message.destination())
2284 && message.direction() == MessageDirection::ToWidget
2285 {
2286 self.request_focus(self.root_canvas);
2287 }
2288 }
2289 WidgetMessage::Topmost => {
2290 if self.nodes.is_valid_handle(message.destination()) {
2291 self.make_topmost(message.destination());
2292 }
2293 }
2294 WidgetMessage::Lowermost => {
2295 if self.nodes.is_valid_handle(message.destination()) {
2296 self.make_lowermost(message.destination());
2297 }
2298 }
2299 WidgetMessage::Unlink => {
2300 if self.nodes.is_valid_handle(message.destination()) {
2301 self.unlink_node(message.destination());
2302
2303 let node = &self.nodes[message.destination()];
2304 let new_position = self.screen_to_root_canvas_space(node.screen_position());
2305 self.send(
2306 message.destination(),
2307 WidgetMessage::DesiredPosition(new_position),
2308 );
2309 }
2310 }
2311 &WidgetMessage::LinkWith(parent) => {
2312 if self.nodes.is_valid_handle(message.destination())
2313 && self.nodes.is_valid_handle(parent)
2314 {
2315 self.link_nodes(message.destination(), parent, false);
2316 }
2317 }
2318 &WidgetMessage::LinkWithReverse(parent) => {
2319 if self.nodes.is_valid_handle(message.destination())
2320 && self.nodes.is_valid_handle(parent)
2321 {
2322 self.link_nodes(message.destination(), parent, true);
2323 }
2324 }
2325 WidgetMessage::ReplaceChildren(children) => {
2326 if self.nodes.is_valid_handle(message.destination()) {
2327 let old_children = self.node(message.destination()).children().to_vec();
2328 for child in old_children.iter() {
2329 if self.nodes.is_valid_handle(*child) {
2330 if children.contains(child) {
2331 self.unlink_node(*child);
2332 } else {
2333 self.remove_node(*child);
2334 }
2335 }
2336 }
2337 for &child in children.iter() {
2338 if self.nodes.is_valid_handle(child) {
2339 self.link_nodes(child, message.destination(), false);
2340 }
2341 }
2342 }
2343 }
2344 WidgetMessage::Remove => {
2345 if self.nodes.is_valid_handle(message.destination()) {
2346 self.remove_node(message.destination());
2347 }
2348 }
2349 WidgetMessage::ContextMenu(context_menu) => {
2350 if self.nodes.is_valid_handle(message.destination()) {
2351 let node = self.nodes.borrow_mut(message.destination());
2352 node.set_context_menu(context_menu.clone());
2353 }
2354 }
2355 WidgetMessage::Tooltip(tooltip) => {
2356 if self.nodes.is_valid_handle(message.destination()) {
2357 let node = self.nodes.borrow_mut(message.destination());
2358 node.set_tooltip(tooltip.clone());
2359 }
2360 }
2361 WidgetMessage::Center => {
2362 if self.nodes.is_valid_handle(message.destination()) {
2363 let node = self.node(message.destination());
2364 let size = node.actual_initial_size();
2365 let parent = node.parent();
2366 let parent_size = if parent.is_some() {
2367 self.node(parent).actual_initial_size()
2368 } else {
2369 self.screen_size
2370 };
2371
2372 self.send(
2373 message.destination(),
2374 WidgetMessage::DesiredPosition((parent_size - size).scale(0.5)),
2375 );
2376 }
2377 }
2378 WidgetMessage::RenderTransform(_) => {
2379 if self.nodes.is_valid_handle(message.destination()) {
2380 self.update_visual_transform(message.destination());
2381 }
2382 }
2383 WidgetMessage::AdjustPositionToFit => {
2384 if self.nodes.is_valid_handle(message.destination()) {
2385 let node = self.node(message.destination());
2386 let mut position = node.actual_local_position();
2387 let size = node.actual_initial_size();
2388 let parent = node.parent();
2389 let parent_size = if parent.is_some() {
2390 self.node(parent).actual_initial_size()
2391 } else {
2392 self.screen_size
2393 };
2394
2395 if position.x < 0.0 {
2396 position.x = 0.0;
2397 }
2398 if position.x + size.x > parent_size.x {
2399 position.x -= (position.x + size.x) - parent_size.x;
2400 }
2401 if position.y < 0.0 {
2402 position.y = 0.0;
2403 }
2404 if position.y + size.y > parent_size.y {
2405 position.y -= (position.y + size.y) - parent_size.y;
2406 }
2407
2408 self.send(
2409 message.destination(),
2410 WidgetMessage::DesiredPosition(position),
2411 );
2412 }
2413 }
2414 WidgetMessage::Align {
2415 relative_to,
2416 horizontal_alignment,
2417 vertical_alignment,
2418 margin,
2419 } => {
2420 if let (Ok(node), Ok(relative_node)) = (
2421 self.try_get_node(message.destination()),
2422 self.try_get_node(*relative_to),
2423 ) {
2424 let relative_node_screen_size = relative_node.screen_bounds().size;
2426 let relative_node_screen_position = relative_node.screen_position();
2427 let node_screen_size = node.screen_bounds().size;
2428
2429 let mut screen_anchor_point = Vector2::default();
2430 match horizontal_alignment {
2431 HorizontalAlignment::Stretch => {
2432 }
2434 HorizontalAlignment::Left => {
2435 screen_anchor_point.x =
2436 relative_node_screen_position.x + margin.left;
2437 }
2438 HorizontalAlignment::Center => {
2439 screen_anchor_point.x = relative_node_screen_position.x
2440 + (relative_node_screen_size.x
2441 + node_screen_size.x
2442 + margin.left
2443 + margin.right)
2444 * 0.5;
2445 }
2446 HorizontalAlignment::Right => {
2447 screen_anchor_point.x = relative_node_screen_position.x
2448 + relative_node_screen_size.x
2449 - node_screen_size.x
2450 - margin.right;
2451 }
2452 }
2453
2454 match vertical_alignment {
2455 VerticalAlignment::Stretch => {
2456 }
2458 VerticalAlignment::Top => {
2459 screen_anchor_point.y =
2460 relative_node_screen_position.y + margin.top;
2461 }
2462 VerticalAlignment::Center => {
2463 screen_anchor_point.y = relative_node_screen_position.y
2464 + (relative_node_screen_size.y
2465 + node_screen_size.y
2466 + margin.top
2467 + margin.bottom)
2468 * 0.5;
2469 }
2470 VerticalAlignment::Bottom => {
2471 screen_anchor_point.y = relative_node_screen_position.y
2472 + (relative_node_screen_size.y
2473 - node_screen_size.y
2474 - margin.bottom);
2475 }
2476 }
2477
2478 if let Ok(parent) = self.try_get_node(node.parent()) {
2479 let local_anchor_point = parent.screen_to_local(screen_anchor_point);
2482 self.send(
2483 message.destination(),
2484 WidgetMessage::DesiredPosition(local_anchor_point),
2485 );
2486 }
2487 }
2488 }
2489 WidgetMessage::MouseUp { button, .. } => {
2490 if *button == MouseButton::Right && !message.handled() {
2491 if let Ok(picked) = self.nodes.try_borrow(self.picked_node) {
2492 let (context_menu, target) = if picked.context_menu().is_some() {
2494 (picked.context_menu(), self.picked_node)
2495 } else {
2496 let parent_handle = picked
2497 .find_by_criteria_up(self, |n| n.context_menu().is_some());
2498
2499 if let Ok(parent) = self.nodes.try_borrow(parent_handle) {
2500 (parent.context_menu(), parent_handle)
2501 } else {
2502 (None, Handle::NONE)
2503 }
2504 };
2505
2506 if let Some(context_menu) = context_menu {
2508 self.send(
2509 context_menu.handle(),
2510 PopupMessage::Placement(Placement::Cursor(target)),
2511 );
2512 self.send(context_menu.handle(), PopupMessage::Open);
2513 self.send(
2516 context_menu.handle(),
2517 PopupMessage::Owner(self.picked_node),
2518 );
2519 }
2520 }
2521 }
2522 }
2523 _ => {}
2524 }
2525 }
2526
2527 match message.delivery_mode {
2528 DeliveryMode::FullCycle => Some(message),
2529 DeliveryMode::SyncOnly => None,
2530 }
2531 }
2532
2533 pub fn screen_to_root_canvas_space(&self, position: Vector2<f32>) -> Vector2<f32> {
2534 self.node(self.root()).screen_to_local(position)
2535 }
2536
2537 fn show_tooltip(&self, tooltip: RcUiNodeHandle) {
2538 self.send(tooltip.handle(), WidgetMessage::Visibility(true));
2539 self.send(tooltip.handle(), WidgetMessage::Topmost);
2540 self.send(
2541 tooltip.handle(),
2542 WidgetMessage::DesiredPosition(
2543 self.screen_to_root_canvas_space(self.cursor_position() + Vector2::new(0.0, 16.0)),
2544 ),
2545 );
2546 self.send(tooltip.handle(), WidgetMessage::AdjustPositionToFit);
2547 }
2548
2549 fn replace_or_update_tooltip(&mut self, tooltip: RcUiNodeHandle, disappear_timeout: f32) {
2550 if let Some(entry) = self.active_tooltip.as_mut() {
2551 if entry.tooltip == tooltip {
2552 if entry.shown {
2553 entry.disappear_timer = disappear_timeout;
2555 }
2556 } else {
2557 let old_tooltip = entry.tooltip.clone();
2558
2559 entry.shown = false;
2560 entry.appear_timer = self.tooltip_appear_delay;
2561 entry.disappear_timer = disappear_timeout;
2562 entry.tooltip = tooltip.clone();
2563
2564 self.send(old_tooltip.handle(), WidgetMessage::Visibility(false));
2566 }
2567 } else {
2568 self.active_tooltip = Some(TooltipEntry::new(
2569 tooltip,
2570 self.tooltip_appear_delay,
2571 disappear_timeout,
2572 ));
2573 }
2574 }
2575
2576 fn update_tooltips(&mut self, dt: f32) {
2579 let sender = self.sender.clone();
2580 if let Some(entry) = self.active_tooltip.as_mut() {
2581 if entry.shown {
2582 entry.disappear_timer -= dt;
2583 if entry.disappear_timer <= 0.0 {
2584 sender
2587 .send(UiMessage::for_widget(
2588 entry.tooltip.handle(),
2589 WidgetMessage::Visibility(false),
2590 ))
2591 .unwrap();
2592
2593 self.active_tooltip = None;
2594 }
2595 } else {
2596 let mut tooltip_owner_hovered = false;
2597 let mut handle = self.picked_node;
2598 while let Ok(node) = self.nodes.try_borrow(handle) {
2599 if let Some(tooltip) = node.tooltip.as_ref() {
2600 if &entry.tooltip == tooltip {
2601 tooltip_owner_hovered = true;
2602 break;
2603 }
2604 }
2605 handle = node.parent();
2606 }
2607
2608 if tooltip_owner_hovered {
2609 entry.appear_timer -= dt;
2610 if entry.appear_timer <= 0.0 {
2611 entry.shown = true;
2612 let tooltip = entry.tooltip.clone();
2613 self.show_tooltip(tooltip);
2614 }
2615 } else {
2616 self.active_tooltip = None;
2617 }
2618 }
2619 }
2620
2621 let mut handle = self.picked_node;
2623 while let Ok(node) = self.nodes.try_borrow(handle) {
2624 let parent = node.parent();
2625
2626 if let Some(tooltip) = node.tooltip() {
2627 let disappear_timeout = node.tooltip_time();
2629 self.replace_or_update_tooltip(tooltip, disappear_timeout);
2630 break;
2631 } else if let Some(entry) = self.active_tooltip.as_mut() {
2632 if entry.tooltip.handle() == handle {
2633 entry.disappear_timer = entry.max_time;
2636 break;
2637 }
2638 }
2639
2640 handle = parent;
2641 }
2642 }
2643
2644 pub fn captured_node(&self) -> Handle<UiNode> {
2645 self.captured_node
2646 }
2647
2648 fn try_set_picked_node(&mut self, node: Handle<UiNode>) -> bool {
2651 if self.picked_node != node {
2652 self.picked_node = node;
2653 self.reset_double_click_entries();
2654 true
2655 } else {
2656 false
2657 }
2658 }
2659
2660 fn reset_double_click_entries(&mut self) {
2661 for entry in self.double_click_entries.values_mut() {
2662 entry.timer = self.double_click_time_slice;
2663 entry.click_count = 0;
2664 }
2665 }
2666
2667 fn request_focus(&mut self, new_focused: Handle<UiNode>) {
2668 if self.keyboard_focus_node != new_focused {
2669 if self.keyboard_focus_node.is_some() {
2670 self.post(self.keyboard_focus_node, WidgetMessage::Unfocus);
2671 }
2672 self.keyboard_focus_node = new_focused;
2673 if self.keyboard_focus_node.is_some() {
2674 self.post(self.keyboard_focus_node, WidgetMessage::Focus);
2675 }
2676 }
2677 }
2678
2679 pub fn process_os_event(&mut self, event: &OsEvent) -> bool {
2683 let mut event_processed = false;
2684
2685 match event {
2686 &OsEvent::MouseInput { button, state, .. } => {
2687 match button {
2688 MouseButton::Left => self.mouse_state.left = state,
2689 MouseButton::Right => self.mouse_state.right = state,
2690 MouseButton::Middle => self.mouse_state.middle = state,
2691 _ => {}
2692 }
2693
2694 match state {
2695 ButtonState::Pressed => {
2696 let picked_changed =
2697 self.try_set_picked_node(self.hit_test(self.cursor_position));
2698
2699 let mut emit_double_click = false;
2700 if !picked_changed {
2701 match self.double_click_entries.entry(button) {
2702 Entry::Occupied(e) => {
2703 let entry = e.into_mut();
2704 if entry.timer > 0.0 {
2705 entry.click_count += 1;
2706 if entry.click_count >= 2 {
2707 entry.click_count = 0;
2708 entry.timer = self.double_click_time_slice;
2709 emit_double_click = true;
2710 }
2711 } else {
2712 entry.timer = self.double_click_time_slice;
2713 entry.click_count = 1;
2714 }
2715 }
2716 Entry::Vacant(entry) => {
2717 entry.insert(DoubleClickEntry {
2720 timer: self.double_click_time_slice,
2721 click_count: 1,
2722 });
2723 }
2724 }
2725 }
2726
2727 if self.picked_node.is_some() {
2729 self.stack.clear();
2730 self.stack.push(self.picked_node);
2731 while let Some(handle) = self.stack.pop() {
2732 let node = &self.nodes[handle];
2733 if node.is_drag_allowed() {
2734 self.drag_context.drag_node = handle;
2735 self.stack.clear();
2736 break;
2737 } else if node.parent().is_some() {
2738 self.stack.push(node.parent());
2739 }
2740 }
2741 self.drag_context.click_pos = self.cursor_position;
2742 }
2743
2744 self.request_focus(self.picked_node);
2745
2746 if self.picked_node.is_some() {
2747 self.post(
2748 self.picked_node,
2749 WidgetMessage::MouseDown {
2750 pos: self.cursor_position,
2751 button,
2752 },
2753 );
2754 event_processed = true;
2755 }
2756
2757 if emit_double_click {
2759 self.post(self.picked_node, WidgetMessage::DoubleClick { button });
2760 }
2761 }
2762 ButtonState::Released => {
2763 if self.picked_node.is_some() {
2764 self.post(
2765 self.picked_node,
2766 WidgetMessage::MouseUp {
2767 pos: self.cursor_position,
2768 button,
2769 },
2770 );
2771
2772 if self.drag_context.is_dragging {
2773 self.drag_context.is_dragging = false;
2774 self.cursor_icon = CursorIcon::Default;
2775
2776 self.stack.clear();
2778 self.stack.push(self.picked_node);
2779 while let Some(handle) = self.stack.pop() {
2780 let node = &self.nodes[handle];
2781 if node.is_drop_allowed() {
2782 self.post(
2783 handle,
2784 WidgetMessage::Drop(self.drag_context.drag_node),
2785 );
2786 self.stack.clear();
2787 break;
2788 } else if node.parent().is_some() {
2789 self.stack.push(node.parent());
2790 }
2791 }
2792 }
2793 self.drag_context.drag_node = Handle::NONE;
2794 if self.nodes.is_valid_handle(self.drag_context.drag_preview) {
2795 self.remove_node(self.drag_context.drag_preview);
2796 self.drag_context.drag_preview = Default::default();
2797 }
2798
2799 event_processed = true;
2800 }
2801 }
2802 }
2803 }
2804 OsEvent::CursorMoved { position } => {
2805 self.cursor_position = *position;
2806 self.try_set_picked_node(self.hit_test(self.cursor_position));
2807
2808 if !self.drag_context.is_dragging
2809 && self.mouse_state.left == ButtonState::Pressed
2810 && self.picked_node.is_some()
2811 && self.nodes.is_valid_handle(self.drag_context.drag_node)
2812 && (self.drag_context.click_pos - *position).norm() > 5.0
2813 {
2814 self.drag_context.drag_preview =
2815 self.copy_node_with_limit(self.drag_context.drag_node, Some(30));
2816 self.nodes[self.drag_context.drag_preview].set_opacity(Some(0.5));
2817
2818 let mut stack = vec![self.drag_context.drag_preview];
2820 while let Some(handle) = stack.pop() {
2821 let preview_node = &mut self.nodes[handle];
2822 preview_node.hit_test_visibility.set_value_silent(false);
2823 stack.extend_from_slice(preview_node.children());
2824 }
2825
2826 self.drag_context.is_dragging = true;
2827
2828 self.post(
2829 self.picked_node,
2830 WidgetMessage::DragStarted(self.drag_context.drag_node),
2831 );
2832
2833 self.cursor_icon = CursorIcon::Crosshair;
2834 }
2835
2836 if self.drag_context.is_dragging
2837 && self.nodes.is_valid_handle(self.drag_context.drag_preview)
2838 {
2839 let local_position = self.screen_to_root_canvas_space(*position);
2840 self.send(
2841 self.drag_context.drag_preview,
2842 WidgetMessage::DesiredPosition(local_position),
2843 );
2844 }
2845
2846 if self.picked_node != self.prev_picked_node && self.prev_picked_node.is_some() {
2848 let prev_picked_node = self.nodes.borrow_mut(self.prev_picked_node);
2849 if prev_picked_node.is_mouse_directly_over {
2850 prev_picked_node.is_mouse_directly_over = false;
2851 self.post(self.prev_picked_node, WidgetMessage::MouseLeave);
2852 }
2853 }
2854
2855 if self.picked_node.is_some() {
2856 let picked_node = self.nodes.borrow_mut(self.picked_node);
2857 if !picked_node.is_mouse_directly_over {
2858 picked_node.is_mouse_directly_over = true;
2859 self.post(self.picked_node, WidgetMessage::MouseEnter);
2860 }
2861
2862 self.post(
2864 self.picked_node,
2865 WidgetMessage::MouseMove {
2866 pos: self.cursor_position,
2867 state: self.mouse_state,
2868 },
2869 );
2870
2871 if self.drag_context.is_dragging {
2872 self.post(
2873 self.picked_node,
2874 WidgetMessage::DragOver(self.drag_context.drag_node),
2875 );
2876 }
2877
2878 event_processed = true;
2879 }
2880 }
2881 OsEvent::MouseWheel(_, y) => {
2882 if self.picked_node.is_some() {
2883 self.post(
2884 self.picked_node,
2885 WidgetMessage::MouseWheel {
2886 pos: self.cursor_position,
2887 amount: *y,
2888 },
2889 );
2890
2891 event_processed = true;
2892 }
2893 }
2894 OsEvent::KeyboardInput {
2895 button,
2896 state,
2897 text,
2898 } => {
2899 if let Ok(keyboard_focus_node) = self.try_get_node(self.keyboard_focus_node) {
2900 if keyboard_focus_node.is_globally_visible() {
2901 match state {
2902 ButtonState::Pressed => {
2903 self.post(
2904 self.keyboard_focus_node,
2905 WidgetMessage::KeyDown(*button),
2906 );
2907
2908 if !text.is_empty() {
2909 self.post(
2910 self.keyboard_focus_node,
2911 WidgetMessage::Text(text.clone()),
2912 );
2913 }
2914 }
2915 ButtonState::Released => {
2916 self.post(self.keyboard_focus_node, WidgetMessage::KeyUp(*button))
2917 }
2918 }
2919
2920 event_processed = true;
2921 }
2922 }
2923 }
2924 &OsEvent::KeyboardModifiers(modifiers) => {
2925 self.keyboard_modifiers = modifiers;
2927 }
2928 OsEvent::Touch {
2929 phase,
2930 location,
2931 force,
2932 id,
2933 } => match phase {
2934 TouchPhase::Started => {
2935 self.cursor_position = *location;
2936 let picked_changed =
2937 self.try_set_picked_node(self.hit_test(self.cursor_position));
2938
2939 let mut emit_double_tap = false;
2940 if !picked_changed {
2941 match self.double_click_entries.entry(MouseButton::Left) {
2942 Entry::Occupied(e) => {
2943 let entry = e.into_mut();
2944 if entry.timer > 0.0 {
2945 entry.click_count += 1;
2946 if entry.click_count >= 2 {
2947 entry.click_count = 0;
2948 entry.timer = self.double_click_time_slice;
2949 emit_double_tap = true;
2950 }
2951 } else {
2952 entry.timer = self.double_click_time_slice;
2953 entry.click_count = 1;
2954 }
2955 }
2956 Entry::Vacant(entry) => {
2957 entry.insert(DoubleClickEntry {
2960 timer: self.double_click_time_slice,
2961 click_count: 1,
2962 });
2963 }
2964 }
2965 }
2966
2967 if self.picked_node.is_some() {
2969 self.stack.clear();
2970 self.stack.push(self.picked_node);
2971 while let Some(handle) = self.stack.pop() {
2972 let node = &self.nodes[handle];
2973 if node.is_drag_allowed() {
2974 self.drag_context.drag_node = handle;
2975 self.stack.clear();
2976 break;
2977 } else if node.parent().is_some() {
2978 self.stack.push(node.parent());
2979 }
2980 }
2981 self.drag_context.click_pos = self.cursor_position;
2982 }
2983
2984 self.request_focus(self.picked_node);
2985
2986 if self.picked_node.is_some() {
2987 self.post(
2988 self.picked_node,
2989 WidgetMessage::TouchStarted {
2990 pos: self.cursor_position,
2991 force: *force,
2992 id: *id,
2993 },
2994 );
2995 event_processed = true;
2996 }
2997
2998 if emit_double_tap {
3000 self.post(
3001 self.picked_node,
3002 WidgetMessage::DoubleTap {
3003 pos: *location,
3004 force: *force,
3005 id: *id,
3006 },
3007 );
3008 }
3009 }
3010 TouchPhase::Moved => {
3011 self.cursor_position = *location;
3012 self.try_set_picked_node(self.hit_test(self.cursor_position));
3013
3014 if self.picked_node.is_some() {
3016 self.stack.clear();
3017 self.stack.push(self.picked_node);
3018 while let Some(handle) = self.stack.pop() {
3019 let node = &self.nodes[handle];
3020 if node.is_drag_allowed() {
3021 self.drag_context.drag_node = handle;
3022 self.stack.clear();
3023 break;
3024 } else if node.parent().is_some() {
3025 self.stack.push(node.parent());
3026 }
3027 }
3028 self.drag_context.click_pos = self.cursor_position;
3029 }
3030
3031 self.request_focus(self.picked_node);
3032
3033 if self.picked_node.is_some() {
3034 self.post(
3035 self.picked_node,
3036 WidgetMessage::TouchMoved {
3037 pos: self.cursor_position,
3038 force: *force,
3039 id: *id,
3040 },
3041 );
3042 event_processed = true;
3043 }
3044 }
3045 TouchPhase::Ended => {
3046 if self.picked_node.is_some() {
3047 self.post(
3048 self.picked_node,
3049 WidgetMessage::TouchEnded {
3050 pos: self.cursor_position,
3051 id: *id,
3052 },
3053 );
3054
3055 if self.drag_context.is_dragging {
3056 self.drag_context.is_dragging = false;
3057
3058 self.stack.clear();
3060 self.stack.push(self.picked_node);
3061 while let Some(handle) = self.stack.pop() {
3062 let node = &self.nodes[handle];
3063 if node.is_drop_allowed() {
3064 self.post(
3065 handle,
3066 WidgetMessage::Drop(self.drag_context.drag_node),
3067 );
3068 self.stack.clear();
3069 break;
3070 } else if node.parent().is_some() {
3071 self.stack.push(node.parent());
3072 }
3073 }
3074 }
3075 self.drag_context.drag_node = Handle::NONE;
3076 if self.nodes.is_valid_handle(self.drag_context.drag_preview) {
3077 self.remove_node(self.drag_context.drag_preview);
3078 self.drag_context.drag_preview = Default::default();
3079 }
3080
3081 event_processed = true;
3082 }
3083 }
3084 TouchPhase::Cancelled => {
3085 if self.picked_node.is_some() {
3086 self.post(
3087 self.picked_node,
3088 WidgetMessage::TouchCancelled {
3089 pos: self.cursor_position,
3090 id: *id,
3091 },
3092 );
3093
3094 if self.drag_context.is_dragging {
3095 self.drag_context.is_dragging = false;
3096 self.cursor_icon = CursorIcon::Default;
3097 self.stack.clear();
3098 }
3099 self.drag_context.drag_node = Handle::NONE;
3100 if self.nodes.is_valid_handle(self.drag_context.drag_preview) {
3101 self.remove_node(self.drag_context.drag_preview);
3102 self.drag_context.drag_preview = Default::default();
3103 }
3104
3105 event_processed = true;
3106 }
3107 }
3108 },
3109 }
3110
3111 self.prev_picked_node = self.picked_node;
3112
3113 let on_os_event_subs = std::mem::take(&mut self.methods_registry.handle_os_event);
3114
3115 for &handle in on_os_event_subs.iter() {
3116 let (ticket, mut node) = self.nodes.take_reserve(handle);
3117 node.handle_os_event(handle, self, event);
3118 self.nodes.put_back(ticket, node);
3119 }
3120
3121 self.methods_registry.handle_os_event = on_os_event_subs;
3122
3123 event_processed
3124 }
3125
3126 pub fn nodes(&self) -> &Pool<UiNode, WidgetContainer> {
3127 &self.nodes
3128 }
3129
3130 pub fn root(&self) -> Handle<UiNode> {
3131 self.root_canvas
3132 }
3133
3134 #[inline]
3138 pub fn take_reserve(&mut self, handle: Handle<UiNode>) -> (Ticket<UiNode>, UiNode) {
3139 self.isolate_node(handle);
3140 self.nodes.take_reserve(handle)
3141 }
3142
3143 #[inline]
3145 pub fn put_back(&mut self, ticket: Ticket<UiNode>, node: UiNode) -> Handle<UiNode> {
3146 let handle = self.nodes.put_back(ticket, node);
3147 self.link_nodes(handle, self.root_canvas, false);
3148 handle
3149 }
3150
3151 #[inline]
3153 pub fn forget_ticket(&mut self, ticket: Ticket<UiNode>, node: UiNode) -> UiNode {
3154 self.nodes.forget_ticket(ticket);
3155 node
3156 }
3157
3158 #[inline]
3163 pub fn take_reserve_sub_graph(&mut self, root: Handle<UiNode>) -> SubGraph {
3164 let mut descendants = Vec::new();
3166 let root_ref = &mut self.nodes[root];
3167 let mut stack = root_ref.children().to_vec();
3168 let parent = root_ref.parent;
3169 while let Some(handle) = stack.pop() {
3170 stack.extend_from_slice(self.nodes[handle].children());
3171 descendants.push(self.nodes.take_reserve(handle));
3172 }
3173
3174 SubGraph {
3175 root: self.take_reserve(root),
3177 descendants,
3178 parent,
3179 }
3180 }
3181
3182 #[inline]
3185 pub fn put_sub_graph_back(&mut self, sub_graph: SubGraph) -> Handle<UiNode> {
3186 for (ticket, node) in sub_graph.descendants {
3187 self.nodes.put_back(ticket, node);
3188 }
3189
3190 let (ticket, node) = sub_graph.root;
3191 let root_handle = self.put_back(ticket, node);
3192
3193 self.link_nodes(root_handle, sub_graph.parent, false);
3194
3195 root_handle
3196 }
3197
3198 #[inline]
3200 pub fn forget_sub_graph(&mut self, sub_graph: SubGraph) {
3201 for (ticket, _) in sub_graph.descendants {
3202 self.nodes.forget_ticket(ticket);
3203 }
3204 let (ticket, _) = sub_graph.root;
3205 self.nodes.forget_ticket(ticket);
3206 }
3207
3208 pub fn restricts_picking(&self, node: Handle<UiNode>) -> bool {
3209 self.picking_stack.iter().any(|e| e.handle == node)
3210 }
3211
3212 pub fn push_picking_restriction(&mut self, restriction: RestrictionEntry) {
3213 if let Some(top) = self.top_picking_restriction() {
3214 assert_ne!(top.handle, restriction.handle);
3215 }
3216 self.picking_stack.push(restriction);
3217 }
3218
3219 pub fn remove_picking_restriction(&mut self, node: Handle<UiNode>) {
3220 if let Some(pos) = self.picking_stack.iter().position(|h| h.handle == node) {
3221 self.picking_stack.remove(pos);
3222 }
3223 }
3224
3225 pub fn picking_restriction_stack(&self) -> &[RestrictionEntry] {
3226 &self.picking_stack
3227 }
3228
3229 pub fn drop_picking_restrictions(&mut self) {
3231 self.picking_stack.clear();
3232 }
3233
3234 pub fn top_picking_restriction(&self) -> Option<RestrictionEntry> {
3235 self.picking_stack.last().cloned()
3236 }
3237
3238 pub fn drag_context(&self) -> &DragContext {
3239 &self.drag_context
3240 }
3241
3242 #[inline]
3244 pub fn link_nodes(
3245 &mut self,
3246 child_handle: Handle<impl ObjectOrVariant<UiNode>>,
3247 parent_handle: Handle<impl ObjectOrVariant<UiNode>>,
3248 in_front: bool,
3249 ) {
3250 let child_handle = child_handle.to_base();
3251 let parent_handle = parent_handle.to_base();
3252 assert_ne!(child_handle, parent_handle);
3253 self.isolate_node(child_handle);
3254 self.nodes[child_handle].set_parent(parent_handle);
3255 self.nodes[parent_handle].add_child(child_handle, in_front);
3256 }
3257
3258 #[inline]
3259 pub fn node_mut(&mut self, node_handle: Handle<UiNode>) -> &mut UiNode {
3260 self.nodes.borrow_mut(node_handle)
3261 }
3262
3263 #[inline]
3264 pub fn try_get_node_mut(
3265 &mut self,
3266 node_handle: Handle<UiNode>,
3267 ) -> Result<&mut UiNode, PoolError> {
3268 self.nodes.try_borrow_mut(node_handle)
3269 }
3270
3271 pub fn copy_node(&mut self, node: Handle<UiNode>) -> Handle<UiNode> {
3272 let mut old_new_mapping = NodeHandleMap::default();
3273
3274 let root = self.copy_node_recursive(node, &mut old_new_mapping);
3275
3276 remap_handles(&old_new_mapping, self);
3277
3278 root
3279 }
3280
3281 #[allow(clippy::unnecessary_to_owned)] fn copy_node_recursive(
3283 &mut self,
3284 node_handle: Handle<UiNode>,
3285 old_new_mapping: &mut NodeHandleMap<UiNode>,
3286 ) -> Handle<UiNode> {
3287 let node = self.nodes.borrow(node_handle);
3288 let mut cloned = UiNode(node.clone_boxed());
3289 cloned.id = Uuid::new_v4();
3290
3291 let mut cloned_children = Vec::new();
3292 for child in node.children().to_vec() {
3293 cloned_children.push(self.copy_node_recursive(child, old_new_mapping));
3294 }
3295
3296 cloned.set_children(cloned_children);
3297 let copy_handle = self.add_node(cloned);
3298 old_new_mapping.insert(node_handle, copy_handle);
3299 copy_handle
3300 }
3301
3302 pub fn copy_node_to<Post>(
3303 &self,
3304 node: Handle<UiNode>,
3305 dest: &mut UserInterface,
3306 post_process_callback: &mut Post,
3307 ) -> (Handle<UiNode>, NodeHandleMap<UiNode>)
3308 where
3309 Post: FnMut(Handle<UiNode>, Handle<UiNode>, &mut UiNode),
3310 {
3311 let mut old_new_mapping = NodeHandleMap::default();
3312
3313 let root =
3314 self.copy_node_to_recursive(node, dest, &mut old_new_mapping, post_process_callback);
3315
3316 remap_handles(&old_new_mapping, dest);
3317
3318 (root, old_new_mapping)
3319 }
3320
3321 fn copy_node_to_recursive<Post>(
3322 &self,
3323 node_handle: Handle<UiNode>,
3324 dest: &mut UserInterface,
3325 old_new_mapping: &mut NodeHandleMap<UiNode>,
3326 post_process_callback: &mut Post,
3327 ) -> Handle<UiNode>
3328 where
3329 Post: FnMut(Handle<UiNode>, Handle<UiNode>, &mut UiNode),
3330 {
3331 let node = self.nodes.borrow(node_handle);
3332 let children = node.children.clone();
3333
3334 let mut cloned = UiNode(node.clone_boxed());
3335 cloned.children.clear();
3336 cloned.parent = Handle::NONE;
3337 cloned.id = Uuid::new_v4();
3338 let cloned_node_handle = dest.add_node(cloned);
3339
3340 for child in children {
3341 let cloned_child_node_handle =
3342 self.copy_node_to_recursive(child, dest, old_new_mapping, post_process_callback);
3343 dest.link_nodes(cloned_child_node_handle, cloned_node_handle, false);
3344 }
3345
3346 old_new_mapping.insert(node_handle, cloned_node_handle);
3347
3348 post_process_callback(
3349 cloned_node_handle,
3350 node_handle,
3351 dest.try_get_node_mut(cloned_node_handle).unwrap(),
3352 );
3353
3354 cloned_node_handle
3355 }
3356
3357 pub fn copy_node_with_limit(
3358 &mut self,
3359 node: Handle<UiNode>,
3360 limit: Option<usize>,
3361 ) -> Handle<UiNode> {
3362 let mut old_new_mapping = NodeHandleMap::default();
3363 let mut counter = 0;
3364
3365 let root =
3366 self.copy_node_recursive_with_limit(node, &mut old_new_mapping, limit, &mut counter);
3367
3368 remap_handles(&old_new_mapping, self);
3369
3370 root
3371 }
3372
3373 #[allow(clippy::unnecessary_to_owned)] fn copy_node_recursive_with_limit(
3375 &mut self,
3376 node_handle: Handle<UiNode>,
3377 old_new_mapping: &mut NodeHandleMap<UiNode>,
3378 limit: Option<usize>,
3379 counter: &mut usize,
3380 ) -> Handle<UiNode> {
3381 if let Some(limit) = limit {
3382 if *counter >= limit {
3383 return Default::default();
3384 }
3385 }
3386
3387 let Ok(node) = self.nodes.try_borrow(node_handle) else {
3388 return Default::default();
3389 };
3390
3391 let mut cloned = UiNode(node.clone_boxed());
3392 cloned.id = Uuid::new_v4();
3393
3394 let mut cloned_children = Vec::new();
3395 for child in node.children().to_vec() {
3396 let cloned_child =
3397 self.copy_node_recursive_with_limit(child, old_new_mapping, limit, counter);
3398 if cloned_child.is_some() {
3399 cloned_children.push(cloned_child);
3400 } else {
3401 break;
3402 }
3403 }
3404
3405 cloned.set_children(cloned_children);
3406 let copy_handle = self.add_node(cloned);
3407 old_new_mapping.insert(node_handle, copy_handle);
3408
3409 *counter += 1;
3410
3411 copy_handle
3412 }
3413
3414 pub fn save(&mut self, path: &Path) -> Result<Visitor, VisitError> {
3415 let mut visitor = Visitor::new();
3416 self.visit("Ui", &mut visitor)?;
3417 visitor.save_ascii_to_file(path)?;
3418 Ok(visitor)
3419 }
3420
3421 #[allow(clippy::arc_with_non_send_sync)]
3422 pub async fn load_from_file<P: AsRef<Path>>(
3423 path: P,
3424 constructors: Arc<WidgetConstructorContainer>,
3425 dyn_type_constructors: Arc<DynTypeConstructorContainer>,
3426 resource_manager: ResourceManager,
3427 ) -> Result<Self, VisitError> {
3428 Self::load_from_file_ex(
3429 path,
3430 constructors,
3431 dyn_type_constructors,
3432 resource_manager,
3433 &FsResourceIo,
3434 )
3435 .await
3436 }
3437
3438 fn restore_dynamic_node_data(&mut self) {
3439 for (handle, widget) in self.nodes.pair_iter_mut() {
3440 widget.handle = handle;
3441 widget.layout_events_sender = Some(self.layout_events_sender.clone());
3442 widget.invalidate_layout();
3443 widget.notify_z_index_changed();
3444 }
3445 }
3446
3447 pub fn resolve(&mut self) {
3448 self.restore_dynamic_node_data();
3449 self.restore_original_handles_and_inherit_properties(&[], |_, _| {});
3450 self.update_visual_transform(self.root_canvas);
3451 self.update_global_visibility(self.root_canvas);
3452 let instances = self.restore_integrity(|model, model_data, handle, dest_graph| {
3453 model_data.copy_node_to(handle, dest_graph, &mut |_, original_handle, node| {
3454 node.set_inheritance_data(original_handle, model.clone());
3455 })
3456 });
3457 self.remap_handles(&instances);
3458 }
3459
3460 pub fn collect_used_resources(&self) -> FxHashSet<UntypedResource> {
3464 let mut collection = FxHashSet::default();
3465 fyrox_resource::collect_used_resources(self, &mut collection);
3466 collection
3467 }
3468
3469 #[allow(clippy::arc_with_non_send_sync)]
3470 pub async fn load_from_file_ex<P: AsRef<Path>>(
3471 path: P,
3472 constructors: Arc<WidgetConstructorContainer>,
3473 dyn_type_constructors: Arc<DynTypeConstructorContainer>,
3474 resource_manager: ResourceManager,
3475 io: &dyn ResourceIo,
3476 ) -> Result<Self, VisitError> {
3477 if !resource_manager.registry_is_loaded().await {
3478 return Err("The resource registry is unavailable!".to_string().into());
3479 }
3480 let mut ui = {
3481 let mut visitor = Visitor::load_from_memory(&io.load_file(path.as_ref()).await?)?;
3482 let (sender, receiver) = mpsc::channel();
3483 visitor.blackboard.register(constructors);
3484 visitor.blackboard.register(Arc::new(sender.clone()));
3485 visitor.blackboard.register(Arc::new(resource_manager));
3486 visitor.blackboard.register(dyn_type_constructors);
3487 let mut ui =
3488 UserInterface::new_with_channel(sender, receiver, Vector2::new(100.0, 100.0));
3489 ui.visit("Ui", &mut visitor)?;
3490 ui
3491 };
3492
3493 Log::info("UserInterface - Collecting resources used by the scene...");
3494
3495 let used_resources = ui.collect_used_resources();
3496
3497 let used_resources_count = used_resources.len();
3498
3499 Log::info(format!(
3500 "UserInterface - {used_resources_count} resources collected. Waiting them to load..."
3501 ));
3502
3503 join_all(used_resources.into_iter()).await;
3505
3506 ui.resolve();
3507
3508 Ok(ui)
3509 }
3510}
3511
3512impl PrefabData for UserInterface {
3513 type Graph = Self;
3514
3515 #[inline]
3516 fn graph(&self) -> &Self::Graph {
3517 self
3518 }
3519
3520 #[inline]
3521 fn mapping(&self) -> NodeMapping {
3522 NodeMapping::UseHandles
3523 }
3524}
3525
3526impl SceneGraph for UserInterface {
3527 type Prefab = Self;
3528 type NodeContainer = WidgetContainer;
3529 type Node = UiNode;
3530
3531 fn summary(&self) -> String {
3532 let mut result = String::new();
3533 self.recursive_summary(0, self.root_canvas, &mut result);
3534 result
3535 }
3536
3537 #[inline]
3538 fn actual_type_id(&self, handle: Handle<Self::Node>) -> Result<TypeId, PoolError> {
3539 self.nodes
3540 .try_borrow(handle)
3541 .map(|n| ControlAsAny::as_any(n.0.deref()).type_id())
3542 }
3543
3544 fn actual_type_name(&self, handle: Handle<Self::Node>) -> Result<&'static str, PoolError> {
3545 self.nodes
3546 .try_borrow(handle)
3547 .map(|n| Reflect::type_name(n.0.deref()))
3548 }
3549
3550 fn derived_type_ids(&self, handle: Handle<Self::Node>) -> Result<Vec<TypeId>, PoolError> {
3551 self.nodes
3552 .try_borrow(handle)
3553 .map(|n| n.0.query_derived_types().to_vec())
3554 }
3555
3556 #[inline]
3557 fn root(&self) -> Handle<Self::Node> {
3558 self.root_canvas
3559 }
3560
3561 #[inline]
3562 fn set_root(&mut self, root: Handle<Self::Node>) {
3563 self.root_canvas = root;
3564 }
3565
3566 #[inline]
3567 fn try_get_node(&self, handle: Handle<Self::Node>) -> Result<&Self::Node, PoolError> {
3568 self.nodes.try_borrow(handle)
3569 }
3570
3571 #[inline]
3572 fn try_get_node_mut(
3573 &mut self,
3574 handle: Handle<Self::Node>,
3575 ) -> Result<&mut Self::Node, PoolError> {
3576 self.nodes.try_borrow_mut(handle)
3577 }
3578
3579 #[inline]
3580 fn is_valid_handle(&self, handle: Handle<impl ObjectOrVariant<Self::Node>>) -> bool {
3581 self.nodes.is_valid_handle(handle)
3582 }
3583
3584 #[inline]
3585 fn add_node(&mut self, node: Self::Node) -> Handle<Self::Node> {
3586 let handle = self.nodes.next_free_handle();
3587 self.add_node_at_handle(node, handle);
3588 handle
3589 }
3590
3591 fn add_node_at_handle(&mut self, mut node: Self::Node, node_handle: Handle<Self::Node>) {
3592 let children = node.children().to_vec();
3593 node.clear_children();
3594 self.nodes
3595 .spawn_at_handle(node_handle, node)
3596 .expect("The handle must be valid!");
3597 if self.root_canvas.is_some() {
3598 self.link_nodes(node_handle, self.root_canvas, false);
3599 }
3600 for child in children {
3601 self.link_nodes(child, node_handle, false)
3602 }
3603 let node = self.nodes[node_handle].deref_mut();
3604 node.layout_events_sender = Some(self.layout_events_sender.clone());
3605 node.handle = node_handle;
3606 self.methods_registry.register(node);
3607 node.invalidate_layout();
3608 node.notify_z_index_changed();
3609 self.layout_events_sender
3610 .send(LayoutEvent::VisibilityChanged(node_handle))
3611 .unwrap();
3612 }
3613
3614 #[inline]
3615 fn remove_node(&mut self, node: Handle<impl ObjectOrVariant<Self::Node>>) {
3616 let node = node.to_base();
3617 self.isolate_node(node);
3618
3619 let sender = self.sender.clone();
3620 let mut stack = vec![node];
3621 while let Some(handle) = stack.pop() {
3622 if self.prev_picked_node == handle {
3623 self.prev_picked_node = Handle::NONE;
3624 }
3625 if self.picked_node == handle {
3626 self.try_set_picked_node(Handle::NONE);
3627 }
3628 if self.captured_node == handle {
3629 self.captured_node = Handle::NONE;
3630 }
3631 if self.keyboard_focus_node == handle {
3632 self.keyboard_focus_node = Handle::NONE;
3633 }
3634 self.remove_picking_restriction(handle);
3635
3636 let node_ref = self.nodes.borrow(handle);
3637 stack.extend_from_slice(node_ref.children());
3638
3639 node_ref.on_remove(&sender);
3642
3643 self.methods_registry.unregister(node_ref.deref());
3644 self.nodes.free(handle);
3645 }
3646 }
3647
3648 #[inline]
3649 fn link_nodes(
3650 &mut self,
3651 child: Handle<impl ObjectOrVariant<Self::Node>>,
3652 parent: Handle<impl ObjectOrVariant<Self::Node>>,
3653 ) {
3654 self.link_nodes(child.to_base(), parent.to_base(), false)
3655 }
3656
3657 #[inline]
3658 fn unlink_node(&mut self, node_handle: Handle<impl ObjectOrVariant<Self::Node>>) {
3659 self.isolate_node(node_handle);
3660 self.link_nodes(node_handle, self.root_canvas, false);
3661 }
3662
3663 #[inline]
3664 fn isolate_node(&mut self, node_handle: Handle<impl ObjectOrVariant<Self::Node>>) {
3665 let node_handle = node_handle.to_base();
3666 let node = self.nodes.borrow_mut(node_handle);
3667 let parent_handle = node.parent();
3668 if parent_handle.is_some() {
3669 node.set_parent(Handle::NONE);
3670
3671 self.nodes[parent_handle].remove_child(node_handle);
3673 }
3674 }
3675
3676 #[inline]
3677 fn pair_iter(&self) -> impl Iterator<Item = (Handle<Self::Node>, &Self::Node)> {
3678 self.nodes.pair_iter()
3679 }
3680
3681 #[inline]
3682 fn linear_iter(&self) -> impl Iterator<Item = &Self::Node> {
3683 self.nodes.iter()
3684 }
3685
3686 #[inline]
3687 fn linear_iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Node> {
3688 self.nodes.iter_mut()
3689 }
3690
3691 fn try_get<U: ObjectOrVariant<UiNode>>(&self, handle: Handle<U>) -> Result<&U, PoolError> {
3692 self.nodes.try_get(handle)
3693 }
3694
3695 fn try_get_mut<U: ObjectOrVariant<UiNode>>(
3696 &mut self,
3697 handle: Handle<U>,
3698 ) -> Result<&mut U, PoolError> {
3699 self.nodes.try_get_mut(handle)
3700 }
3701}
3702
3703pub trait UserInterfaceResourceExtension {
3704 fn instantiate(&self, ui: &mut UserInterface) -> (Handle<UiNode>, NodeHandleMap<UiNode>);
3705}
3706
3707impl UserInterfaceResourceExtension for Resource<UserInterface> {
3708 fn instantiate(&self, ui: &mut UserInterface) -> (Handle<UiNode>, NodeHandleMap<UiNode>) {
3709 let resource = self.clone();
3710 let mut data = self.state();
3711 let data = data.data().expect("The resource must be loaded!");
3712
3713 let (root, mapping) =
3714 data.copy_node_to(data.root_canvas, ui, &mut |_, original_handle, node| {
3715 node.set_inheritance_data(original_handle, resource.clone());
3716 });
3717
3718 ui.node_mut(root).is_resource_instance_root = true;
3720
3721 (root, mapping)
3722 }
3723}
3724
3725fn is_approx_zero(v: f32) -> bool {
3726 v.abs() <= 10.0 * f32::EPSILON
3727}
3728
3729fn are_close(value1: f32, value2: f32) -> bool {
3730 if value1 == value2 {
3732 return true;
3733 }
3734 let eps = (value1.abs() + value2.abs() + 10.0) * f32::EPSILON;
3736 let delta = value1 - value2;
3737 (-eps < delta) && (eps > delta)
3738}
3739
3740fn greater_than_or_close(value1: f32, value2: f32) -> bool {
3741 (value1 > value2) || are_close(value1, value2)
3742}
3743
3744fn less_than_or_close(value1: f32, value2: f32) -> bool {
3745 (value1 < value2) || are_close(value1, value2)
3746}
3747
3748fn transform_size(transform_space_bounds: Vector2<f32>, matrix: &Matrix3<f32>) -> Vector2<f32> {
3758 let mut x_constr: f32 = transform_space_bounds.x;
3760 let mut y_constr: f32 = transform_space_bounds.y;
3761
3762 if is_approx_zero(x_constr) || is_approx_zero(y_constr) {
3764 return Vector2::new(0.0, 0.0);
3765 }
3766
3767 let x_constr_infinite = x_constr.is_infinite();
3768 let y_constr_infinite = y_constr.is_infinite();
3769
3770 if x_constr_infinite && y_constr_infinite {
3771 return Vector2::new(f32::INFINITY, f32::INFINITY);
3772 } else if x_constr_infinite
3773 {
3775 x_constr = y_constr;
3776 } else if y_constr_infinite {
3777 y_constr = x_constr;
3778 }
3779
3780 if !matrix.is_invertible() {
3783 return Vector2::new(0.0, 0.0);
3784 }
3785
3786 let a = matrix[(0, 0)];
3787 let b = matrix[(0, 1)];
3788 let c = matrix[(1, 0)];
3789 let d = matrix[(1, 1)];
3790
3791 let mut w;
3793 let mut h;
3794
3795 if is_approx_zero(b) || is_approx_zero(c) {
3799 let y_cover_d = if y_constr_infinite {
3802 f32::INFINITY
3803 } else {
3804 (y_constr / d).abs()
3805 };
3806 let x_cover_a = if x_constr_infinite {
3807 f32::INFINITY
3808 } else {
3809 (x_constr / a).abs()
3810 };
3811
3812 if is_approx_zero(b) {
3813 if is_approx_zero(c) {
3814 h = y_cover_d;
3819 w = x_cover_a;
3820 } else {
3821 h = (0.5 * (x_constr / c).abs()).min(y_cover_d);
3827 w = x_cover_a - ((c * h) / a);
3828 }
3829 } else {
3830 w = (0.5 * (y_constr / b).abs()).min(x_cover_a);
3836 h = y_cover_d - ((b * w) / d);
3837 }
3838 } else if is_approx_zero(a) || is_approx_zero(d) {
3839 let y_cover_b = (y_constr / b).abs();
3842 let x_cover_c = (x_constr / c).abs();
3843
3844 if is_approx_zero(a) {
3845 if is_approx_zero(d) {
3846 h = x_cover_c;
3851 w = y_cover_b;
3852 } else {
3853 h = (0.5 * (y_constr / d).abs()).min(x_cover_c);
3859 w = y_cover_b - ((d * h) / b);
3860 }
3861 } else {
3862 w = (0.5 * (x_constr / a).abs()).min(y_cover_b);
3868 h = x_cover_c - ((a * w) / c);
3869 }
3870 } else {
3871 let x_cover_a = (x_constr / a).abs(); let x_cover_c = (x_constr / c).abs(); let y_cover_b = (y_constr / b).abs(); let y_cover_d = (y_constr / d).abs(); w = y_cover_b.min(x_cover_a) * 0.5;
3883 h = x_cover_c.min(y_cover_d) * 0.5;
3884
3885 if (greater_than_or_close(x_cover_a, y_cover_b) && less_than_or_close(x_cover_c, y_cover_d))
3886 || (less_than_or_close(x_cover_a, y_cover_b)
3887 && greater_than_or_close(x_cover_c, y_cover_d))
3888 {
3889 let child_bounds_tr = Rect::new(0.0, 0.0, w, h).transform(matrix);
3898 let expand_factor =
3899 (x_constr / child_bounds_tr.size.x).min(y_constr / child_bounds_tr.size.y);
3900
3901 if !expand_factor.is_nan() && !expand_factor.is_infinite() {
3902 w *= expand_factor;
3903 h *= expand_factor;
3904 }
3905 }
3906 }
3907
3908 Vector2::new(w, h)
3909}
3910
3911uuid_provider!(UserInterface = "0d065c93-ef9c-4dd2-9fe7-e2b33c1a21b6");
3912
3913impl ResourceData for UserInterface {
3914 fn type_uuid(&self) -> Uuid {
3915 <Self as TypeUuidProvider>::type_uuid()
3916 }
3917
3918 fn save(&mut self, path: &Path) -> Result<(), Box<dyn Error>> {
3919 self.save(path)?;
3920 Ok(())
3921 }
3922
3923 fn can_be_saved(&self) -> bool {
3924 true
3925 }
3926
3927 fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
3928 Some(Box::new(self.clone()))
3929 }
3930}
3931
3932#[cfg(test)]
3933mod test_inner {
3934 use crate::message::UiMessage;
3935 use crate::{
3936 border::BorderBuilder,
3937 core::algebra::{Rotation2, UnitComplex, Vector2},
3938 message::{ButtonState, KeyCode},
3939 text_box::TextBoxBuilder,
3940 transform_size,
3941 widget::{WidgetBuilder, WidgetMessage},
3942 OsEvent, UserInterface,
3943 };
3944
3945 #[test]
3946 fn test_transform_size() {
3947 let input = Vector2::new(100.0, 100.0);
3948 let transform =
3949 Rotation2::from(UnitComplex::from_angle(45.0f32.to_radians())).to_homogeneous();
3950 let transformed = transform_size(input, &transform);
3951 dbg!(input, transformed);
3952 }
3953
3954 #[test]
3955 fn center() {
3956 let screen_size = Vector2::new(1000.0, 1000.0);
3957 let widget_size = Vector2::new(100.0, 100.0);
3958 let mut ui = UserInterface::new(screen_size);
3959 let widget = BorderBuilder::new(
3960 WidgetBuilder::new()
3961 .with_width(widget_size.x)
3962 .with_height(widget_size.y),
3963 )
3964 .build(&mut ui.build_ctx());
3965 ui.update(screen_size, 0.0, &Default::default()); ui.send(widget, WidgetMessage::Center);
3967 while ui.poll_message().is_some() {}
3968 ui.update(screen_size, 0.0, &Default::default());
3969 let expected_position = (screen_size - widget_size).scale(0.5);
3970 let actual_position = ui[widget].actual_local_position();
3971 assert_eq!(actual_position, expected_position);
3972 }
3973
3974 #[test]
3975 fn test_keyboard_focus() {
3976 let screen_size = Vector2::new(1000.0, 1000.0);
3977 let mut ui = UserInterface::new(screen_size);
3978
3979 let text_box = TextBoxBuilder::new(WidgetBuilder::new()).build(&mut ui.build_ctx());
3980
3981 ui.update(screen_size, 0.0, &Default::default());
3983
3984 assert!(ui.poll_message().is_none());
3985
3986 ui.send(text_box, WidgetMessage::Focus);
3987
3988 assert_eq!(
3990 ui.poll_message(),
3991 Some(UiMessage::for_widget(text_box, WidgetMessage::Focus))
3992 );
3993 assert_eq!(
3995 ui.poll_message(),
3996 Some(UiMessage::from_widget(ui.root(), WidgetMessage::Unfocus))
3997 );
3998 assert_eq!(
4000 ui.poll_message(),
4001 Some(UiMessage::from_widget(text_box, WidgetMessage::Focus))
4002 );
4003
4004 ui.process_os_event(&OsEvent::KeyboardInput {
4006 button: KeyCode::KeyA,
4007 state: ButtonState::Pressed,
4008 text: "A".to_string(),
4009 });
4010
4011 let msg = UiMessage::from_widget(text_box, WidgetMessage::KeyDown(KeyCode::KeyA));
4012 msg.set_handled(true);
4013 assert_eq!(ui.poll_message(), Some(msg));
4014
4015 assert_eq!(
4016 ui.poll_message(),
4017 Some(UiMessage::from_widget(
4018 text_box,
4019 WidgetMessage::Text('A'.to_string())
4020 ))
4021 );
4022
4023 assert!(ui.poll_message().is_none());
4024 }
4025}