1#![allow(dead_code)]
2use {
3 std::rc::Rc,
4 std::cell::RefCell,
5 crate::{
6 cx_draw::CxDraw,
7 makepad_platform::Area,
8 makepad_platform::DrawListId,
9 makepad_platform::Margin,
10 makepad_platform::Cx,
11 }
12};
13
14#[derive(Default)]
15pub struct CxNavTree {
16 nav_lists: Vec<CxNavList>
17}
18
19#[derive(Clone)]
20pub struct CxNavTreeRc(pub Rc<RefCell<CxNavTree >>);
21
22#[derive(Debug, Default, Clone)]
23pub struct CxNavList {
24 pub nav_list: Vec<NavItem>
25}
26
27impl std::ops::Index<DrawListId> for CxNavTree {
28 type Output = CxNavList;
29 fn index(&self, index: DrawListId) -> &Self::Output {
30 &self.nav_lists[index.index()]
31 }
32}
33
34impl std::ops::IndexMut<DrawListId> for CxNavTree {
35 fn index_mut(&mut self, index: DrawListId) -> &mut Self::Output {
36 &mut self.nav_lists[index.index()]
37 }
38}
39
40#[derive(Debug, Clone)]
41pub enum NavOrder {
42 Default,
43 Top(u64),
44 Middle(u64),
45 Bottom(u64),
46}
47
48#[derive(Debug, Clone)]
49pub struct NavStop {
50 pub role: NavRole,
51 pub order: NavOrder,
52 pub margin: Margin,
53 pub area: Area
54}
55
56#[derive(Debug, Clone)]
57pub enum NavItem {
58 Child(DrawListId),
59 Stop(NavStop),
60 BeginScroll(Area),
61 EndScroll(Area)
62}
63
64#[derive(Debug, Clone)]
65pub enum NavRole {
66 TextInput,
67 DropDown,
68 Slider,
69}
70
71impl<'a> CxDraw<'a> {
72
73 pub fn lazy_construct_nav_tree(cx: &mut Cx) {
74 if !cx.has_global::<CxNavTreeRc>() {
76 cx.set_global(CxNavTreeRc(Rc::new(RefCell::new(CxNavTree::default()))));
77 }
78 }
79
80 pub fn iterate_nav_stops<F>(cx: &mut Cx, root: DrawListId, mut callback: F) -> Option<(Area, Vec<Area>)> where F: FnMut(&Cx, &NavStop) -> Option<Area> {
81 let nav_tree_rc = cx.get_global::<CxNavTreeRc>().clone();
82 let nav_tree = &*nav_tree_rc.0.borrow();
83 let mut scroll_stack = Vec::new();
84 fn iterate_nav_stops<F>(cx: &Cx, scroll_stack: &mut Vec<Area>, nav_tree: &CxNavTree, draw_list_id: DrawListId, callback: &mut F) -> Option<Area>
85 where F: FnMut(&Cx, &NavStop) -> Option<Area> {
86
87 for i in 0..nav_tree[draw_list_id].nav_list.len() {
88 let nav_item = &nav_tree[draw_list_id].nav_list[i];
89 match nav_item {
90 NavItem::Child(draw_list_id) => {
91 if let Some(area) = iterate_nav_stops(cx, scroll_stack, nav_tree, *draw_list_id, callback) {
92 return Some(area)
93 }
94 }
95 NavItem::Stop(stop) => if let Some(area) = callback(cx, stop) {
96 scroll_stack.push(area);
97 return Some(area)
98 }
99 NavItem::BeginScroll(area)=>{
100 scroll_stack.push(*area);
101 }
102 NavItem::EndScroll(area)=>{
103 if *area != scroll_stack.pop().unwrap(){panic!()};
104 }
105 }
106 }
107 None
108 }
109 if let Some(area) = iterate_nav_stops(cx, &mut scroll_stack, nav_tree, root, &mut callback){
110 Some((area, scroll_stack))
111 }
112 else{
113 None
114 }
115 }
116
117 pub fn nav_list_clear(&mut self, draw_list_id: DrawListId) {
118 let mut nav_tree = self.nav_tree_rc.0.borrow_mut();
119 if draw_list_id.index() >= nav_tree.nav_lists.len() {
120 nav_tree.nav_lists.resize(draw_list_id.index() + 1, Default::default());
121 }
122 nav_tree[draw_list_id].nav_list.clear();
123 }
124
125 pub fn nav_list_item_push(&mut self, draw_list_id: DrawListId, item: NavItem){
126 let mut nav_tree = self.nav_tree_rc.0.borrow_mut();
127 nav_tree[draw_list_id].nav_list.push(item);
128 }
129
130 pub fn add_nav_stop(&mut self, area: Area, role: NavRole, margin: Margin) {
131 let draw_list_id = *self.draw_list_stack.last().unwrap();
132 self.nav_list_item_push(draw_list_id, NavItem::Stop(NavStop {
133 role,
134 area,
135 order: NavOrder::Default,
136 margin
137 }));
138 }
139
140 pub fn add_begin_scroll(&mut self)->NavScrollIndex{
141 let mut nav_tree = self.nav_tree_rc.0.borrow_mut();
142 let draw_list_id = *self.draw_list_stack.last().unwrap();
143 let id = NavScrollIndex(nav_tree[draw_list_id].nav_list.len());
144 nav_tree[draw_list_id].nav_list.push(NavItem::BeginScroll(Area::Empty));
145 id
146 }
147
148 pub fn add_end_scroll(&mut self, index:NavScrollIndex, area:Area){
149 let mut nav_tree = self.nav_tree_rc.0.borrow_mut();
150 let draw_list_id = *self.draw_list_stack.last().unwrap();
151 nav_tree[draw_list_id].nav_list[index.0] = NavItem::BeginScroll(area);
152 nav_tree[draw_list_id].nav_list.push(NavItem::EndScroll(area));
153 }
154}
155
156pub struct NavScrollIndex(usize);