blockworx/shell/
workspace.rs1#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize)]
14pub enum PanelView {
15 History,
16 Hierarchy,
17}
18
19impl PanelView {
20 pub const RAIL: [PanelView; 2] = [PanelView::History, PanelView::Hierarchy];
22
23 pub fn title(self) -> &'static str {
30 match self {
31 PanelView::History => "History",
32 PanelView::Hierarchy => "Hierarchy",
33 }
34 }
35}
36
37#[derive(Clone, Copy, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize)]
40pub enum Panel {
41 Showing,
42 Collapsed,
43}
44
45impl Panel {
46 fn is_showing(self) -> bool {
47 self == Panel::Showing
48 }
49}
50
51impl From<bool> for Panel {
52 fn from(showing: bool) -> Self {
53 if showing {
54 Panel::Showing
55 } else {
56 Panel::Collapsed
57 }
58 }
59}
60
61#[derive(Clone, Copy, PartialEq, Debug, serde::Serialize, serde::Deserialize)]
64pub struct Workspace {
65 pub view: PanelView,
66 pub panel: Panel,
67}
68
69impl Default for Workspace {
70 fn default() -> Self {
71 Workspace {
72 view: PanelView::History,
73 panel: Panel::Collapsed,
74 }
75 }
76}
77
78impl Workspace {
79 pub fn showing(self, view: PanelView) -> bool {
81 self.panel.is_showing() && self.view == view
82 }
83
84 pub fn open(self) -> bool {
86 self.panel.is_showing()
87 }
88
89 pub fn show(&mut self, view: PanelView) {
93 self.view = view;
94 self.panel = Panel::Showing;
95 }
96
97 pub fn close(&mut self) {
99 self.panel = Panel::Collapsed;
100 }
101
102 pub fn toggle(&mut self) {
104 self.panel = (!self.open()).into();
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
115 fn a_segment_switches_the_view_and_never_shuts_the_panel() {
116 let mut state = Workspace::default();
117 assert!(!state.showing(PanelView::History), "opens shut");
118
119 state.show(PanelView::History);
120 assert!(state.showing(PanelView::History));
121
122 state.show(PanelView::Hierarchy);
123 assert!(
124 state.showing(PanelView::Hierarchy) && !state.showing(PanelView::History),
125 "picking another view switched nothing",
126 );
127
128 state.show(PanelView::Hierarchy);
129 assert_eq!(
130 state.panel,
131 Panel::Showing,
132 "the active segment shut the panel from inside it",
133 );
134 }
135
136 #[test]
139 fn the_toggle_reopens_the_view_the_user_left() {
140 let mut state = Workspace::default();
141 state.show(PanelView::Hierarchy);
142 state.toggle();
143 assert!(!state.open(), "the toggle did not shut the panel");
144 state.toggle();
145 assert!(
146 state.showing(PanelView::Hierarchy),
147 "re-opening lost the view the user left",
148 );
149 }
150
151 #[test]
154 fn every_segment_names_a_distinct_view() {
155 let titles: std::collections::HashSet<&str> =
156 PanelView::RAIL.iter().map(|v| v.title()).collect();
157 assert_eq!(titles.len(), PanelView::RAIL.len());
158 }
159}