cursive_extras/views/tabs/
container.rs1use super::{TabIter, TabIterMut};
2use std::cmp::min;
3use cursive_core::{
4 Printer, Vec2, View, Rect,
5 views::BoxedView,
6 direction::Direction,
7 event::{AnyCb, Event, EventResult},
8 view::{CannotFocus, Selector, ViewNotFound}
9};
10
11pub struct TabContainer {
16 tabs: Vec<(usize, BoxedView)>,
17 focused_id: Option<usize>
18}
19
20impl TabContainer {
21 #[must_use]
23 pub fn new() -> TabContainer {
24 TabContainer {
25 tabs: vec![],
26 focused_id: None
27 }
28 }
29
30 pub fn cur_id(&self) -> Option<usize> { self.focused_id }
32
33 pub fn cur_view(&self) -> Option<&BoxedView> {
35 if let Some(focused) = self.focused_id {
36 self.get_view(focused)
37 }
38 else { None }
39 }
40
41 pub fn cur_view_mut(&mut self) -> Option<&mut BoxedView> {
43 if let Some(focused) = self.focused_id {
44 self.get_view_mut(focused)
45 }
46 else { None }
47 }
48
49 pub fn get_view(&self, id: usize) -> Option<&BoxedView> {
51 for (view_id, view) in &self.tabs {
52 if id == *view_id { return Some(view); }
53 }
54 None
55 }
56
57 pub fn get_view_mut(&mut self, id: usize) -> Option<&mut BoxedView> {
59 for (view_id, view) in &mut self.tabs {
60 if id == *view_id { return Some(view); }
61 }
62 None
63 }
64
65 pub fn views(&self) -> TabIter { self.tabs.iter() }
67
68 pub fn views_mut(&mut self) -> TabIterMut { self.tabs.iter_mut() }
73
74 pub fn ids(&self) -> Vec<usize> {
78 let mut ids = self.views().map(|(id, _)| *id).collect::<Vec<_>>();
79 ids.sort_unstable();
80 ids
81 }
82
83 pub fn set_cur_tab(&mut self, id: usize) {
85 if self.get_view(id).is_some() {
86 self.focused_id = Some(id)
87 }
88 }
89
90 pub fn add_tab<V: View>(&mut self, view: V) -> usize {
92 if self.tabs.is_empty() {
93 self.tabs.push((0, BoxedView::boxed(view)));
94 0
95 }
96 else {
97 let new_id = self.ids().last().unwrap() + 1;
98 self.tabs.push((new_id, BoxedView::boxed(view)));
99 new_id
100 }
101 }
102
103 #[must_use]
107 pub fn tab<V: View>(mut self, view: V) -> TabContainer {
108 self.add_tab(view);
109 self.set_cur_tab(0);
110 self
111 }
112
113 pub fn remove_tab(&mut self, id: usize) {
117 self.tabs.retain(|(v_id, _)| *v_id != id);
118 if self.tabs.is_empty() {
119 self.focused_id = None;
120 }
121 else {
122 let last_id = self.tabs.last().unwrap().0;
123 self.set_cur_tab(last_id);
124 }
125 }
126
127 pub fn swap_tabs(&mut self, id_1: usize, id_2: usize) {
131 if let Some(idx_1) = self.find_tab_idx(id_1) {
132 if let Some(idx_2) = self.find_tab_idx(id_2) {
133 self.tabs.swap(idx_1, idx_2);
134 }
135 }
136 }
137
138 pub fn next(&mut self) {
140 if let Some(focused) = self.focused_id {
141 let idx = self.find_tab_idx(focused).unwrap();
142 let mut new_idx = 0;
143 if idx < self.tabs.len() - 1 {
144 new_idx = idx + 1;
145 }
146
147 self.set_cur_tab(self.tabs[new_idx].0);
148 }
149 }
150
151 pub fn prev(&mut self) {
153 if let Some(focused) = self.focused_id {
154 let idx = self.find_tab_idx(focused).unwrap();
155 let mut new_idx = self.tabs.len() - 1;
156 if idx > 0 {
157 new_idx = idx - 1;
158 }
159
160 self.set_cur_tab(self.tabs[new_idx].0);
161 }
162 }
163
164 pub fn set_as_first(&mut self, id: usize) {
166 if let Some(idx) = self.find_tab_idx(id) {
167 let tab = self.tabs.remove(idx);
168 self.tabs.insert(0, tab);
169 }
170 }
171
172 pub fn set_as_last(&mut self, id: usize) {
174 if let Some(idx) = self.find_tab_idx(id) {
175 let tab = self.tabs.remove(idx);
176 self.tabs.push(tab);
177 }
178 }
179
180 fn find_tab_idx(&self, id: usize) -> Option<usize> {
182 for (i, (v_id, _)) in self.views().enumerate() {
183 if id == *v_id { return Some(i) }
184 }
185 None
186 }
187}
188
189impl View for TabContainer {
190 fn draw(&self, printer: &Printer) {
191 if let Some(view) = self.cur_view() {
192 view.draw(printer)
193 }
194 }
195
196 fn layout(&mut self, size: Vec2) {
197 if let Some(view) = self.cur_view_mut() {
198 view.layout(size);
199 }
200 }
201
202 fn required_size(&mut self, constraint: Vec2) -> Vec2 {
203 if let Some(view) = self.cur_view_mut() {
204 let tab_size = view.required_size(constraint);
205 Vec2::from((min(tab_size.x, constraint.x), min(tab_size.y, constraint.y)))
206 }
207 else { Vec2::from((1, 1)) }
208 }
209
210 fn on_event(&mut self, event: Event) -> EventResult {
211 if let Some(view) = self.cur_view_mut() { view.on_event(event) }
212 else { EventResult::Ignored }
213 }
214
215 fn take_focus(&mut self, dir: Direction) -> Result<EventResult, CannotFocus> {
216 if let Some(view) = self.cur_view_mut() { view.take_focus(dir) }
217 else { Err(CannotFocus) }
218 }
219
220 fn call_on_any(&mut self, sel: &Selector, cb: AnyCb) {
221 for (_, view) in self.views_mut() {
222 view.call_on_any(sel, cb);
223 }
224 }
225
226 fn focus_view(&mut self, sel: &Selector) -> Result<EventResult, ViewNotFound> {
227 if let Some(view) = self.cur_view_mut() { view.focus_view(sel) }
228 else { Err(ViewNotFound) }
229 }
230
231 fn needs_relayout(&self) -> bool {
232 if let Some(view) = self.cur_view() { view.needs_relayout() }
233 else { true }
234 }
235
236 fn important_area(&self, size: Vec2) -> Rect {
237 if let Some(view) = self.cur_view() { view.important_area(size) }
238 else { Rect::from_point((1, 1)) }
239 }
240}
241
242impl Default for TabContainer {
243 fn default() -> Self { Self::new() }
244}