1use makepad_render::*;
2
3use crate::scrollbar::*;
4use crate::scrollview::*;
5use crate::tab::*;
6use crate::widgetstyle::*;
7
8#[derive(Clone)]
9pub struct TabControl {
10 pub tabs_view: ScrollView,
11 pub tabs: Elements<usize, Tab, Tab>,
12 pub drag_tab_view: View,
13 pub drag_tab: Tab,
14 pub page_view: View,
15 pub hover: Quad,
16 pub tab_fill: Quad,
18 pub animator: Animator,
19
20 pub _dragging_tab: Option<(FingerMoveEvent, usize)>,
21 pub _tab_id_alloc: usize,
22 pub _tab_now_selected: Option<usize>,
23 pub _tab_last_selected:Option<usize>,
24 pub _focussed: bool
25}
26
27#[derive(Clone, PartialEq)]
28pub enum TabControlEvent {
29 None,
30 TabDragMove {fe: FingerMoveEvent, tab_id: usize},
31 TabDragEnd {fe: FingerUpEvent, tab_id: usize},
32 TabSelect {tab_id: usize},
33 TabClose {tab_id: usize}
34}
35
36impl TabControl {
37 pub fn proto(cx: &mut Cx) -> Self {
38 Self {
39 tabs_view: ScrollView {
40 scroll_h: Some(ScrollBar {
41 bar_size: 8.0,
42 smoothing: Some(0.15),
43 use_vertical_finger_scroll: true,
44 ..ScrollBar::proto(cx)
45 }),
46 ..ScrollView::proto(cx)
47 },
48 page_view: View::proto(cx),
49 tabs: Elements::new(Tab::proto(cx)),
50 drag_tab: Tab {
51 z: 10.,
52 ..Tab::proto(cx)
53 },
54 drag_tab_view: View {
55 is_overlay: true,
56 ..View::proto(cx)
57 },
58 hover: Quad {
59 color: color("purple"),
60 ..Quad::proto(cx)
61 },
62 tab_fill: Quad::proto(cx),
64 animator: Animator::default(),
65 _dragging_tab: None,
66 _tab_now_selected:None,
67 _tab_last_selected:None,
68 _focussed: false,
69 _tab_id_alloc: 0
70 }
71 }
72
73 pub fn handle_tab_control(&mut self, cx: &mut Cx, event: &mut Event) -> TabControlEvent {
74 let mut tab_control_event = TabControlEvent::None;
75
76 self.tabs_view.handle_scroll_bars(cx, event);
77
78 for (id, tab) in self.tabs.enumerate() {
79
80 match tab.handle_tab(cx, event) {
81 TabEvent::Select => {
82 self.page_view.redraw_view_area(cx);
83 tab_control_event = TabControlEvent::TabSelect {tab_id: *id}
85 },
86 TabEvent::DragMove(fe) => {
87 self._dragging_tab = Some((fe.clone(), *id));
88 self.tabs_view.redraw_view_area(cx);
90 self.drag_tab_view.redraw_view_area(cx);
91
92 tab_control_event = TabControlEvent::TabDragMove {fe: fe, tab_id: *id};
93 },
94 TabEvent::DragEnd(fe) => {
95 self._dragging_tab = None;
96 self.drag_tab_view.redraw_view_area(cx);
97
98 tab_control_event = TabControlEvent::TabDragEnd {fe, tab_id: *id};
99 },
100 TabEvent::Closing => { if tab._is_selected { let next_sel = if *id == self._tab_id_alloc - 1 { if *id > 0 {
104 *id - 1
105 }
106 else {
107 *id
108 }
109 }
110 else {
111 *id + 1
112 };
113 if *id != next_sel {
114 tab_control_event = TabControlEvent::TabSelect {tab_id: next_sel};
115 }
116 }
117 },
118 TabEvent::Close => {
119 tab_control_event = TabControlEvent::TabClose {tab_id: *id};
121 },
122 _ => ()
123 }
124 };
125 match tab_control_event {
126 TabControlEvent::TabSelect {tab_id} => {
127 self._focussed = true;
128 for (id, tab) in self.tabs.enumerate() {
129 if tab_id != *id {
130 tab.set_tab_selected(cx, false);
131 tab.set_tab_focus(cx, true);
132 }
133 }
134 },
135 TabControlEvent::TabClose {..} => { self.tabs.clear(cx, | _, _ | ());
137 },
138 _ => ()
139 };
140 tab_control_event
141 }
142
143 pub fn tab_control_style()->StyleId{uid!()}
144
145 pub fn style(cx:&mut Cx, opt:&StyleOptions){
146 cx.begin_style(Self::tab_control_style());
147 ScrollBar::bar_size().set(cx, 8. * opt.scale.powf(0.5));
148 cx.end_style();
149 }
150
151 pub fn get_tab_rects(&mut self, cx: &Cx) -> Vec<Rect> {
152 let mut rects = Vec::new();
153 for tab in self.tabs.iter() {
154 rects.push(tab.get_tab_rect(cx))
155 }
156 return rects
157 }
158
159 pub fn set_tab_control_focus(&mut self, cx: &mut Cx, focus: bool) {
160 self._focussed = focus;
161 for tab in self.tabs.iter() {
162 tab.set_tab_focus(cx, focus);
163 }
164 }
165
166 pub fn get_tabs_view_rect(&mut self, cx: &Cx) -> Rect {
167 self.tabs_view.get_rect(cx)
168 }
169
170 pub fn get_content_drop_rect(&mut self, cx: &Cx) -> Rect {
171 let pr = self.page_view.get_rect(cx);
172 Rect {
174 x: pr.x,
175 y: pr.y,
176 w: pr.w,
177 h: pr.h
178 }
179 }
180
181 pub fn begin_tabs(&mut self, cx: &mut Cx) -> ViewRedraw {
183 if let Err(_) = self.tabs_view.begin_view(cx, Layout {
185 walk:Walk::wh(Width::Fill, Height::Compute),
186 ..Layout::default()
187 }) {
188 return Err(())
189 }
190 self._tab_now_selected = None;
191 self._tab_id_alloc = 0;
192 Ok(())
193 }
194
195 pub fn get_draw_tab(&mut self, cx: &mut Cx, label: &str, selected: bool, closeable: bool)->&mut Tab{
196 let new_tab = self.tabs.get(self._tab_id_alloc).is_none();
197 let tab = self.tabs.get_draw(cx, self._tab_id_alloc, | _cx, tmpl | tmpl.clone());
198 if selected{
199 self._tab_now_selected = Some(self._tab_id_alloc);
200 }
201 self._tab_id_alloc += 1;
202 tab.label = label.to_string();
203 tab.is_closeable = closeable;
204 if new_tab {
205 tab.set_tab_state(cx, selected, self._focussed);
206 }
207 else { tab.set_tab_selected(cx, selected);
209 }
210 tab
211 }
212
213 pub fn draw_tab(&mut self, cx: &mut Cx, label: &str, selected: bool, closeable: bool) {
214 let tab = self.get_draw_tab(cx, label, selected, closeable);
215 tab.draw_tab(cx);
216 }
217
218 pub fn end_tabs(&mut self, cx: &mut Cx) {
219 self.tab_fill.color = Theme::color_bg_normal().get(cx);
220 self.tab_fill.draw_quad(cx, Walk::wh(Width::Fill, Height::Fill));
221 self.tabs.sweep(cx, | _, _ | ());
222 if let Some((fe, id)) = &self._dragging_tab {
223 if let Ok(()) = self.drag_tab_view.begin_view(cx, Layout {
224 abs_origin: Some(Vec2::default()),
225 ..Default::default()
226 }) {
227
228 self.drag_tab.abs_origin = Some(Vec2 {x: fe.abs.x - fe.rel_start.x, y: fe.abs.y - fe.rel_start.y});
229 let origin_tab = self.tabs.get_draw(cx, *id, | _cx, tmpl | tmpl.clone());
230 self.drag_tab.label = origin_tab.label.clone();
231 self.drag_tab.is_closeable = origin_tab.is_closeable;
232 self.drag_tab.draw_tab(cx);
233
234 self.drag_tab_view.end_view(cx);
235 }
236 }
237 cx.begin_style(Self::tab_control_style());
238 self.tabs_view.end_view(cx);
239 cx.end_style();
240 if self._tab_now_selected != self._tab_last_selected{
241 if let Some(tab_id) = self._tab_now_selected{
243 if let Some(tab) = self.tabs.get(tab_id){
244 let tab_rect = tab._bg_area.get_rect(cx);
245 self.tabs_view.scroll_into_view_abs(cx, tab_rect);
246 }
247 }
248 self._tab_last_selected = self._tab_now_selected;
249 }
250 }
251
252 pub fn begin_tab_page(&mut self, cx: &mut Cx) -> ViewRedraw {
253 cx.turtle_new_line();
254 self.page_view.begin_view(cx, Layout::default())
255 }
256
257 pub fn end_tab_page(&mut self, cx: &mut Cx) {
258 self.page_view.end_view(cx);
259 }
263}