Skip to main content

liveplot/app/
panel_helpers.rs

1//! Utility methods for finding and toggling specific sub-panels.
2//!
3//! These helpers iterate over all panel lists (left, right, bottom, detached,
4//! empty) to locate a panel by its concrete type and modify its visibility state.
5//! They are used by the controller modules and the layout/rendering code.
6
7use crate::panels::hotkeys_ui::HotkeysPanel;
8use crate::panels::panel_trait::Panel;
9use crate::panels::thresholds_ui::ThresholdsPanel;
10use crate::panels::traces_ui::TracesPanel;
11
12use super::LivePlotPanel;
13
14impl LivePlotPanel {
15    /// Return a mutable reference to the [`ThresholdsPanel`], if one exists in any panel list.
16    ///
17    /// Searches left → right → bottom → detached → empty panels in order.
18    pub(crate) fn thresholds_panel_mut(&mut self) -> Option<&mut ThresholdsPanel> {
19        for p in self
20            .left_side_panels
21            .iter_mut()
22            .chain(self.right_side_panels.iter_mut())
23            .chain(self.bottom_panels.iter_mut())
24            .chain(self.detached_panels.iter_mut())
25            .chain(self.empty_panels.iter_mut())
26        {
27            if let Some(tp) = p.downcast_mut::<ThresholdsPanel>() {
28                return Some(tp);
29            }
30        }
31        None
32    }
33
34    /// Return a mutable reference to the [`TracesPanel`], if one exists in any panel list.
35    ///
36    /// Searches left → right → bottom → detached → empty panels in order.
37    pub(crate) fn traces_panel_mut(&mut self) -> Option<&mut TracesPanel> {
38        for p in self
39            .left_side_panels
40            .iter_mut()
41            .chain(self.right_side_panels.iter_mut())
42            .chain(self.bottom_panels.iter_mut())
43            .chain(self.detached_panels.iter_mut())
44            .chain(self.empty_panels.iter_mut())
45        {
46            if let Some(tp) = p.downcast_mut::<TracesPanel>() {
47                return Some(tp);
48            }
49        }
50        None
51    }
52
53    /// Toggle the visibility of the first panel of type `T` found in any list.
54    ///
55    /// If the panel is currently visible and attached (not detached), it becomes hidden.
56    /// Otherwise it becomes visible and attached (un-detached).
57    ///
58    /// Returns `true` if a matching panel was found (regardless of whether its
59    /// state actually changed).
60    pub(crate) fn toggle_panel_visibility<T: 'static + Panel>(&mut self) -> bool {
61        for p in self
62            .left_side_panels
63            .iter_mut()
64            .chain(self.right_side_panels.iter_mut())
65            .chain(self.bottom_panels.iter_mut())
66            .chain(self.detached_panels.iter_mut())
67            .chain(self.empty_panels.iter_mut())
68        {
69            if p.downcast_ref::<T>().is_some() {
70                let st = p.state_mut();
71                let currently_shown = st.visible && !st.detached;
72                st.visible = !currently_shown;
73                st.detached = false;
74                return true;
75            }
76        }
77        false
78    }
79
80    /// Hide the Hotkeys panel (useful when focus switches away via hotkeys).
81    pub fn hide_hotkeys_panel(&mut self) {
82        for p in self
83            .left_side_panels
84            .iter_mut()
85            .chain(self.right_side_panels.iter_mut())
86            .chain(self.bottom_panels.iter_mut())
87            .chain(self.detached_panels.iter_mut())
88            .chain(self.empty_panels.iter_mut())
89        {
90            if p.downcast_ref::<HotkeysPanel>().is_some() {
91                p.state_mut().visible = false;
92            }
93        }
94    }
95}