makepad_widgets/
view.rs

1use {
2    std::collections::hash_map::HashMap,
3    crate::{
4        makepad_derive_widget::*,
5        makepad_draw::*,
6        widget::*,
7        scroll_bars::ScrollBars,
8    },
9};
10
11live_design!{
12    ViewBase = {{View}} {}
13}
14
15// maybe we should put an enum on the bools like
16
17#[derive(Live, LiveHook)]
18#[live_ignore]
19pub enum ViewOptimize {
20    #[pick] None,
21    DrawList,
22    Texture
23}
24
25
26#[derive(Live, LiveHook)]
27#[live_ignore]
28pub enum EventOrder {
29    Down,
30    #[pick] Up,
31    #[live(Default::default())] List(Vec<LiveId>),
32}
33
34
35impl ViewOptimize {
36    fn is_texture(&self) -> bool {
37        if let Self::Texture = self {true} else {false}
38    }
39    fn is_draw_list(&self) -> bool {
40        if let Self::DrawList = self {true} else {false}
41    }
42    fn needs_draw_list(&self) -> bool {
43        return self.is_texture() || self.is_draw_list()
44    }
45}
46
47#[derive(Live)]
48pub struct View { // draw info per UI element
49    #[live] draw_bg: DrawColor,
50    
51    #[live(false)] show_bg: bool,
52    
53    #[layout] layout: Layout,
54    
55    #[walk] walk: Walk,
56    
57    //#[live] use_cache: bool,
58    #[live] dpi_factor: Option<f64>,
59    
60    #[live] optimize: ViewOptimize,
61    #[live] event_order: EventOrder,
62    
63    #[live(true)] visible: bool,
64    
65    #[live(true)] grab_key_focus: bool,
66    #[live(false)] block_signal_event: bool,
67    #[live] cursor: Option<MouseCursor>,
68    #[live] scroll_bars: Option<LivePtr>,
69    #[live(false)] design_mode: bool,
70    
71    #[rust] find_cache: HashMap<u64, WidgetSet>,
72    
73    #[rust] scroll_bars_obj: Option<Box<ScrollBars >>,
74    #[rust] view_size: Option<DVec2>,
75    
76    #[rust] area: Area,
77    #[rust] draw_list: Option<DrawList2d>,
78    
79    #[rust] texture_cache: Option<ViewTextureCache>,
80    #[rust] defer_walks: Vec<(LiveId, DeferWalk)>,
81    #[rust] draw_state: DrawStateWrap<DrawState>,
82    #[rust] children: ComponentMap<LiveId, WidgetRef>,
83    #[rust] draw_order: Vec<LiveId>,
84    
85    #[animator] animator: Animator,
86}
87
88struct ViewTextureCache {
89    pass: Pass,
90    _depth_texture: Texture,
91    color_texture: Texture,
92}
93
94impl LiveHook for View {
95    fn before_live_design(cx: &mut Cx) {
96        register_widget!(cx, View)
97    }
98    
99    fn before_apply(&mut self, _cx: &mut Cx, from: ApplyFrom, _index: usize, _nodes: &[LiveNode]) {
100        if let ApplyFrom::UpdateFromDoc {..} = from {
101            //self.children.clear();
102            self.draw_order.clear();
103            self.find_cache.clear();
104        }
105    }
106    
107    fn after_apply(&mut self, cx: &mut Cx, _from: ApplyFrom, _index: usize, _nodes: &[LiveNode]) {
108        if self.optimize.needs_draw_list() && self.draw_list.is_none() {
109            self.draw_list = Some(DrawList2d::new(cx));
110        }
111        if self.scroll_bars.is_some() {
112            if self.scroll_bars_obj.is_none() {
113                self.scroll_bars_obj = Some(Box::new(ScrollBars::new_from_ptr(cx, self.scroll_bars)));
114            }
115        }
116        /*
117        if let Some(image_texture) = &mut self.image_texture {
118            if self.image_scale != 0.0 {
119                let texture_desc = image_texture.get_desc(cx);
120                self.walk = Walk::fixed_size(
121                    DVec2 {
122                        x: texture_desc.width.unwrap() as f64 * self.image_scale,
123                        y: texture_desc.height.unwrap() as f64 * self.image_scale
124                    }
125                );
126            }
127        */
128    }
129    
130    fn apply_value_instance(&mut self, cx: &mut Cx, from: ApplyFrom, index: usize, nodes: &[LiveNode]) -> usize {
131        //! TODO
132        // NOTE FOR LIVE RELOAD
133        // the id is always unique
134        // Draw order is never cleared.
135        
136        let id = nodes[index].id;
137        match from {
138            ApplyFrom::Animate | ApplyFrom::ApplyOver => {
139                if let Some(component) = self.children.get_mut(&nodes[index].id) {
140                    component.apply(cx, from, index, nodes)
141                }
142                else {
143                    nodes.skip_node(index)
144                }
145            }
146            ApplyFrom::NewFromDoc {..} | ApplyFrom::UpdateFromDoc {..} => {
147                if nodes[index].origin.has_prop_type(LivePropType::Instance) {
148                    self.draw_order.push(id);
149                    return self.children.get_or_insert(cx, id, | cx | {
150                        WidgetRef::new(cx)
151                    })
152                        .apply(cx, from, index, nodes);
153                }
154                else {
155                    cx.apply_error_no_matching_field(live_error_origin!(), index, nodes);
156                    nodes.skip_node(index)
157                }
158            }
159            _ => {
160                nodes.skip_node(index)
161            }
162        }
163    }
164}
165
166#[derive(Clone, PartialEq, WidgetRef)]
167pub struct ViewRef(WidgetRef);
168
169
170#[derive(Clone, WidgetSet)]
171pub struct ViewSet(WidgetSet);
172
173#[derive(Clone, WidgetAction)]
174pub enum ViewAction {
175    None,
176    FingerDown(FingerDownEvent),
177    FingerUp(FingerUpEvent),
178    FingerMove(FingerMoveEvent),
179    KeyDown(KeyEvent),
180    KeyUp(KeyEvent),
181}
182
183impl ViewRef {
184    pub fn finger_down(&self, actions: &WidgetActions) -> Option<FingerDownEvent> {
185        if let Some(item) = actions.find_single_action(self.widget_uid()) {
186            if let ViewAction::FingerDown(fd) = item.action() {
187                return Some(fd)
188            }
189        }
190        None
191    }
192    
193    pub fn finger_up(&self, actions: &WidgetActions) -> Option<FingerUpEvent> {
194        if let Some(item) = actions.find_single_action(self.widget_uid()) {
195            if let ViewAction::FingerUp(fd) = item.action() {
196                return Some(fd)
197            }
198        }
199        None
200    }
201    
202    pub fn finger_move(&self, actions: &WidgetActions) -> Option<FingerMoveEvent> {
203        if let Some(item) = actions.find_single_action(self.widget_uid()) {
204            if let ViewAction::FingerMove(fd) = item.action() {
205                return Some(fd)
206            }
207        }
208        None
209    }
210    
211    pub fn key_down(&self, actions: &WidgetActions) -> Option<KeyEvent> {
212        if let Some(item) = actions.find_single_action(self.widget_uid()) {
213            if let ViewAction::KeyDown(fd) = item.action() {
214                return Some(fd)
215            }
216        }
217        None
218    }
219    
220    pub fn key_up(&self, actions: &WidgetActions) -> Option<KeyEvent> {
221        if let Some(item) = actions.find_single_action(self.widget_uid()) {
222            if let ViewAction::KeyUp(fd) = item.action() {
223                return Some(fd)
224            }
225        }
226        None
227    }
228    
229    pub fn cut_state(&self, cx: &mut Cx, state: &[LiveId; 2]) {
230        if let Some(mut inner) = self.borrow_mut() {
231            inner.animator_cut(cx, state);
232        }
233    }
234    
235    pub fn animator_play(&self, cx: &mut Cx, state: &[LiveId; 2]) {
236        if let Some(mut inner) = self.borrow_mut() {
237            inner.animator_play(cx, state);
238        }
239    }
240    
241    pub fn toggle_state(&self, cx: &mut Cx, is_state_1: bool, animate: Animate, state1: &[LiveId; 2], state2: &[LiveId; 2]) {
242        if let Some(mut inner) = self.borrow_mut() {
243            inner.animator_toggle(cx, is_state_1, animate, state1, state2);
244        }
245    }
246    
247    pub fn set_visible(&self, visible: bool) {
248        if let Some(mut inner) = self.borrow_mut() {
249            inner.visible = visible
250        }
251    }
252    
253    
254    pub fn set_visible_and_redraw(&self, cx: &mut Cx, visible: bool) {
255        if let Some(mut inner) = self.borrow_mut() {
256            inner.visible = visible;
257            inner.redraw(cx);
258        }
259    }
260    
261    pub fn visible(&self) -> bool {
262        if let Some(inner) = self.borrow() {
263            inner.visible
264        }
265        else {
266            false
267        }
268    }
269    
270    pub fn set_texture(&self, slot: usize, texture: &Texture) {
271        if let Some(mut inner) = self.borrow_mut() {
272            inner.draw_bg.set_texture(slot, texture);
273        }
274    }
275    
276    pub fn set_uniform(&self, cx: &Cx, uniform: &[LiveId], value: &[f32]) {
277        if let Some(mut inner) = self.borrow_mut() {
278            inner.draw_bg.set_uniform(cx, uniform, value);
279        }
280    }
281    
282    pub fn set_scroll_pos(&self, cx: &mut Cx, v: DVec2) {
283        if let Some(mut inner) = self.borrow_mut() {
284            inner.set_scroll_pos(cx, v)
285        }
286    }
287    
288    pub fn area(&self) -> Area {
289        if let Some(inner) = self.borrow_mut() {
290            inner.area
291        }
292        else {
293            Area::Empty
294        }
295    }
296    
297    pub fn child_count(&self) -> usize {
298        if let Some(inner) = self.borrow_mut() {
299            inner.draw_order.len()
300        }
301        else {
302            0
303        }
304    }
305}
306
307impl ViewSet {
308    
309    pub fn cut_state(&mut self, cx: &mut Cx, state: &[LiveId; 2]) {
310        for item in self.iter() {
311            item.cut_state(cx, state)
312        }
313    }
314    
315    pub fn animator_play(&mut self, cx: &mut Cx, state: &[LiveId; 2]) {
316        for item in self.iter() {
317            item.animator_play(cx, state);
318        }
319    }
320    
321    pub fn toggle_state(&mut self, cx: &mut Cx, is_state_1: bool, animate: Animate, state1: &[LiveId; 2], state2: &[LiveId; 2]) {
322        for item in self.iter() {
323            item.toggle_state(cx, is_state_1, animate, state1, state2);
324        }
325    }
326    
327    pub fn set_visible(&self, visible: bool) {
328        for item in self.iter() {
329            item.set_visible(visible)
330        }
331    }
332    
333    pub fn set_texture(&self, slot: usize, texture: &Texture) {
334        for item in self.iter() {
335            item.set_texture(slot, texture)
336        }
337    }
338    
339    pub fn set_uniform(&self, cx: &Cx, uniform: &[LiveId], value: &[f32]) {
340        for item in self.iter() {
341            item.set_uniform(cx, uniform, value)
342        }
343    }
344    
345    pub fn redraw(&self, cx: &mut Cx) {
346        for item in self.iter() {
347            item.redraw(cx);
348        }
349    }
350    
351    pub fn finger_down(&self, actions: &WidgetActions) -> Option<FingerDownEvent> {
352        for item in self.iter() {
353            if let Some(e) = item.finger_down(actions) {
354                return Some(e)
355            }
356        }
357        None
358    }
359    
360    pub fn finger_up(&self, actions: &WidgetActions) -> Option<FingerUpEvent> {
361        for item in self.iter() {
362            if let Some(e) = item.finger_up(actions) {
363                return Some(e)
364            }
365        }
366        None
367    }
368    
369    
370    pub fn finger_move(&self, actions: &WidgetActions) -> Option<FingerMoveEvent> {
371        for item in self.iter() {
372            if let Some(e) = item.finger_move(actions) {
373                return Some(e)
374            }
375        }
376        None
377    }
378    
379    pub fn key_down(&self, actions: &WidgetActions) -> Option<KeyEvent> {
380        for item in self.iter() {
381            if let Some(e) = item.key_down(actions) {
382                return Some(e)
383            }
384        }
385        None
386    }
387    
388    pub fn key_up(&self, actions: &WidgetActions) -> Option<KeyEvent> {
389        for item in self.iter() {
390            if let Some(e) = item.key_up(actions) {
391                return Some(e)
392            }
393        }
394        None
395    }
396}
397
398impl Widget for View {
399    fn handle_widget_event_with(
400        &mut self,
401        cx: &mut Cx,
402        event: &Event,
403        dispatch_action: &mut dyn FnMut(&mut Cx, WidgetActionItem)
404    ) {
405        let uid = self.widget_uid();
406        if self.animator_handle_event(cx, event).must_redraw() {
407            self.redraw(cx);
408        }
409        
410        if self.block_signal_event {
411            if let Event::Signal = event {
412                return
413            }
414        }
415        if let Some(scroll_bars) = &mut self.scroll_bars_obj {
416            let mut redraw = false;
417            scroll_bars.handle_main_event(cx, event, &mut | _, _ | {
418                // lets invalidate all children
419                redraw = true;
420            });
421            if redraw {
422                cx.redraw_area_and_children(self.area);
423            }
424        }
425        
426        match &self.event_order {
427            EventOrder::Up => {
428                for id in self.draw_order.iter().rev() {
429                    if let Some(child) = self.children.get_mut(id) {
430                        if child.is_visible() || !event.requires_visibility() {
431                            child.handle_widget_event_with(cx, event, dispatch_action);
432                        }
433                    }
434                }
435            }
436            EventOrder::Down => {
437                for id in self.draw_order.iter() {
438                    if let Some(child) = self.children.get_mut(id) {
439                        if child.is_visible() || !event.requires_visibility() {
440                            child.handle_widget_event_with(cx, event, dispatch_action);
441                        }
442                    }
443                }
444            }
445            EventOrder::List(list) => {
446                for id in list {
447                    if let Some(child) = self.children.get_mut(id) {
448                        if child.is_visible() || !event.requires_visibility() {
449                            child.handle_widget_event_with(cx, event, dispatch_action);
450                        }
451                    }
452                }
453            }
454        }
455        
456        
457        if self.visible && self.cursor.is_some() || self.animator.live_ptr.is_some() {
458            match event.hits(cx, self.area()) {
459                Hit::FingerDown(e) => {
460                    if self.grab_key_focus {
461                        cx.set_key_focus(self.area());
462                    }
463                    dispatch_action(cx, ViewAction::FingerDown(e).into_action(uid));
464                    if self.animator.live_ptr.is_some() {
465                        self.animator_play(cx, id!(down.on));
466                    }
467                }
468                Hit::FingerMove(e) => {
469                    dispatch_action(cx, ViewAction::FingerMove(e).into_action(uid))
470                }
471                Hit::FingerUp(e) => {
472                    dispatch_action(cx, ViewAction::FingerUp(e).into_action(uid));
473                    if self.animator.live_ptr.is_some() {
474                        self.animator_play(cx, id!(down.off));
475                    }
476                }
477                Hit::FingerHoverIn(_) => {
478                    if let Some(cursor) = &self.cursor {
479                        cx.set_cursor(*cursor);
480                    }
481                    if self.animator.live_ptr.is_some() {
482                        self.animator_play(cx, id!(hover.on));
483                    }
484                }
485                Hit::FingerHoverOut(_) => {
486                    if self.animator.live_ptr.is_some() {
487                        self.animator_play(cx, id!(hover.off));
488                    }
489                }
490                Hit::KeyDown(e) => {
491                    dispatch_action(cx, ViewAction::KeyDown(e).into_action(uid))
492                }
493                Hit::KeyUp(e) => {
494                    dispatch_action(cx, ViewAction::KeyUp(e).into_action(uid))
495                }
496                _ => ()
497            }
498        }
499        
500        if let Some(scroll_bars) = &mut self.scroll_bars_obj {
501            scroll_bars.handle_scroll_event(cx, event, &mut | _, _ | {});
502        }
503    }
504    
505    fn is_visible(&self) -> bool {
506        self.visible
507    }
508    
509    fn walk(&mut self, _cx: &mut Cx) -> Walk {
510        self.walk
511    }
512    
513    fn draw_walk_widget(&mut self, cx: &mut Cx2d, walk: Walk) -> WidgetDraw {
514        self.draw_walk(cx, walk)
515    }
516    
517    fn redraw(&mut self, cx: &mut Cx) {
518        self.area.redraw(cx);
519        for child in self.children.values_mut() {
520            child.redraw(cx);
521        }
522    }
523    
524    fn find_widgets(&mut self, path: &[LiveId], cached: WidgetCache, results: &mut WidgetSet) {
525        match cached {
526            WidgetCache::Yes | WidgetCache::Clear => {
527                if let WidgetCache::Clear = cached {
528                    self.find_cache.clear();
529                }
530                let mut hash = 0u64;
531                for i in 0..path.len() {
532                    hash ^= path[i].0
533                }
534                if let Some(widget_set) = self.find_cache.get(&hash) {
535                    results.extend_from_set(widget_set);
536                    return
537                }
538                let mut local_results = WidgetSet::empty();
539                if let Some(child) = self.children.get_mut(&path[0]) {
540                    if path.len()>1 {
541                        child.find_widgets(&path[1..], WidgetCache::No, &mut local_results);
542                    }
543                    else {
544                        local_results.push(child.clone());
545                    }
546                }
547                for child in self.children.values_mut() {
548                    child.find_widgets(path, WidgetCache::No, &mut local_results);
549                }
550                if !local_results.is_empty() {
551                    results.extend_from_set(&local_results);
552                }
553                self.find_cache.insert(hash, local_results);
554            }
555            WidgetCache::No => {
556                if let Some(child) = self.children.get_mut(&path[0]) {
557                    if path.len()>1 {
558                        child.find_widgets(&path[1..], WidgetCache::No, results);
559                    }
560                    else {
561                        results.push(child.clone());
562                    }
563                }
564                for child in self.children.values_mut() {
565                    child.find_widgets(path, WidgetCache::No, results);
566                }
567            }
568        }
569    }
570}
571
572#[derive(Clone)]
573enum DrawState {
574    Drawing(usize, bool),
575    DeferWalk(usize)
576}
577
578impl View {
579    
580    pub fn set_scroll_pos(&mut self, cx: &mut Cx, v: DVec2) {
581        if let Some(scroll_bars) = &mut self.scroll_bars_obj {
582            scroll_bars.set_scroll_pos(cx, v);
583        }
584        else {
585            self.layout.scroll = v;
586        }
587    }
588    
589    pub fn area(&self) -> Area {
590        self.area
591    }
592    
593    pub fn walk_from_previous_size(&self, walk: Walk) -> Walk {
594        let view_size = self.view_size.unwrap_or(DVec2::default());
595        Walk {
596            abs_pos: walk.abs_pos,
597            width: if walk.width.is_fill() {walk.width}else {Size::Fixed(view_size.x)},
598            height: if walk.height.is_fill() {walk.height}else {Size::Fixed(view_size.y)},
599            margin: walk.margin
600        }
601    }
602    
603    pub fn draw_walk(&mut self, cx: &mut Cx2d, walk: Walk) -> WidgetDraw {
604        // the beginning state
605        if self.draw_state.begin(cx, DrawState::Drawing(0, false)) {
606            if !self.visible {
607                self.draw_state.end();
608                return WidgetDraw::done()
609            }
610            
611            self.defer_walks.clear();
612            
613            match self.optimize {
614                ViewOptimize::Texture => {
615                    let walk = self.walk_from_previous_size(walk);
616                    if !cx.will_redraw(self.draw_list.as_mut().unwrap(), walk) {
617                        if let Some(texture_cache) = &self.texture_cache {
618                            self.draw_bg.draw_vars.set_texture(0, &texture_cache.color_texture);
619                            let mut rect = cx.walk_turtle_with_area(&mut self.area, walk);
620                            rect.size *= 2.0 / self.dpi_factor.unwrap_or(1.0);
621                            self.draw_bg.draw_abs(cx, rect);
622                            self.area = self.draw_bg.area();
623                            cx.set_pass_scaled_area(&texture_cache.pass, self.area, 2.0 / self.dpi_factor.unwrap_or(1.0));
624                        }
625                        return WidgetDraw::done()
626                    }
627                    // lets start a pass
628                    if self.texture_cache.is_none() {
629                        self.texture_cache = Some(ViewTextureCache {
630                            pass: Pass::new(cx),
631                            _depth_texture: Texture::new(cx),
632                            color_texture: Texture::new(cx)
633                        });
634                        let texture_cache = self.texture_cache.as_mut().unwrap();
635                        //cache.pass.set_depth_texture(cx, &cache.depth_texture, PassClearDepth::ClearWith(1.0));
636                        texture_cache.pass.add_color_texture(cx, &texture_cache.color_texture, PassClearColor::ClearWith(vec4(0.0, 0.0, 0.0, 0.0)));
637                    }
638                    let texture_cache = self.texture_cache.as_mut().unwrap();
639                    cx.make_child_pass(&texture_cache.pass);
640                    cx.begin_pass(&texture_cache.pass, self.dpi_factor);
641                    self.draw_list.as_mut().unwrap().begin_always(cx)
642                }
643                ViewOptimize::DrawList => {
644                    let walk = self.walk_from_previous_size(walk);
645                    if self.draw_list.as_mut().unwrap().begin(cx, walk).is_not_redrawing() {
646                        cx.walk_turtle_with_area(&mut self.area, walk);
647                        return WidgetDraw::done()
648                    }
649                }
650                _ => ()
651            }
652            
653            
654            // ok so.. we have to keep calling draw till we return LiveId(0)
655            let scroll = if let Some(scroll_bars) = &mut self.scroll_bars_obj {
656                scroll_bars.begin_nav_area(cx);
657                scroll_bars.get_scroll_pos()
658            }
659            else {
660                self.layout.scroll
661            };
662            
663            if self.show_bg {
664                /*if let Some(image_texture) = &self.image_texture {
665                    self.draw_bg.draw_vars.set_texture(0, image_texture);
666                }*/
667                self.draw_bg.begin(cx, walk, self.layout.with_scroll(scroll)); //.with_scale(2.0 / self.dpi_factor.unwrap_or(2.0)));
668            }
669            else {
670                cx.begin_turtle(walk, self.layout.with_scroll(scroll)); //.with_scale(2.0 / self.dpi_factor.unwrap_or(2.0)));
671            }
672        }
673        
674        while let Some(DrawState::Drawing(step, resume)) = self.draw_state.get() {
675            if step < self.draw_order.len() {
676                let id = self.draw_order[step];
677                if let Some(child) = self.children.get_mut(&id) {
678                    if child.is_visible() {
679                        let walk = child.walk(cx);
680                        if resume {
681                            child.draw_walk_widget(cx, walk) ?;
682                        }
683                        else if let Some(fw) = cx.defer_walk(walk) {
684                            self.defer_walks.push((id, fw));
685                        }
686                        else {
687                            self.draw_state.set(DrawState::Drawing(step, true));
688                            child.draw_walk_widget(cx, walk) ?;
689                        }
690                    }
691                }
692                self.draw_state.set(DrawState::Drawing(step + 1, false));
693            }
694            else {
695                self.draw_state.set(DrawState::DeferWalk(0));
696            }
697        }
698        
699        while let Some(DrawState::DeferWalk(step)) = self.draw_state.get() {
700            if step < self.defer_walks.len() {
701                let (id, dw) = &mut self.defer_walks[step];
702                if let Some(child) = self.children.get_mut(&id) {
703                    let walk = dw.resolve(cx);
704                    child.draw_walk_widget(cx, walk) ?;
705                }
706                self.draw_state.set(DrawState::DeferWalk(step + 1));
707            }
708            else {
709                if let Some(scroll_bars) = &mut self.scroll_bars_obj {
710                    scroll_bars.draw_scroll_bars(cx);
711                };
712                
713                if self.show_bg {
714                    if self.optimize.is_texture() {
715                        panic!("dont use show_bg and texture cazching at the same time");
716                    }
717                    self.draw_bg.end(cx);
718                    self.area = self.draw_bg.area();
719                }
720                else {
721                    cx.end_turtle_with_area(&mut self.area);
722                };
723                
724                if let Some(scroll_bars) = &mut self.scroll_bars_obj {
725                    scroll_bars.set_area(self.area);
726                    scroll_bars.end_nav_area(cx);
727                };
728                
729                if self.optimize.needs_draw_list() {
730                    let rect = self.area.get_rect(cx);
731                    self.view_size = Some(rect.size);
732                    self.draw_list.as_mut().unwrap().end(cx);
733                    
734                    if self.optimize.is_texture() {
735                        let texture_cache = self.texture_cache.as_mut().unwrap();
736                        cx.end_pass(&texture_cache.pass);
737                        /*if cache.pass.id_equals(4){
738                            self.draw_bg.draw_vars.set_uniform(cx, id!(marked),&[1.0]);
739                        }
740                        else{
741                            self.draw_bg.draw_vars.set_uniform(cx, id!(marked),&[0.0]);
742                        }*/
743                        self.draw_bg.draw_vars.set_texture(0, &texture_cache.color_texture);
744                        self.draw_bg.draw_abs(cx, rect);
745                        let area = self.draw_bg.area();
746                        let texture_cache = self.texture_cache.as_mut().unwrap();
747                        cx.set_pass_scaled_area(&texture_cache.pass, area, 2.0 / self.dpi_factor.unwrap_or(1.0));
748                    }
749                }
750                self.draw_state.end();
751            }
752        }
753        WidgetDraw::done()
754    }
755    
756    pub fn child_count(&self) -> usize {
757        self.draw_order.len()
758    }
759}
760