1use {
2 crate::{makepad_derive_widget::*, makepad_draw::*, scroll_bars::ScrollBars, widget::*}, makepad_draw::event::FingerLongPressEvent, std::cell::RefCell
3};
4
5live_design! {
6 pub ViewBase = {{View}} {debug:None}
7}
8
9#[derive(Live, LiveHook, Clone, Copy)]
12#[live_ignore]
13pub enum ViewOptimize {
14 #[pick]
15 None,
16 DrawList,
17 Texture,
18}
19
20impl Default for ViewOptimize {
21 fn default() -> Self {
22 Self::None
23 }
24}
25
26#[derive(Live)]
27#[live_ignore]
28pub enum ViewDebug {
29 #[pick]
30 None,
31 R,
32 G,
33 B,
34 M,
35 Margin,
36 P,
37 Padding,
38 A,
39 All,
40 #[live(Vec4::default())]
41 Color(Vec4),
42}
43
44impl LiveHook for ViewDebug {
45 fn skip_apply(
46 &mut self,
47 _cx: &mut Cx,
48 _apply: &mut Apply,
49 index: usize,
50 nodes: &[LiveNode],
51 ) -> Option<usize> {
52 match &nodes[index].value {
53 LiveValue::Vec4(v) => {
54 *self = Self::Color(*v);
55 Some(index + 1)
56 }
57 LiveValue::Color(v) => {
58 *self = Self::Color(Vec4::from_u32(*v));
59 Some(index + 1)
60 }
61 LiveValue::Bool(v) => {
62 if *v {
63 *self = Self::R;
64 } else {
65 *self = Self::None;
66 }
67 Some(index + 1)
68 }
69 LiveValue::Float64(v) => {
70 if *v != 0.0 {
71 *self = Self::R;
72 } else {
73 *self = Self::None;
74 }
75 Some(index + 1)
76 }
77 LiveValue::Int64(v) => {
78 if *v != 0 {
79 *self = Self::R;
80 } else {
81 *self = Self::None;
82 }
83 Some(index + 1)
84 }
85 _ => None,
86 }
87 }
88}
89
90#[derive(Live, LiveHook)]
91#[live_ignore]
92pub enum EventOrder {
93 Down,
94 #[pick]
95 Up,
96 #[live(Default::default())]
97 List(Vec<LiveId>),
98}
99
100impl ViewOptimize {
101 fn is_texture(&self) -> bool {
102 if let Self::Texture = self {
103 true
104 } else {
105 false
106 }
107 }
108 fn is_draw_list(&self) -> bool {
109 if let Self::DrawList = self {
110 true
111 } else {
112 false
113 }
114 }
115 fn needs_draw_list(&self) -> bool {
116 return self.is_texture() || self.is_draw_list();
117 }
118}
119
120#[derive(Live, LiveRegisterWidget, WidgetRef, WidgetSet)]
121pub struct View {
122 #[live]
124 pub draw_bg: DrawColor,
125
126 #[live(false)]
127 pub show_bg: bool,
128
129 #[layout]
130 pub layout: Layout,
131
132 #[walk]
133 pub walk: Walk,
134
135 #[live]
137 dpi_factor: Option<f64>,
138
139 #[live]
140 optimize: ViewOptimize,
141 #[live]
142 debug: ViewDebug,
143 #[live]
144 event_order: EventOrder,
145
146 #[live(true)]
147 pub visible: bool,
148
149 #[live(true)]
150 grab_key_focus: bool,
151 #[live(false)]
152 block_signal_event: bool,
153 #[live]
154 cursor: Option<MouseCursor>,
155 #[live(false)]
156 capture_overload: bool,
157 #[live]
158 scroll_bars: Option<LivePtr>,
159 #[live(false)]
160 design_mode: bool,
161
162 #[rust]
163 find_cache: RefCell<SmallVec<[(u64, WidgetSet);3]>>,
164
165 #[rust]
166 scroll_bars_obj: Option<Box<ScrollBars>>,
167 #[rust]
168 view_size: Option<DVec2>,
169
170 #[rust]
171 area: Area,
172 #[rust]
173 draw_list: Option<DrawList2d>,
174
175 #[rust]
176 texture_cache: Option<ViewTextureCache>,
177 #[rust]
178 defer_walks: SmallVec<[(LiveId, DeferWalk);1]>,
179 #[rust]
180 draw_state: DrawStateWrap<DrawState>,
181 #[rust]
182 children: SmallVec<[(LiveId, WidgetRef);2]>,
183 #[rust]
184 live_update_order: SmallVec<[LiveId;1]>,
185 #[animator]
189 animator: Animator,
190}
191
192struct ViewTextureCache {
193 pass: Pass,
194 _depth_texture: Texture,
195 color_texture: Texture,
196}
197
198impl LiveHook for View {
199 fn before_apply(
200 &mut self,
201 _cx: &mut Cx,
202 apply: &mut Apply,
203 _index: usize,
204 _nodes: &[LiveNode],
205 ) {
206 if let ApplyFrom::UpdateFromDoc { .. } = apply.from {
207 self.live_update_order.clear();
209 self.find_cache.get_mut().clear();
210 }
211 }
212
213 fn after_apply(
214 &mut self,
215 cx: &mut Cx,
216 apply: &mut Apply,
217 _index: usize,
218 _nodes: &[LiveNode],
219 ) {
220 if apply.from.is_update_from_doc(){for (idx, id) in self.live_update_order.iter().enumerate(){
223 if let Some(pos) = self.children.iter().position(|(i,_v)| *i == *id){
225 self.children.swap(idx, pos);
227 }
228 }
229 self.children.truncate(self.live_update_order.len());
231 }
232 if self.optimize.needs_draw_list() && self.draw_list.is_none() {
233 self.draw_list = Some(DrawList2d::new(cx));
234 }
235 if self.scroll_bars.is_some() {
236 if self.scroll_bars_obj.is_none() {
237 self.scroll_bars_obj =
238 Some(Box::new(ScrollBars::new_from_ptr(cx, self.scroll_bars)));
239 }
240 }
241 }
242
243 fn apply_value_instance(
244 &mut self,
245 cx: &mut Cx,
246 apply: &mut Apply,
247 index: usize,
248 nodes: &[LiveNode],
249 ) -> usize {
250
251 let id = nodes[index].id;
252 match apply.from {
253 ApplyFrom::Animate | ApplyFrom::Over => {
254 let node_id = nodes[index].id;
255 if let Some((_,component)) = self.children.iter_mut().find(|(id,_)| *id == node_id) {
256 component.apply(cx, apply, index, nodes)
257 } else {
258 nodes.skip_node(index)
259 }
260 }
261 ApplyFrom::NewFromDoc { .. } | ApplyFrom::UpdateFromDoc { .. } => {
262 if nodes[index].is_instance_prop() {
263 if apply.from.is_update_from_doc(){self.live_update_order.push(id);
265 }
266 if let Some((_,node)) = self.children.iter_mut().find(|(id2,_)| *id2 == id){
268 node.apply(cx, apply, index, nodes)
269 }
270 else{
271 self.children.push((id,WidgetRef::new(cx)));
272 self.children.last_mut().unwrap().1.apply(cx, apply, index, nodes)
273 }
274 } else {
275 cx.apply_error_no_matching_field(live_error_origin!(), index, nodes);
276 nodes.skip_node(index)
277 }
278 }
279 _ => nodes.skip_node(index),
280 }
281 }
282}
283
284#[derive(Clone, Debug, DefaultNone)]
285pub enum ViewAction {
286 None,
287 FingerDown(FingerDownEvent),
288 FingerUp(FingerUpEvent),
289 FingerLongPress(FingerLongPressEvent),
290 FingerMove(FingerMoveEvent),
291 FingerHoverIn(FingerHoverEvent),
292 FingerHoverOut(FingerHoverEvent),
293 KeyDown(KeyEvent),
294 KeyUp(KeyEvent),
295}
296
297impl ViewRef {
298 pub fn finger_down(&self, actions: &Actions) -> Option<FingerDownEvent> {
299 if let Some(item) = actions.find_widget_action(self.widget_uid()) {
300 if let ViewAction::FingerDown(fd) = item.cast() {
301 return Some(fd);
302 }
303 }
304 None
305 }
306
307 pub fn finger_up(&self, actions: &Actions) -> Option<FingerUpEvent> {
308 if let Some(item) = actions.find_widget_action(self.widget_uid()) {
309 if let ViewAction::FingerUp(fd) = item.cast() {
310 return Some(fd);
311 }
312 }
313 None
314 }
315
316 pub fn finger_move(&self, actions: &Actions) -> Option<FingerMoveEvent> {
317 if let Some(item) = actions.find_widget_action(self.widget_uid()) {
318 if let ViewAction::FingerMove(fd) = item.cast() {
319 return Some(fd);
320 }
321 }
322 None
323 }
324
325 pub fn finger_hover_in(&self, actions: &Actions) -> Option<FingerHoverEvent> {
326 if let Some(item) = actions.find_widget_action(self.widget_uid()) {
327 if let ViewAction::FingerHoverIn(fd) = item.cast() {
328 return Some(fd);
329 }
330 }
331 None
332 }
333
334 pub fn finger_hover_out(&self, actions: &Actions) -> Option<FingerHoverEvent> {
335 if let Some(item) = actions.find_widget_action(self.widget_uid()) {
336 if let ViewAction::FingerHoverOut(fd) = item.cast() {
337 return Some(fd);
338 }
339 }
340 None
341 }
342
343 pub fn key_down(&self, actions: &Actions) -> Option<KeyEvent> {
344 if let Some(item) = actions.find_widget_action(self.widget_uid()) {
345 if let ViewAction::KeyDown(fd) = item.cast() {
346 return Some(fd);
347 }
348 }
349 None
350 }
351
352 pub fn key_up(&self, actions: &Actions) -> Option<KeyEvent> {
353 if let Some(item) = actions.find_widget_action(self.widget_uid()) {
354 if let ViewAction::KeyUp(fd) = item.cast() {
355 return Some(fd);
356 }
357 }
358 None
359 }
360
361 pub fn animator_cut(&self, cx: &mut Cx, state: &[LiveId; 2]) {
362 if let Some(mut inner) = self.borrow_mut() {
363 inner.animator_cut(cx, state);
364 }
365 }
366
367 pub fn animator_play(&self, cx: &mut Cx, state: &[LiveId; 2]) {
368 if let Some(mut inner) = self.borrow_mut() {
369 inner.animator_play(cx, state);
370 }
371 }
372
373 pub fn toggle_state(
374 &self,
375 cx: &mut Cx,
376 is_state_1: bool,
377 animate: Animate,
378 state1: &[LiveId; 2],
379 state2: &[LiveId; 2],
380 ) {
381 if let Some(mut inner) = self.borrow_mut() {
382 inner.animator_toggle(cx, is_state_1, animate, state1, state2);
383 }
384 }
385
386 pub fn set_visible(&self, cx: &mut Cx, visible: bool) {
387 if let Some(mut inner) = self.borrow_mut() {
388 inner.set_visible(cx, visible)
389 }
390 }
391
392 pub fn visible(&self) -> bool {
393 if let Some(inner) = self.borrow() {
394 inner.visible()
395 } else {
396 false
397 }
398 }
399
400 pub fn set_texture(&self, slot: usize, texture: &Texture) {
401 if let Some(mut inner) = self.borrow_mut() {
402 inner.draw_bg.set_texture(slot, texture);
403 }
404 }
405
406 pub fn set_uniform(&self, cx: &Cx, uniform: &[LiveId], value: &[f32]) {
407 if let Some(mut inner) = self.borrow_mut() {
408 inner.draw_bg.set_uniform(cx, uniform, value);
409 }
410 }
411
412 pub fn set_scroll_pos(&self, cx: &mut Cx, v: DVec2) {
413 if let Some(mut inner) = self.borrow_mut() {
414 inner.set_scroll_pos(cx, v)
415 }
416 }
417
418 pub fn area(&self) -> Area {
419 if let Some(inner) = self.borrow_mut() {
420 inner.area
421 } else {
422 Area::Empty
423 }
424 }
425
426 pub fn child_count(&self) -> usize {
427 if let Some(inner) = self.borrow_mut() {
428 inner.children.len()
429 } else {
430 0
431 }
432 }
433
434 pub fn set_key_focus(&self, cx: &mut Cx) {
435 if let Some(inner) = self.borrow_mut() {
436 inner.set_key_focus(cx);
437 }
438 }
439}
440
441impl ViewSet {
442 pub fn animator_cut(&self, cx: &mut Cx, state: &[LiveId; 2]) {
443 for item in self.iter() {
444 item.animator_cut(cx, state)
445 }
446 }
447
448 pub fn animator_play(&self, cx: &mut Cx, state: &[LiveId; 2]) {
449 for item in self.iter() {
450 item.animator_play(cx, state);
451 }
452 }
453
454 pub fn toggle_state(
455 &self,
456 cx: &mut Cx,
457 is_state_1: bool,
458 animate: Animate,
459 state1: &[LiveId; 2],
460 state2: &[LiveId; 2],
461 ) {
462 for item in self.iter() {
463 item.toggle_state(cx, is_state_1, animate, state1, state2);
464 }
465 }
466
467 pub fn set_visible(&self, cx:&mut Cx, visible: bool) {
468 for item in self.iter() {
469 item.set_visible(cx, visible)
470 }
471 }
472
473 pub fn set_texture(&self, slot: usize, texture: &Texture) {
474 for item in self.iter() {
475 item.set_texture(slot, texture)
476 }
477 }
478
479 pub fn set_uniform(&self, cx: &Cx, uniform: &[LiveId], value: &[f32]) {
480 for item in self.iter() {
481 item.set_uniform(cx, uniform, value)
482 }
483 }
484
485 pub fn redraw(&self, cx: &mut Cx) {
486 for item in self.iter() {
487 item.redraw(cx);
488 }
489 }
490
491 pub fn finger_down(&self, actions: &Actions) -> Option<FingerDownEvent> {
492 for item in self.iter() {
493 if let Some(e) = item.finger_down(actions) {
494 return Some(e);
495 }
496 }
497 None
498 }
499
500 pub fn finger_up(&self, actions: &Actions) -> Option<FingerUpEvent> {
501 for item in self.iter() {
502 if let Some(e) = item.finger_up(actions) {
503 return Some(e);
504 }
505 }
506 None
507 }
508
509 pub fn finger_move(&self, actions: &Actions) -> Option<FingerMoveEvent> {
510 for item in self.iter() {
511 if let Some(e) = item.finger_move(actions) {
512 return Some(e);
513 }
514 }
515 None
516 }
517
518 pub fn key_down(&self, actions: &Actions) -> Option<KeyEvent> {
519 for item in self.iter() {
520 if let Some(e) = item.key_down(actions) {
521 return Some(e);
522 }
523 }
524 None
525 }
526
527 pub fn key_up(&self, actions: &Actions) -> Option<KeyEvent> {
528 for item in self.iter() {
529 if let Some(e) = item.key_up(actions) {
530 return Some(e);
531 }
532 }
533 None
534 }
535}
536
537impl WidgetNode for View {
538 fn walk(&mut self, _cx: &mut Cx) -> Walk {
539 self.walk
540 }
541
542 fn area(&self)->Area{
543 self.area
544 }
545
546 fn redraw(&mut self, cx: &mut Cx) {
547 self.area.redraw(cx);
548 for (_,child) in &mut self.children {
549 child.redraw(cx);
550 }
551 }
552
553 fn uid_to_widget(&self, uid:WidgetUid)->WidgetRef{
554 for (_,child) in &self.children {
555 let x = child.uid_to_widget(uid);
556 if !x.is_empty(){return x}
557 }
558 WidgetRef::empty()
559 }
560
561 fn find_widgets(&self, path: &[LiveId], cached: WidgetCache, results: &mut WidgetSet) {
562 match cached {
563 WidgetCache::Yes | WidgetCache::Clear => {
564 if let WidgetCache::Clear = cached {
565 self.find_cache.borrow_mut().clear();
566 if path.len() == 0{
567 return
568 }
569 }
570 let mut hash = 0u64;
571 for i in 0..path.len() {
572 hash ^= path[i].0
573 }
574 if let Some((_,widget_set)) = self.find_cache.borrow().iter().find(|(h,_v)| h == &hash) {
575 results.extend_from_set(widget_set);
576 return;
585 }
586 let mut local_results = WidgetSet::empty();
587 if let Some((_,child)) = self.children.iter().find(|(id,_)| *id == path[0]) {
588 if path.len() > 1 {
589 child.find_widgets(&path[1..], WidgetCache::No, &mut local_results);
590 } else {
591 local_results.push(child.clone());
592 }
593 }
594 for (_,child) in &self.children {
595 child.find_widgets(path, WidgetCache::No, &mut local_results);
596 }
597 if !local_results.is_empty() {
598 results.extend_from_set(&local_results);
599 }
600 self.find_cache.borrow_mut().push((hash, local_results));
609 }
610 WidgetCache::No => {
611 if let Some((_,child)) = self.children.iter().find(|(id,_)| *id == path[0]) {
612 if path.len() > 1 {
613 child.find_widgets(&path[1..], WidgetCache::No, results);
614 } else {
615 results.push(child.clone());
616 }
617 }
618 for (_,child) in &self.children {
619 child.find_widgets(path, WidgetCache::No, results);
620 }
621 }
622 }
623 }
624
625 fn set_visible(&mut self, cx:&mut Cx, visible:bool) {
626 if self.visible != visible{
627 self.visible = visible;
628 self.redraw(cx);
629 }
630 }
631
632 fn visible(&self) -> bool {
633 self.visible
634 }
635}
636
637impl Widget for View {
638 fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
639
640 if !self.visible && event.requires_visibility(){
641 return
642 }
643
644 let uid = self.widget_uid();
645 if self.animator_handle_event(cx, event).must_redraw() {
646 self.redraw(cx);
647 }
648
649 if self.block_signal_event {
650 if let Event::Signal = event {
651 return;
652 }
653 }
654 if let Some(scroll_bars) = &mut self.scroll_bars_obj {
655 let mut actions = Vec::new();
656 scroll_bars.handle_main_event(cx, event, scope, &mut actions);
657 if actions.len() > 0 {
658 cx.redraw_area_and_children(self.area);
659 };
660 }
661
662 if cx.widget_query_invalidation_event.is_some() {
665 self.find_cache.borrow_mut().clear();
666 }
667
668 match &self.event_order {
669 EventOrder::Up => {
670 for (id, child) in self.children.iter_mut().rev() {
671 scope.with_id(*id, |scope| {
672 child.handle_event(cx, event, scope);
673 });
674 }
675 }
676 EventOrder::Down => {
677 for (id, child) in self.children.iter_mut() {
678 scope.with_id(*id, |scope| {
679 child.handle_event(cx, event, scope);
680 })
681 }
682 }
683 EventOrder::List(list) => {
684 for id in list {
685 if let Some((_,child)) = self.children.iter_mut().find(|(id2,_)| id2 == id) {
686 scope.with_id(*id, |scope| {
687 child.handle_event(cx, event, scope);
688 })
689 }
690 }
691 }
692 }
693
694 match event.hit_designer(cx, self.area()){
695 HitDesigner::DesignerPick(_e)=>{
696 cx.widget_action(uid, &scope.path, WidgetDesignAction::PickedBody)
697 }
698 _=>()
699 }
700
701 if self.visible && self.cursor.is_some() || self.animator.live_ptr.is_some() {
702 match event.hits_with_capture_overload(cx, self.area(), self.capture_overload) {
703 Hit::FingerDown(e) => {
704 if self.grab_key_focus {
705 cx.set_key_focus(self.area());
706 }
707 cx.widget_action(uid, &scope.path, ViewAction::FingerDown(e));
708 if self.animator.live_ptr.is_some() {
709 self.animator_play(cx, id!(down.on));
710 }
711 }
712 Hit::FingerMove(e) => cx.widget_action(uid, &scope.path, ViewAction::FingerMove(e)),
713 Hit::FingerLongPress(e) => cx.widget_action(uid, &scope.path, ViewAction::FingerLongPress(e)),
714 Hit::FingerUp(e) => {
715 cx.widget_action(uid, &scope.path, ViewAction::FingerUp(e));
716 if self.animator.live_ptr.is_some() {
717 self.animator_play(cx, id!(down.off));
718 }
719 }
720 Hit::FingerHoverIn(e) => {
721 cx.widget_action(uid, &scope.path, ViewAction::FingerHoverIn(e));
722 if let Some(cursor) = &self.cursor {
723 cx.set_cursor(*cursor);
724 }
725 if self.animator.live_ptr.is_some() {
726 self.animator_play(cx, id!(hover.on));
727 }
728 }
729 Hit::FingerHoverOut(e) => {
730 cx.widget_action(uid, &scope.path, ViewAction::FingerHoverOut(e));
731 if self.animator.live_ptr.is_some() {
732 self.animator_play(cx, id!(hover.off));
733 }
734 }
735 Hit::KeyDown(e) => cx.widget_action(uid, &scope.path, ViewAction::KeyDown(e)),
736 Hit::KeyUp(e) => cx.widget_action(uid, &scope.path, ViewAction::KeyUp(e)),
737 _ => (),
738 }
739 }
740
741 if let Some(scroll_bars) = &mut self.scroll_bars_obj {
742 scroll_bars.handle_scroll_event(cx, event, scope, &mut Vec::new());
743 }
744 }
745
746
747 fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
748 if self.draw_state.begin(cx, DrawState::Drawing(0, false)) {
750 if !self.visible {
751 self.draw_state.end();
752 return DrawStep::done();
753 }
754
755 self.defer_walks.clear();
756
757 match self.optimize {
758 ViewOptimize::Texture => {
759 let walk = self.walk_from_previous_size(walk);
760 if !cx.will_redraw(self.draw_list.as_mut().unwrap(), walk) {
761 if let Some(texture_cache) = &self.texture_cache {
762 self.draw_bg
763 .draw_vars
764 .set_texture(0, &texture_cache.color_texture);
765 let mut rect = cx.walk_turtle_with_area(&mut self.area, walk);
766 if false {
769 rect.size *= 2.0 / self.dpi_factor.unwrap_or(1.0);
770 }
771 self.draw_bg.draw_abs(cx, rect);
772 self.area = self.draw_bg.area();
773 cx.set_pass_area(
785 &texture_cache.pass,
786 self.area,
787 );
788 }
790 return DrawStep::done();
791 }
792 if self.texture_cache.is_none() {
794 self.texture_cache = Some(ViewTextureCache {
795 pass: Pass::new(cx),
796 _depth_texture: Texture::new(cx),
797 color_texture: Texture::new(cx),
798 });
799 let texture_cache = self.texture_cache.as_mut().unwrap();
800 texture_cache.color_texture = Texture::new_with_format(
802 cx,
803 TextureFormat::RenderBGRAu8 {
804 size: TextureSize::Auto,
805 initial: true,
806 },
807 );
808 texture_cache.pass.set_color_texture(
809 cx,
810 &texture_cache.color_texture,
811 PassClearColor::ClearWith(vec4(0.0, 0.0, 0.0, 0.0)),
812 );
813 }
814 let texture_cache = self.texture_cache.as_mut().unwrap();
815 cx.make_child_pass(&texture_cache.pass);
816 cx.begin_pass(&texture_cache.pass, self.dpi_factor);
817 self.draw_list.as_mut().unwrap().begin_always(cx)
818 }
819 ViewOptimize::DrawList => {
820 let walk = self.walk_from_previous_size(walk);
821 if self
822 .draw_list
823 .as_mut()
824 .unwrap()
825 .begin(cx, walk)
826 .is_not_redrawing()
827 {
828 cx.walk_turtle_with_area(&mut self.area, walk);
829 return DrawStep::done();
830 }
831 }
832 _ => (),
833 }
834
835 let scroll = if let Some(scroll_bars) = &mut self.scroll_bars_obj {
837 scroll_bars.begin_nav_area(cx);
838 scroll_bars.get_scroll_pos()
839 } else {
840 self.layout.scroll
841 };
842
843 if self.show_bg {
844 self.draw_bg
848 .begin(cx, walk, self.layout.with_scroll(scroll)); } else {
850 cx.begin_turtle(walk, self.layout.with_scroll(scroll)); }
852 }
853
854 while let Some(DrawState::Drawing(step, resume)) = self.draw_state.get() {
855 if step < self.children.len() {
856 if let Some((id,child)) = self.children.get_mut(step) {
858 if child.visible() {
859 let walk = child.walk(cx);
860 if resume {
861 scope.with_id(*id, |scope| child.draw_walk(cx, scope, walk))?;
862 } else if let Some(fw) = cx.defer_walk(walk) {
863 self.defer_walks.push((*id, fw));
864 } else {
865 self.draw_state.set(DrawState::Drawing(step, true));
866 scope.with_id(*id, |scope| child.draw_walk(cx, scope, walk))?;
867 }
868 }
869 }
870 self.draw_state.set(DrawState::Drawing(step + 1, false));
871 } else {
872 self.draw_state.set(DrawState::DeferWalk(0));
873 }
874 }
875
876 while let Some(DrawState::DeferWalk(step)) = self.draw_state.get() {
877 if step < self.defer_walks.len() {
878 let (id, dw) = &mut self.defer_walks[step];
879 if let Some((id, child)) = self.children.iter_mut().find(|(id2,_)|id2 == id) {
880 let walk = dw.resolve(cx);
881 scope.with_id(*id, |scope| child.draw_walk(cx, scope, walk))?;
882 }
883 self.draw_state.set(DrawState::DeferWalk(step + 1));
884 } else {
885 if let Some(scroll_bars) = &mut self.scroll_bars_obj {
886 scroll_bars.draw_scroll_bars(cx);
887 };
888
889 if self.show_bg {
890 if self.optimize.is_texture() {
891 panic!("dont use show_bg and texture caching at the same time");
892 }
893 self.draw_bg.end(cx);
894 self.area = self.draw_bg.area();
895 } else {
896 cx.end_turtle_with_area(&mut self.area);
897 };
898
899 if let Some(scroll_bars) = &mut self.scroll_bars_obj {
900 scroll_bars.set_area(self.area);
901 scroll_bars.end_nav_area(cx);
902 };
903
904 if self.optimize.needs_draw_list() {
905 let rect = self.area.rect(cx);
906 self.view_size = Some(rect.size);
907 self.draw_list.as_mut().unwrap().end(cx);
908
909 if self.optimize.is_texture() {
910 let texture_cache = self.texture_cache.as_mut().unwrap();
911 cx.end_pass(&texture_cache.pass);
912 self.draw_bg
919 .draw_vars
920 .set_texture(0, &texture_cache.color_texture);
921 self.draw_bg.draw_abs(cx, rect);
922 let area = self.draw_bg.area();
923 let texture_cache = self.texture_cache.as_mut().unwrap();
924 cx.set_pass_area(
936 &texture_cache.pass,
937 area,
938 );
939 }
941 }
942 self.draw_state.end();
943 }
944 }
945 match &self.debug {
946 ViewDebug::None => {}
947 ViewDebug::Color(c) => {
948 cx.debug.area(self.area, *c);
949 }
950 ViewDebug::R => {
951 cx.debug.area(self.area, Vec4::R);
952 }
953 ViewDebug::G => {
954 cx.debug.area(self.area, Vec4::G);
955 }
956 ViewDebug::B => {
957 cx.debug.area(self.area, Vec4::B);
958 }
959 ViewDebug::M | ViewDebug::Margin => {
960 let tl = dvec2(self.walk.margin.left, self.walk.margin.top);
961 let br = dvec2(self.walk.margin.right, self.walk.margin.bottom);
962 cx.debug.area_offset(self.area, tl, br, Vec4::B);
963 cx.debug.area(self.area, Vec4::R);
964 }
965 ViewDebug::P | ViewDebug::Padding => {
966 let tl = dvec2(-self.layout.padding.left, -self.walk.margin.top);
967 let br = dvec2(-self.layout.padding.right, -self.layout.padding.bottom);
968 cx.debug.area_offset(self.area, tl, br, Vec4::G);
969 cx.debug.area(self.area, Vec4::R);
970 }
971 ViewDebug::All | ViewDebug::A => {
972 let tl = dvec2(self.walk.margin.left, self.walk.margin.top);
973 let br = dvec2(self.walk.margin.right, self.walk.margin.bottom);
974 cx.debug.area_offset(self.area, tl, br, Vec4::B);
975 let tl = dvec2(-self.layout.padding.left, -self.walk.margin.top);
976 let br = dvec2(-self.layout.padding.right, -self.layout.padding.bottom);
977 cx.debug.area_offset(self.area, tl, br, Vec4::G);
978 cx.debug.area(self.area, Vec4::R);
979 }
980 }
981 DrawStep::done()
982 }
983}
984
985#[derive(Clone)]
986enum DrawState {
987 Drawing(usize, bool),
988 DeferWalk(usize),
989}
990
991impl View {
992 pub fn swap_child(&mut self, pos_a: usize, pos_b: usize){
993 self.children.swap(pos_a, pos_b);
994 }
995
996 pub fn child_index(&mut self, comp:&WidgetRef)->Option<usize>{
997 if let Some(pos) = self.children.iter().position(|(_,w)|{w == comp}){
998 Some(pos)
999 }
1000 else{
1001 None
1002 }
1003 }
1004
1005 pub fn child_at_index(&mut self, index:usize)->Option<&WidgetRef>{
1006 if let Some(f) = self.children.get(index){
1007 Some(&f.1)
1008 }
1009 else{
1010 None
1011 }
1012 }
1013
1014 pub fn set_scroll_pos(&mut self, cx: &mut Cx, v: DVec2) {
1015 if let Some(scroll_bars) = &mut self.scroll_bars_obj {
1016 scroll_bars.set_scroll_pos(cx, v);
1017 } else {
1018 self.layout.scroll = v;
1019 }
1020 }
1021
1022 pub fn area(&self) -> Area {
1023 self.area
1024 }
1025
1026 pub fn walk_from_previous_size(&self, walk: Walk) -> Walk {
1027 let view_size = self.view_size.unwrap_or(DVec2::default());
1028 Walk {
1029 abs_pos: walk.abs_pos,
1030 width: if walk.width.is_fill() {
1031 walk.width
1032 } else {
1033 Size::Fixed(view_size.x)
1034 },
1035 height: if walk.height.is_fill() {
1036 walk.height
1037 } else {
1038 Size::Fixed(view_size.y)
1039 },
1040 margin: walk.margin,
1041 }
1042 }
1043
1044 pub fn child_count(&self) -> usize {
1045 self.children.len()
1046 }
1047
1048 pub fn debug_print_children(&self){
1049 log!("Debug print view children {:?}", self.children.len());
1050 for i in 0..self.children.len(){
1051 log!("Child: {}",self.children[i].0)
1052 }
1053 }
1054
1055 pub fn set_key_focus(&self, cx: &mut Cx) {
1056 cx.set_key_focus(self.draw_bg.area());
1057 }
1058}