Skip to main content

cursive_split_panel/
split_panel.rs

1use super::{pane::*, which::*};
2
3use cursive::{direction::*, view::*, views::DummyView, *};
4
5//
6// SplitPanel
7//
8
9/// Split panel.
10///
11/// Contains two panes with an optionally movable divider between them and an optional border.
12/// (Both are enabled by default.)
13///
14/// Can be oriented horizontally (the default) or vertically.
15///
16/// When [movable_divider](Self::movable_divider) is true will support the following
17/// events:
18///
19/// * Shift+Left/Shift+Up: move the divider towards the front
20/// * Shift+Right/Shift+Down: move the divider towards the back
21/// * Mouse dragging of the divider
22pub struct SplitPanel {
23    pub(crate) orientation: Orientation,
24    pub(crate) border: bool,
25    pub(crate) movable_divider: bool,
26    pub(crate) front: Pane,
27    pub(crate) back: Pane,
28    pub(crate) divider: Option<usize>,
29    pub(crate) needs_relayout: bool,
30    pub(crate) size: Option<Vec2>,
31    pub(crate) focus: Option<WhichPane>,
32    pub(crate) moving_divider: bool,
33}
34
35impl SplitPanel {
36    /// Constructor.
37    pub fn new(orientation: Orientation) -> Self {
38        Self {
39            orientation,
40            border: true,
41            movable_divider: true,
42            front: DummyView.into_boxed_view().into(),
43            back: DummyView.into_boxed_view().into(),
44            divider: None,
45            needs_relayout: true,
46            size: None,
47            focus: None,
48            moving_divider: false,
49        }
50    }
51
52    /// Constructor.
53    pub fn horizontal() -> Self {
54        Self::new(Orientation::Horizontal)
55    }
56
57    /// Constructor.
58    pub fn vertical() -> Self {
59        Self::new(Orientation::Vertical)
60    }
61
62    /// Orienation.
63    pub fn orientation(&self) -> Orientation {
64        self.orientation
65    }
66
67    /// Set orientation.
68    pub fn set_orientation(&mut self, orientation: Orientation) {
69        let old_orientation = self.orientation;
70        self.orientation = orientation;
71        if self.orientation != old_orientation {
72            self.needs_relayout = true;
73        }
74    }
75
76    /// Set orientation.
77    ///
78    /// Chainable.
79    pub fn with_orientation(self, orientation: Orientation) -> Self {
80        self.with(|self_| self_.set_orientation(orientation))
81    }
82
83    /// Whether to draw a border.
84    pub fn border(&self) -> bool {
85        self.border
86    }
87
88    /// Set whether to draw a border.
89    pub fn set_border(&mut self, border: bool) {
90        let old_border = self.border;
91        self.border = border;
92        if self.border != old_border {
93            self.needs_relayout = true;
94        }
95    }
96
97    /// Set whether to draw a border.
98    ///
99    /// Chainable.
100    pub fn with_border(self, border: bool) -> Self {
101        self.with(|self_| self_.set_border(border))
102    }
103
104    /// Whether to allow the divider to move.
105    pub fn movable_divider(&self) -> bool {
106        self.movable_divider
107    }
108
109    /// Set whether to allow the divider to move.
110    pub fn set_movable_divider(&mut self, movable_divider: bool) {
111        self.movable_divider = movable_divider;
112    }
113
114    /// Set whether to allow the divider to move.
115    ///
116    /// Chainable.
117    pub fn with_movable_divider(self, movable_divider: bool) -> Self {
118        self.with(|self_| self_.set_movable_divider(movable_divider))
119    }
120
121    /// View for front panel.
122    pub fn front(&self) -> &dyn View {
123        self.front.view.as_ref()
124    }
125
126    /// View for front panel.
127    pub fn front_mut(&mut self) -> &mut dyn View {
128        self.front.view.as_mut()
129    }
130
131    /// Set view for front panel.
132    pub fn set_front<ViewT>(&mut self, view: ViewT)
133    where
134        ViewT: 'static + IntoBoxedView,
135    {
136        self.front = view.into_boxed_view().into();
137        self.needs_relayout = true;
138    }
139
140    /// Set view for front panel.
141    ///
142    /// Chainable.
143    pub fn with_front<ViewT>(self, view: ViewT) -> Self
144    where
145        ViewT: 'static + IntoBoxedView,
146    {
147        self.with(|self_| self_.set_front(view))
148    }
149
150    /// View for back panel.
151    pub fn back(&self) -> &dyn View {
152        self.back.view.as_ref()
153    }
154
155    /// View for back panel.
156    pub fn back_mut(&mut self) -> &mut dyn View {
157        self.back.view.as_mut()
158    }
159
160    /// Set view for back panel.
161    pub fn set_back<ViewT>(&mut self, view: ViewT)
162    where
163        ViewT: 'static + IntoBoxedView,
164    {
165        self.back = view.into_boxed_view().into();
166        self.needs_relayout = true;
167    }
168
169    /// Set view for back panel.
170    ///
171    /// Chainable.
172    pub fn with_back<ViewT>(self, view: ViewT) -> Self
173    where
174        ViewT: 'static + IntoBoxedView,
175    {
176        self.with(|self_| self_.set_back(view))
177    }
178
179    /// The divider position as the distance from the front border.
180    ///
181    /// Returns [None] if not yet set.
182    pub fn divider(&self) -> Option<usize> {
183        self.divider
184    }
185
186    /// Set divider position as the distance from the front border.
187    ///
188    /// Note that if it doesn't fit it will move during layout.
189    pub fn set_divider(&mut self, divider: usize) {
190        let old_divider = self.divider;
191        self.divider = Some(divider);
192        if self.divider != old_divider {
193            self.needs_relayout = true;
194        }
195    }
196
197    /// Set divider position as the distance from the front border.
198    ///
199    /// Note that if it doesn't fit it will move during layout.
200    ///
201    /// Chainable.
202    pub fn with_divider(self, divider: usize) -> Self {
203        self.with(|self_| self_.set_divider(divider))
204    }
205}
206
207impl Default for SplitPanel {
208    fn default() -> Self {
209        Self::new(Orientation::Horizontal)
210    }
211}