Skip to main content

ferroui_diagnostics/diagnostics/
i_dev_tools_top_level_group.rs

1//! Port of `Diagnostics/IDevToolsTopLevelGroup.cs`.
2
3use ferroui_base::collections::FerroList;
4use ferroui_base::Ref;
5use ferroui_controls::application_lifetimes::{IApplicationLifetime, IClassicDesktopStyleApplicationLifetime};
6use ferroui_controls::TopLevel;
7use std::any::Any;
8use std::rc::Rc;
9
10/// The top levels DevTools inspects together: the windows of an application, or one top level.
11pub trait IDevToolsTopLevelGroup {
12    /// The top levels of the group.
13    fn items(&self) -> Vec<Ref<TopLevel>>;
14
15    /// `Items is INotifyCollectionChanged`: the observable collection of the top levels when the
16    /// group changes, `None` when it does not.
17    fn observable_items(&self) -> Option<FerroList<Ref<TopLevel>>> {
18        None
19    }
20
21    /// `Equals(object)`: whether `other` is the same group. By default a group is only equal to
22    /// itself.
23    fn equals(&self, other: &dyn IDevToolsTopLevelGroup) -> bool {
24        std::ptr::addr_eq(self as *const Self, other as *const dyn IDevToolsTopLevelGroup)
25    }
26
27    /// The group as its concrete type (`is`/`as`).
28    fn as_any(&self) -> &dyn Any;
29}
30
31impl PartialEq for dyn IDevToolsTopLevelGroup {
32    fn eq(&self, other: &Self) -> bool {
33        self.equals(other)
34    }
35}
36
37/// The windows of an application with a classic desktop lifetime.
38pub struct ClassicDesktopStyleApplicationLifetimeTopLevelGroup {
39    lifetime: Rc<dyn IApplicationLifetime>,
40}
41
42impl ClassicDesktopStyleApplicationLifetimeTopLevelGroup {
43    /// The group of the windows of `lifetime`.
44    ///
45    /// # Panics
46    /// When `lifetime` is not an `IClassicDesktopStyleApplicationLifetime` (the original takes
47    /// one and throws on null).
48    pub fn new(lifetime: Rc<dyn IApplicationLifetime>) -> Self {
49        assert!(
50            lifetime.as_classic_desktop_style_application_lifetime().is_some(),
51            "Value cannot be null. (Parameter 'lifetime')"
52        );
53        Self { lifetime }
54    }
55
56    /// The lifetime of the group.
57    pub fn lifetime(&self) -> &dyn IClassicDesktopStyleApplicationLifetime {
58        self.lifetime
59            .as_classic_desktop_style_application_lifetime()
60            .expect("the lifetime of the group is a classic desktop lifetime")
61    }
62}
63
64impl IDevToolsTopLevelGroup for ClassicDesktopStyleApplicationLifetimeTopLevelGroup {
65    fn items(&self) -> Vec<Ref<TopLevel>> {
66        self.lifetime().windows().into_iter().map(|window| window.upcast()).collect()
67    }
68
69    fn equals(&self, other: &dyn IDevToolsTopLevelGroup) -> bool {
70        other
71            .as_any()
72            .downcast_ref::<Self>()
73            .is_some_and(|g| std::ptr::addr_eq(Rc::as_ptr(&g.lifetime), Rc::as_ptr(&self.lifetime)))
74    }
75
76    fn as_any(&self) -> &dyn Any {
77        self
78    }
79}
80
81/// One top level.
82pub struct SingleViewTopLevelGroup {
83    top_level: Ref<TopLevel>,
84}
85
86impl SingleViewTopLevelGroup {
87    pub fn new(top_level: Ref<TopLevel>) -> Self {
88        Self { top_level }
89    }
90}
91
92impl IDevToolsTopLevelGroup for SingleViewTopLevelGroup {
93    fn items(&self) -> Vec<Ref<TopLevel>> {
94        vec![self.top_level.clone()]
95    }
96
97    fn equals(&self, other: &dyn IDevToolsTopLevelGroup) -> bool {
98        other.as_any().downcast_ref::<Self>().is_some_and(|g| g.top_level == self.top_level)
99    }
100
101    fn as_any(&self) -> &dyn Any {
102        self
103    }
104}