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