makepad_draw/
nav.rs

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        // ok lets fetch/instance our CxFontsAtlasRc
75        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);