1use std::mem;
2
3use makepad_render::*;
4use crate::splitter::*;
5use crate::tabcontrol::*;
6use crate::widgetstyle::*;
7use serde::*;
8
9#[derive(Clone)]
10pub struct Dock<TItem>
11where TItem: Clone
12{
13 pub splitters: Elements<usize, Splitter, Splitter>,
15 pub tab_controls: Elements<usize, TabControl, TabControl>,
16
17 pub drop_size: Vec2,
18 pub drop_quad: Quad,
19 pub drop_quad_view: View,
20 pub _drag_move: Option<FingerMoveEvent>,
22 pub _drag_end: Option<DockDragEnd<TItem>>,
23 pub _close_tab: Option<DockTabIdent>,
24 pub _tab_select: Option<(usize, usize)>,
25 pub _tweening_quad: Option<(usize, Rect, f32)>
26}
27
28#[derive(Clone, Debug)]
29pub struct DockTabIdent {
30 tab_control_id: usize,
31 tab_id: usize
32}
33
34#[derive(Clone)]
35pub enum DockDragEnd<TItem>
36where TItem: Clone {
37 OldTab {fe: FingerUpEvent, ident: DockTabIdent},
38 NewItems {fe: FingerUpEvent, items: Vec<DockTab<TItem>>}
39}
40
41#[derive(Clone, Serialize, Deserialize)]
42pub struct DockTab<TItem>
43where TItem: Clone
44{
45 pub closeable: bool,
46 pub title: String,
47 pub item: TItem
48}
49
50#[derive(Clone, Serialize, Deserialize)]
51pub enum DockItem<TItem>
52where TItem: Clone
53{
54 Single(TItem),
55 TabControl {
56 current: usize,
57 previous: usize,
58 tabs: Vec<DockTab<TItem>>,
59 },
60 Splitter {
61 pos: f32,
62 align: SplitterAlign,
63 axis: Axis,
64 first: Box<DockItem<TItem>>,
65 last: Box<DockItem<TItem>>
66 }
67}
68
69
70struct DockWalkStack<'a, TItem>
71where TItem: Clone
72{
73 counter: usize,
74 uid: usize,
75 item: &'a mut DockItem<TItem>
76}
77
78pub enum DockEvent {
79 None,
80 DockTabClosed,
81 DockTabCloned {tab_control_id: usize, tab_id: usize},
82 DockChanged
83}
84
85pub struct DockWalker<'a, TItem>
86where TItem: Clone
87{
88 walk_uid: usize,
89 stack: Vec<DockWalkStack<'a, TItem>>,
90 splitters: &'a mut Elements<usize, Splitter, Splitter>,
92 tab_controls: &'a mut Elements<usize, TabControl, TabControl>,
93 drop_quad_view: &'a mut View,
94 _drag_move: &'a mut Option<FingerMoveEvent>,
95 _drag_end: &'a mut Option<DockDragEnd<TItem>>,
96 _close_tab: &'a mut Option<DockTabIdent>,
97 _tab_select: &'a mut Option<(usize, usize)>
98}
99
100impl<'a, TItem> DockWalker<'a, TItem>
101where TItem: Clone
102{
103
104 pub fn walk_dock_item(&mut self) -> Option<(usize, &mut DockItem<TItem>)> {
105 let push_or_pop = if let Some(stack_top) = self.stack.last_mut() {
107 match stack_top.item {
109 DockItem::Single(..) => {
110 if stack_top.counter == 0 {
111 stack_top.counter += 1;
112 return Some((self.walk_uid,unsafe {mem::transmute(&mut *stack_top.item)}));
113 }
114 else {
115 None
116 }
117 },
118 DockItem::TabControl {..} => {
119 if stack_top.counter == 0 {
120 let uid = self.walk_uid;
121 self.walk_uid += 1;
122 stack_top.counter += 1;
123 return Some((uid, unsafe {mem::transmute(&mut *stack_top.item)}));
124 }
125 else {
126 None
127 }
128 },
129 DockItem::Splitter {first, last, ..} => {
130 if stack_top.counter == 0 {
131 let uid = self.walk_uid;
132 self.walk_uid += 1;
133 stack_top.counter += 1;
134 return Some((uid, unsafe {mem::transmute(&mut *stack_top.item)}));
135 }
136 else if stack_top.counter == 1 {
137 stack_top.counter += 1;
138 Some(DockWalkStack {counter: 0, uid: 0, item: unsafe {mem::transmute(first.as_mut())}})
139 }
140 else if stack_top.counter == 2 {
141 stack_top.counter += 1;
142 Some(DockWalkStack {counter: 0, uid: 0, item: unsafe {mem::transmute(last.as_mut())}})
143 }
144 else {
145 None
146 }
147 }
148 }
149 }
150 else {
151 return None;
152 };
153 if let Some(item) = push_or_pop {
154 self.stack.push(item);
155 return self.walk_dock_item();
156 }
157 else if self.stack.len() > 0 {
158 self.stack.pop();
159 return self.walk_dock_item();
160 }
161 return None;
162 }
163
164 pub fn walk_handle_dock(&mut self, cx: &mut Cx, event: &mut Event) -> Option<&mut TItem> {
165 let push_or_pop = if let Some(stack_top) = self.stack.last_mut() {
167 match stack_top.item {
169 DockItem::Single(item) => {
170 if stack_top.counter == 0 {
171 stack_top.counter += 1;
172 return Some(unsafe {mem::transmute(item)});
173 }
174 else {
175 None
176 }
177 },
178 DockItem::TabControl {current, previous, tabs} => {
179 if stack_top.counter == 0 {
180 stack_top.counter += 1;
181 stack_top.uid = self.walk_uid;
182 self.walk_uid += 1;
183
184 if *current < tabs.len() {
185 return Some(unsafe {mem::transmute(&mut tabs[*current].item)});
186 }
187 None
188 }
189 else {
190 let tab_control = self.tab_controls.get(stack_top.uid);
191 let mut defocus = false;
192 if !tab_control.is_none() {
193 match tab_control.unwrap().handle_tab_control(cx, event) {
194 TabControlEvent::TabSelect {tab_id} => {
195 if *current != tab_id{
196 *previous = *current;
197 *current = tab_id;
198 cx.redraw_child_area(Area::All);
200 *self._tab_select = Some((stack_top.uid, tab_id));
201 defocus = true;
202 }
203 },
204 TabControlEvent::TabDragMove {fe, ..} => {
205 *self._drag_move = Some(fe);
206 *self._drag_end = None;
207 self.drop_quad_view.redraw_view_area(cx);
208 },
209 TabControlEvent::TabDragEnd {fe, tab_id} => {
210 *self._drag_move = None;
211 *self._drag_end = Some(DockDragEnd::OldTab {
212 fe: fe,
213
214 ident: DockTabIdent {
215 tab_control_id: stack_top.uid,
216
217 tab_id: tab_id
218 }
219 });
220 self.drop_quad_view.redraw_view_area(cx);
221 },
222 TabControlEvent::TabClose {tab_id} => {
223 *self._close_tab = Some(DockTabIdent {
224 tab_control_id: stack_top.uid,
225 tab_id: tab_id
226 });
227 if tab_id < *current && *current > 0 {
229 *current -= 1;
230 }
231 cx.redraw_child_area(Area::All);
232 },
233 _ => ()
234 }
235 }
236
237 if defocus {
238 for (id, tab_control) in self.tab_controls.enumerate() {
240 if *id != stack_top.uid {
241 tab_control.set_tab_control_focus(cx, false);
242 }
243 }
244 }
245
246 None
247 }
248 },
249 DockItem::Splitter {first, last, pos, align, ..} => {
250 if stack_top.counter == 0 {
251 stack_top.counter += 1;
252 stack_top.uid = self.walk_uid;
253 self.walk_uid += 1;
254 let split = self.splitters.get(stack_top.uid);
255 if let Some(split) = split {
256 match split.handle_splitter(cx, event) {
257 SplitterEvent::Moving {new_pos} => {
258 *pos = new_pos;
259 cx.redraw_pass_of(split._split_area);
260 },
261 SplitterEvent::MovingEnd {new_align, new_pos} => {
262 *align = new_align;
263 *pos = new_pos;
264 cx.redraw_pass_of(split._split_area);
265 },
266 _ => ()
267 };
268 }
269 Some(DockWalkStack {counter: 0, uid: 0, item: unsafe {mem::transmute(first.as_mut())}})
271 }
272 else if stack_top.counter == 1 {
273 stack_top.counter += 1;
274 Some(DockWalkStack {counter: 0, uid: 0, item: unsafe {mem::transmute(last.as_mut())}})
275 }
276 else {
277 None
278 }
279 }
280 }
281 }
282 else {
283 return None;
284 };
285 if let Some(item) = push_or_pop {
286 self.stack.push(item);
287 return self.walk_handle_dock(cx, event);
288 }
289 else if self.stack.len() > 0 {
290 self.stack.pop();
291 return self.walk_handle_dock(cx, event);
292 }
293 return None;
294 }
295
296 pub fn walk_draw_dock<F>(&mut self, cx: &mut Cx, mut tab_handler:F) -> Option<&'a mut TItem>
297 where F: FnMut(&mut Cx, &mut TabControl, &DockTab<TItem>, bool) {
298 let push_or_pop = if let Some(stack_top) = self.stack.last_mut() {
300 match stack_top.item {
302 DockItem::Single(item) => {
303 if stack_top.counter == 0 {
304 stack_top.counter += 1;
305 return Some(unsafe {mem::transmute(item)});
306 }
307 else {
308 None
309 }
310 },
311 DockItem::TabControl {current, previous:_, tabs} => {
312 if stack_top.counter == 0 {
313 stack_top.counter += 1;
314 stack_top.uid = self.walk_uid;
315 self.walk_uid += 1;
316 let tab_control = self.tab_controls.get_draw(cx, stack_top.uid, | _cx, tmpl | tmpl.clone());
317
318 if let Ok(_) = tab_control.begin_tabs(cx) {
319 for (id, tab) in tabs.iter().enumerate() {
320 tab_handler(cx, tab_control, tab, *current == id)
321 }
322 tab_control.end_tabs(cx);
323 }
324
325 if let Ok(_) = tab_control.begin_tab_page(cx) {
326 if *current < tabs.len() {
327 return Some(unsafe {mem::transmute(&mut tabs[*current].item)});
328 }
329 tab_control.end_tab_page(cx);
330 }
331 None
332 }
333 else {
334 let tab_control = self.tab_controls.get_draw(cx, stack_top.uid, | _cx, tmpl | tmpl.clone());
335 tab_control.end_tab_page(cx);
336 None
337 }
338 },
339 DockItem::Splitter {align, pos, axis, first, last} => {
340 if stack_top.counter == 0 {
341 stack_top.counter += 1;
342 stack_top.uid = self.walk_uid;
343 self.walk_uid += 1;
344 let split = self.splitters.get_draw(cx, stack_top.uid, | _cx, tmpl | tmpl.clone());
346 split.set_splitter_state(align.clone(), *pos, axis.clone());
347 split.begin_splitter(cx);
348 Some(DockWalkStack {counter: 0, uid: 0, item: unsafe {mem::transmute(first.as_mut())}})
349 }
350 else if stack_top.counter == 1 {
351 stack_top.counter += 1;
352
353 let split = self.splitters.get_draw(cx, stack_top.uid, | _cx, tmpl | tmpl.clone());
354 split.mid_splitter(cx);
355 Some(DockWalkStack {counter: 0, uid: 0, item: unsafe {mem::transmute(last.as_mut())}})
356 }
357 else {
358 let split = self.splitters.get_draw(cx, stack_top.uid, | _cx, tmpl | tmpl.clone());
359 split.end_splitter(cx);
360 None
361 }
362 }
363 }
364 }
365 else {
366 return None
367 };
368 if let Some(item) = push_or_pop {
369 self.stack.push(item);
370 return self.walk_draw_dock(cx, tab_handler);
371 }
372 else if self.stack.len() > 0 {
373 self.stack.pop();
374 return self.walk_draw_dock(cx, tab_handler);
375 }
376 None
377 }
378}
379
380enum DockDropKind {
381 Tab(usize),
382 TabsView,
383 Left,
384 Top,
385 Right,
386 Bottom,
387 Center
388}
389
390impl<TItem> Dock<TItem>
391where TItem: Clone
392{
393 pub fn proto(cx: &mut Cx) -> Dock<TItem> {
394 Dock {
395 drop_size: Vec2 {x: 100., y: 70.},
397 drop_quad: Quad {
399 z: 10.,
400 ..Quad::proto(cx)
401 },
402 splitters: Elements::new(Splitter::proto(cx)),
403 tab_controls: Elements::new(TabControl::proto(cx)),
404 drop_quad_view: View::proto_overlay(cx),
405 _close_tab: None,
406 _drag_move: None,
407 _drag_end: None,
408 _tab_select: None,
409 _tweening_quad: None
410 }
411 }
412
413 fn recur_remove_tab(dock_walk: &mut DockItem<TItem>, control_id: usize, tab_id: usize, counter: &mut usize, clone: bool, select_previous:bool) -> Option<DockTab<TItem>>
414 where TItem: Clone
415 {
416 match dock_walk {
417 DockItem::Single(_) => {},
418 DockItem::TabControl {tabs, current, previous} => {
419 let id = *counter;
420 *counter += 1;
421 if id == control_id {
422 if tab_id >= tabs.len() {
423 return None;
424 }
425 if clone && tabs[tab_id].closeable {
426 return Some(tabs[tab_id].clone())
427 }
428 else {
429 if select_previous && *previous != *current && *previous < tabs.len() - 1{
431 *current = *previous;
432 }
433 else
434 if *current >= 1 && *current == tabs.len() - 1 {
435 *current -= 1;
436 }
437 return Some(tabs.remove(tab_id));
438 }
439 }
440 },
441 DockItem::Splitter {first, last, ..} => {
442 *counter += 1;
443 let left = Self::recur_remove_tab(first, control_id, tab_id, counter, clone, select_previous);
444 if !left.is_none() {
445 return left
446 }
447 let right = Self::recur_remove_tab(last, control_id, tab_id, counter, clone, select_previous);
448 if !right.is_none() {
449 return right
450 }
451 }
452 }
453 None
454 }
455
456 fn recur_collapse_empty(dock_walk: &mut DockItem<TItem>) -> bool
457 where TItem: Clone
458 {
459 match dock_walk {
460 DockItem::Single(_) => {},
461 DockItem::TabControl {tabs, ..} => {
462 return tabs.len() == 0
463 },
464 DockItem::Splitter {first, last, ..} => {
465 let rem_first = Self::recur_collapse_empty(first);
466 let rem_last = Self::recur_collapse_empty(last);
467 if rem_first && rem_last {
468 return true;
469 }
470 if rem_first {
471 *dock_walk = *last.clone();
472 }
473 else if rem_last {
474 *dock_walk = *first.clone();
475 }
476 }
477 }
478 false
479 }
480
481 fn recur_split_dock(dock_walk: &mut DockItem<TItem>, items: &Vec<DockTab<TItem>>, control_id: usize, kind: &DockDropKind, counter: &mut usize)->Option<DockTabIdent>
482 where TItem: Clone
483 {
484 match dock_walk {
485 DockItem::Single(_) => {},
486 DockItem::TabControl {tabs, previous:_, current} => {
487 let id = *counter;
488 *counter += 1;
489 if id == control_id {
490 match kind {
491 DockDropKind::Tab(id) => {
492 let mut idc = *id;
493 for item in items {
494 tabs.insert(idc, item.clone());
495 idc += 1;
496 }
497 *current = idc - 1;
498 return Some(DockTabIdent{tab_control_id:control_id, tab_id:*current})
499 },
500 DockDropKind::Left => {
501 *dock_walk = DockItem::Splitter {
502 align: SplitterAlign::Weighted,
503 pos: 0.5,
504 axis: Axis::Vertical,
505 last: Box::new(dock_walk.clone()),
506 first: Box::new(DockItem::TabControl {current: 0, previous:0, tabs: items.clone()})
507 };
508 return Some(DockTabIdent{tab_control_id:control_id+1, tab_id:0})
509 },
510 DockDropKind::Right => {
511 *dock_walk = DockItem::Splitter {
512 align: SplitterAlign::Weighted,
513 pos: 0.5,
514 axis: Axis::Vertical,
515 first: Box::new(dock_walk.clone()),
516 last: Box::new(DockItem::TabControl {current: 0, previous:0, tabs: items.clone()})
517 };
518 return Some(DockTabIdent{tab_control_id:control_id+2, tab_id:0})
519 },
520 DockDropKind::Top => {
521 *dock_walk = DockItem::Splitter {
522 align: SplitterAlign::Weighted,
523 pos: 0.5,
524 axis: Axis::Horizontal,
525 last: Box::new(dock_walk.clone()),
526 first: Box::new(DockItem::TabControl {current: 0, previous:0, tabs: items.clone()})
527 };
528 return Some(DockTabIdent{tab_control_id:control_id+1, tab_id:0})
529 },
530 DockDropKind::Bottom => {
531 *dock_walk = DockItem::Splitter {
532 align: SplitterAlign::Weighted,
533 pos: 0.5,
534 axis: Axis::Horizontal,
535 first: Box::new(dock_walk.clone()),
536 last: Box::new(DockItem::TabControl {current: 0, previous:0, tabs: items.clone()})
537 };
538 return Some(DockTabIdent{tab_control_id:control_id+2, tab_id:0})
539 },
540 DockDropKind::TabsView |
541 DockDropKind::Center => {
542 *current = tabs.len() + items.len() - 1;
543 for item in items {
544 tabs.push(item.clone());
545 }
546 return Some(DockTabIdent{tab_control_id:control_id, tab_id:tabs.len()-1})
547 }
548 }
549 }
550 },
551 DockItem::Splitter {first, last, ..} => {
552 *counter += 1;
553 if let Some(ret) = Self::recur_split_dock(first, items, control_id, kind, counter){
554 return Some(ret)
555 }
556 if let Some(ret) = Self::recur_split_dock(last, items, control_id, kind, counter){
557 return Some(ret)
558 }
559 }
560 }
561 None
562 }
563
564 fn get_drop_kind(pos: Vec2, drop_size: Vec2, tvr: Rect, cdr: Rect, tab_rects: Vec<Rect>) -> (DockDropKind, Rect) {
565 if tvr.contains(pos.x, pos.y) {
580 for (id, tr) in tab_rects.iter().enumerate() {
581 if tr.contains(pos.x, pos.y) {
582 return (DockDropKind::Tab(id), *tr)
583 }
584 }
585 return (DockDropKind::TabsView, tvr)
586 }
587 if pos.y < cdr.y + drop_size.y {
588 return (DockDropKind::Top, Rect {
589 x: cdr.x,
590 y: cdr.y,
591 w: cdr.w,
592 h: 0.5 * cdr.h
593 })
594 }
595 if pos.y > cdr.y + cdr.h - drop_size.y {
596 return (DockDropKind::Bottom, Rect {
597 x: cdr.x,
598 y: cdr.y + 0.5 * cdr.h,
599 w: cdr.w,
600 h: 0.5 * cdr.h
601 })
602 }
603 if pos.x < cdr.x + drop_size.x {
604 return (DockDropKind::Left, Rect {
605 x: cdr.x,
606 y: cdr.y,
607 w: 0.5 * cdr.w,
608 h: cdr.h
609 })
610 }
611 if pos.x > cdr.x + cdr.w - drop_size.x {
612 return (DockDropKind::Right, Rect {
613 x: cdr.x + 0.5 * cdr.w,
614 y: cdr.y,
615 w: 0.5 * cdr.w,
616 h: cdr.h
617 })
618 }
619 (DockDropKind::Center, cdr.clone())
620 }
621
622 pub fn dock_drag_out(&mut self, cx: &mut Cx) {
623 self._drag_move = None;
624 self.drop_quad_view.redraw_view_area(cx);
625 }
626
627 pub fn dock_drag_move(&mut self, cx: &mut Cx, fe: FingerMoveEvent) {
628 self._drag_move = Some(fe);
629 self.drop_quad_view.redraw_view_area(cx);
630 }
631
632 pub fn dock_drag_cancel(&mut self, cx: &mut Cx) {
633 self._drag_move = None;
634 self.drop_quad_view.redraw_view_area(cx);
635 }
636
637 pub fn dock_drag_end(&mut self, _cx: &mut Cx, fe: FingerUpEvent, new_items: Vec<DockTab<TItem>>) {
638 self._drag_move = None;
639 self._drag_end = Some(DockDragEnd::NewItems {
640 fe: fe,
641 items: new_items
642 });
643 }
644
645 pub fn handle_dock(&mut self, cx: &mut Cx, _event: &mut Event, dock_items: &mut DockItem<TItem>) -> DockEvent {
646 if let Some(close_tab) = &self._close_tab {
647 Self::recur_remove_tab(dock_items, close_tab.tab_control_id, close_tab.tab_id, &mut 0, false, false);
648 Self::recur_collapse_empty(dock_items);
649 cx.redraw_child_area(Area::All);
650 self._close_tab = None;
651 return DockEvent::DockTabClosed
652 }
653 if let Some(drag_end) = self._drag_end.clone() {
654 self._drag_end = None;
655 let mut tab_clone_ident = None;
656 let fe = match &drag_end {DockDragEnd::OldTab {fe, ..} => fe, DockDragEnd::NewItems {fe, ..} => fe};
657 for (target_id, tab_control) in self.tab_controls.enumerate() {
658
659 let cdr = tab_control.get_content_drop_rect(cx);
660 let tvr = tab_control.get_tabs_view_rect(cx);
661 if tvr.contains(fe.abs.x, fe.abs.y) || cdr.contains(fe.abs.x, fe.abs.y) { let tab_rects = tab_control.get_tab_rects(cx);
664 let (kind, _rect) = Self::get_drop_kind(fe.abs, self.drop_size, tvr, cdr, tab_rects);
665
666 let mut do_tab_clone = false;
671 let items = match &drag_end {
672 DockDragEnd::OldTab {ident, ..} => {
673 if fe.modifiers.control || fe.modifiers.logo {
674 do_tab_clone = true;
675 }
676 let item = Self::recur_remove_tab(dock_items, ident.tab_control_id, ident.tab_id, &mut 0, do_tab_clone, true);
677 if let Some(item) = item {
678 if !item.closeable {
679 do_tab_clone = false;
680 }
681 vec![item]
682 }
683 else {
684 vec![]
685 }
686 },
687 DockDragEnd::NewItems {items, ..} => {
688 items.clone()
689 }
690 };
691 if items.len() > 0 {
693 let new_ident = Self::recur_split_dock(
694 dock_items,
695 &items,
696 *target_id,
697 &kind,
698 &mut 0
699 );
700 if do_tab_clone{
701 tab_clone_ident = new_ident;
702 }
703 };
704 }
705 }
706 Self::recur_collapse_empty(dock_items);
707 cx.redraw_child_area(Area::All);
708 if let Some(ident) = tab_clone_ident {
710 return DockEvent::DockTabCloned {tab_control_id: ident.tab_control_id, tab_id: ident.tab_id}
711 }
712 return DockEvent::DockChanged
713 };
714 DockEvent::None
716 }
717
718 pub fn draw_dock(&mut self, cx: &mut Cx) {
719 if let Some(fe) = &self._drag_move {
721 if let Err(()) = self.drop_quad_view.begin_view(cx, Layout::abs_origin_zero()) {
722 return
723 }
724 let mut found_drop_zone = false;
725 for (id, tab_control) in self.tab_controls.enumerate() {
726
727 let cdr = tab_control.get_content_drop_rect(cx);
728 let tvr = tab_control.get_tabs_view_rect(cx);
729 if tvr.contains(fe.abs.x, fe.abs.y) || cdr.contains(fe.abs.x, fe.abs.y) {
730 let tab_rects = tab_control.get_tab_rects(cx);
731 let (_kind, rect) = Self::get_drop_kind(fe.abs, self.drop_size, tvr, cdr, tab_rects);
732
733 if !self._tweening_quad.is_none() && self._tweening_quad.unwrap().0 != *id {
734 self._tweening_quad = None;
736 }
737
738 let (dr, alpha) = if self._tweening_quad.is_none() {
740 self._tweening_quad = Some((*id, rect, 0.));
741 (rect, 0.)
742 }
743 else {
744 let (id, old_rc, old_alpha) = self._tweening_quad.unwrap();
745 let move_speed = 0.0;
746 let alpha_speed = 0.0;
747 let alpha = old_alpha * alpha_speed + (1. - alpha_speed);
748 let rc = Rect {
749 x: old_rc.x * move_speed + rect.x * (1. - move_speed),
750 y: old_rc.y * move_speed + rect.y * (1. - move_speed),
751 w: old_rc.w * move_speed + rect.w * (1. - move_speed),
752 h: old_rc.h * move_speed + rect.h * (1. - move_speed)
753 };
754 let dist = (rc.x - rect.x)
755 .abs()
756 .max((rc.y - rect.y).abs())
757 .max((rc.w - rect.w).abs())
758 .max((rc.h - rect.h).abs())
759 .max(100. - alpha * 100.);
760 if dist>0.5 { }
764 self._tweening_quad = Some((id, rc, alpha));
765 (rc, alpha)
766 };
767 self.drop_quad.color = Theme::color_drop_quad().get(cx);
768 self.drop_quad.color.a = alpha * 0.8;
769 found_drop_zone = true;
770 self.drop_quad.draw_quad_rel(cx, dr);
771 }
772 }
773 if !found_drop_zone {
774 self._tweening_quad = None;
775 }
776 self.drop_quad_view.end_view(cx);
777 }
778 }
779
780 pub fn walker<'a>(&'a mut self, dock_items: &'a mut DockItem<TItem>) -> DockWalker<'a,
781 TItem> {
782 let mut stack = Vec::new();
783 stack.push(DockWalkStack {counter: 0, uid: 0, item: dock_items});
785 DockWalker {
787 walk_uid: 0,
788 stack: stack,
789 splitters: &mut self.splitters,
790 tab_controls: &mut self.tab_controls,
791 _drag_move: &mut self._drag_move,
792 _drag_end: &mut self._drag_end,
793 _close_tab: &mut self._close_tab,
794 _tab_select: &mut self._tab_select,
795 drop_quad_view: &mut self.drop_quad_view
796 }
797 }
798
799}
800
801