makepad_studio/
run_list.rs

1use {
2    crate::{
3        build_manager::{
4            build_manager::*,
5            build_protocol::*,
6        },
7        app::{AppData, AppAction}, 
8        makepad_widgets::*,
9    },
10    std::env,
11};
12
13live_design!{
14    use link::shaders::*;
15    use link::widgets::*;
16    use link::theme::*;
17     
18    BuildItem = <View> {
19        width: Fill, height: Fit,
20        show_bg: true,
21        
22        draw_bg: {
23            instance is_even: 0.0
24            instance active: 0.0
25            instance hover: 0.0
26            fn pixel(self) -> vec4 {
27                return mix(
28                    mix(
29                        THEME_COLOR_BG_EVEN,
30                        THEME_COLOR_BG_ODD,
31                        self.is_even
32                    ),
33                    THEME_COLOR_OUTSET_ACTIVE,
34                    self.active
35                );
36            }
37        }
38    }
39    
40    RunButton = <CheckBox> {
41        width: Fill,
42        
43        margin: <THEME_MSPACE_H_1> {}
44        draw_bg: {
45            uniform size: 3.5;
46            uniform length: 3.0
47            uniform width: 1.0
48
49            fn pixel(self) -> vec4 {
50                let sdf = Sdf2d::viewport(self.pos * self.rect_size)
51                let left = 3;
52                let sz = self.size;
53                let c = vec2(left + sz, self.rect_size.y * 0.5 - 1);
54                
55                // PAUSE
56                sdf.box(
57                    sz * 0.5,
58                    sz * 2.25,
59                    sz * 0.9,
60                    sz * 3.0,
61                    1.0
62                );
63
64                sdf.box(
65                    sz * 1.75,
66                    sz * 2.25,
67                    sz * 0.9,
68                    sz * 3.0,
69                    1.0
70                );
71
72                sdf.fill(mix(THEME_COLOR_U_HIDDEN, mix(THEME_COLOR_W, THEME_COLOR_LABEL_OUTER_HOVER, self.hover), self.active));
73
74                // PLAY
75                sdf.rotate(self.active * 0.5 * PI + 0.5 * PI, c.x, c.y);
76                sdf.move_to(c.x - sz, c.y + sz);
77                sdf.line_to(c.x, c.y - sz);
78                sdf.line_to(c.x + sz, c.y + sz);
79                sdf.close_path();
80                sdf.fill(mix(mix(THEME_COLOR_U_4, THEME_COLOR_LABEL_OUTER_HOVER, self.hover), THEME_COLOR_U_HIDDEN, self.active));
81
82                return sdf.result
83            }
84        }
85    }
86    
87    pub RunList = {{RunList}}{
88        width: Fill, height: Fill,
89
90        list = <FlatList> {
91            height: Fill, width: Fill,
92            flow: Down,
93            grab_key_focus: true,
94            drag_scrolling: false,
95
96            Target = <BuildItem> {
97                padding: 0,
98                check = <RunButton> { margin: {left: 23} }
99
100                // <Image> {
101                //     width: 20., height: 20.
102                //     svg_file: dep("crate://self/resources/icons/Icon_Search.svg"),
103                // }
104                // platform = <Button> {
105                //     width: 10., height: Fit,
106                //     margin: { right: 5.0}
107                //     align: { x: 0.5, y: 0.5 },
108                //     padding: 0.0
109                //     draw_icon: {
110                //         svg_file: dep("crate://self/resources/icons/Icon_Search.svg"),
111                //         fn get_color(self) -> vec4 { return #FFF3 }
112                //     }
113                //     icon_walk: {
114                //         width: 10., height: Fit
115                //     }
116                //     draw_bg: {
117                //         fn pixel(self) -> vec4 {
118                //             let sdf = Sdf2d::viewport(self.pos * self.rect_size);
119                //             return sdf.result
120                //         }
121                //     }
122                //     text: ""
123                // }
124                // mode = <Button> {
125                //     width: 10., height: Fit,
126                //     margin: { right: 15.0}
127                //     align: { x: 0.5, y: 0.5 },
128                //     padding: 0.0
129                //     draw_icon: {
130                //         svg_file: dep("crate://self/resources/icons/Icon_Search.svg"),
131                //         fn get_color(self) -> vec4 { return #FFF3 }
132                //     }
133                //     icon_walk: {
134                //         width: 10., height: Fit
135                //     }
136                //     draw_bg: {
137                //         fn pixel(self) -> vec4 {
138                //             let sdf = Sdf2d::viewport(self.pos * self.rect_size);
139                //             return sdf.result
140                //         }
141                //     }
142                //     text: ""
143                // }
144            }
145
146            Binary = <BuildItem> {
147                flow: Right
148
149                fold = <FoldButton> {
150                    height: 25, width: 15,
151                    margin: { left: (THEME_SPACE_2) }
152                    animator: { active = { default: off } }
153                    draw_bg: {
154                        uniform size: 3.75;
155                        instance active: 0.0
156                        
157                        fn pixel(self) -> vec4 {
158                            let sdf = Sdf2d::viewport(self.pos * self.rect_size)
159                            let left = 2;
160                            let sz = self.size;
161                            let c = vec2(left + sz, self.rect_size.y * 0.5);
162                            
163                            // PLUS
164                            sdf.box(0.5, sz * 3.0, sz * 2.5, sz * 0.7, 1.0); // rounding = 3rd value
165                            // vertical
166                            sdf.fill_keep(mix((#6), #8, self.hover));
167                            sdf.box(sz * 1.0, sz * 2.125, sz * 0.7, sz * 2.5, 1.0); // rounding = 3rd value
168    
169                            sdf.fill_keep(mix(mix((#6), #8, self.hover), #fff0, self.active))
170    
171                            return sdf.result
172                        }
173                    }
174                }
175                // label = <Label> {width: Fill, margin: {left: 20, top: 7}, padding: 0, draw_text: {wrap: Ellipsis}}
176                check = <RunButton> {}
177            }
178
179            Empty = <BuildItem> {
180                height: Fit, width: Fill,
181                cursor: Default
182            }
183        }
184    }
185}
186
187#[derive(Clone, Debug, DefaultNone)]
188pub enum RunListAction{
189    Create(LiveId, String),
190    Destroy(LiveId),
191    None
192}
193
194#[derive(Clone, Debug, PartialEq, DefaultNone)]
195enum ActionData{
196    RunMain{binary_id: usize},
197    RunTarget{target:BuildTarget, binary_id:usize},
198    FoldBinary{binary_id:usize},
199    None
200}
201
202#[derive(Live, LiveHook, Widget)]
203struct RunList{
204    #[deref] view:View
205}
206
207impl RunList{
208    fn draw_run_list(&mut self, cx: &mut Cx2d, list:&mut FlatList, build_manager:&mut BuildManager){
209        let mut counter = 0u32;
210        for (binary_id, binary) in build_manager.binaries.iter().enumerate() { 
211            let is_even = counter & 1 == 0;
212                            
213            let item_id = LiveId::from_str(&binary.name);
214            let item = list.item(cx, item_id, live_id!(Binary)).unwrap().as_view();
215            item.apply_over(cx, live!{
216                check = {text:(&binary.name)}
217                draw_bg: {is_even: (if is_even {1.0} else {0.0})}
218            });
219            
220            item.fold_button(id!(fold)).set_action_data(ActionData::FoldBinary{binary_id});
221            
222            let cb =  item.check_box(id!(check));
223            cb.set_active(cx, build_manager.active.any_binary_active(&binary.name));
224            cb.set_action_data(ActionData::RunMain{binary_id});
225            
226            item.draw_all(cx, &mut Scope::empty());
227            counter += 1;
228                            
229            if binary.open>0.001 {
230                for i in 0..BuildTarget::len() {
231                    let is_even = counter & 1 == 0;
232                    let item_id = item_id.bytes_append(&i.to_be_bytes());
233                    let item = list.item(cx, item_id, live_id!(Target)).unwrap().as_view();
234                    let height = 25.0 * binary.open;
235                    item.apply_over(cx, live!{
236                        height: (height)
237                        draw_bg: {is_even: (if is_even {1.0} else {0.0})}
238                        check = {text: (BuildTarget::from_id(i).name())}
239                    });
240                    let cb = item.check_box(id!(check));
241                    cb.set_active(cx, build_manager.active.item_id_active(item_id));
242                    
243                    cb.set_action_data(ActionData::RunTarget{target:BuildTarget::from_id(i), binary_id});
244                    item.draw_all(cx, &mut Scope::empty());
245                    counter += 1;
246                }
247            }
248        }
249        while list.space_left(cx)>0.0 {
250            let is_even = counter & 1 == 0;
251            let item_id = LiveId::from_str("empty").bytes_append(&counter.to_be_bytes());
252            let item = list.item(cx, item_id, live_id!(Empty)).unwrap().as_view();
253            let height = list.space_left(cx).min(20.0);
254            item.apply_over(cx, live!{
255                height: (height)
256                draw_bg: {is_even: (if is_even {1.0} else {0.0})}
257            });
258            item.draw_all(cx, &mut Scope::empty());
259            counter += 1;
260        }
261    }
262}
263
264impl WidgetMatchEvent for RunList{
265    fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions, scope: &mut Scope){
266        let build_manager = &mut scope.data.get_mut::<AppData>().unwrap().build_manager;
267        let run_list = self.view.flat_list(id!(list));
268        for (_item_id, item) in run_list.items_with_actions(&actions) {
269            let fb = item.fold_button(id!(fold));
270            if let Some(v) = item.fold_button(id!(fold)).animating(&actions) {
271                // lets find the binary thing to store it on
272                if let ActionData::FoldBinary{binary_id} = fb.action_data().cast_ref(){
273                    build_manager.binaries[*binary_id].open = v;
274                    item.redraw(cx);
275                }
276            }
277            
278            let cb = item.check_box(id!(check));
279            if let Some(change) = cb.changed(&actions) {
280                item.redraw(cx);
281                match cb.action_data().cast_ref(){
282                    ActionData::RunTarget{target, binary_id}=>{
283                        if change{
284                            build_manager.start_active_build(cx, *binary_id, *target);
285                        }
286                        else{
287                            build_manager.stop_active_build(cx, *binary_id, *target);
288                        }
289                    }
290                    ActionData::RunMain{binary_id}=>{
291                        for i in 0..if change{1}else{BuildTarget::len()} {
292                            let target = BuildTarget::from_id(i);
293                            if change{
294                                build_manager.start_active_build(cx, *binary_id, target);
295                            }
296                            else{
297                                build_manager.stop_active_build(cx, *binary_id, target);
298                            }
299                            cx.action(AppAction::ClearLog);
300                        }
301                    }
302                    _=>()
303                }
304            }
305        }
306    }
307}
308
309impl Widget for RunList {
310
311    fn draw_walk(&mut self, cx: &mut Cx2d, scope:&mut Scope, walk:Walk)->DrawStep{
312        while let Some(item) = self.view.draw_walk(cx, scope, walk).step(){
313            if let Some(mut list) = item.as_flat_list().borrow_mut(){
314                self.draw_run_list(cx, &mut *list, &mut scope.data.get_mut::<AppData>().unwrap().build_manager)
315            }
316        }
317        DrawStep::done()
318    }
319    
320    fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope){
321        self.widget_match_event(cx, event, scope);
322        self.view.handle_event(cx, event, scope);
323    }
324}
325 
326impl BuildManager {
327    
328}