1use {
2 std::{
3 collections::{HashSet},
4 },
5 crate::{
6 makepad_derive_widget::*,
7 makepad_draw::*,
8 widget::*,
9 fold_button::*,
10 scroll_shadow::DrawScrollShadow,
11 scroll_bars::ScrollBars
12 }
13};
14
15live_design!{
16 use link::theme::*;
17 use makepad_draw::shader::std::*;
18 use link::widgets::*;
19 use crate::designer_theme::*;
20
21 DrawNodeQuad = {{DrawNodeQuad}} {}
22 DrawNodeText = {{DrawNodeText}} {}
23 DrawNodeIcon = {{DrawNodeIcon}} {}
24
25 pub DesignerOutlineTreeNodeBase = {{DesignerOutlineTreeNode}} {}
26 pub DesignerOutlineTreeBase = {{DesignerOutlineTree}} {}
27
28 pub DesignerOutlineTreeNode = <DesignerOutlineTreeNodeBase> {
29 align: { y: 0.5 }
30 padding: { left: (THEME_SPACE_1) },
31
32 indent_width: 10.0
33 min_drag_distance: 10.0
34 button_open_width: 24.0,
35 draw_eye: false,
36
37 draw_bg: {
38 instance selected: 0.0
39 instance hover: 0.0
40 instance focussed: 0.0
41
42 fn pixel(self) -> vec4 {
43 let sdf = Sdf2d::viewport(self.pos * self.rect_size);
44 sdf.box(
45 0.,
46 -2.,
47 self.rect_size.x,
48 self.rect_size.y + 3.0,
49 1.
50 )
51 sdf.fill_keep(
52 mix(
53 mix(
54 THEME_COLOR_BG_EVEN,
55 THEME_COLOR_BG_ODD,
56 self.is_even
57 ),
58 THEME_COLOR_OUTSET_ACTIVE,
59 self.selected
60 )
61 )
62 return sdf.result
63 }
64 }
65 icon_walk:{
66 margin:{top:3,left:3,right:5}
67 width:12,
68 height:12,
69 }
70 draw_icon: {
71 instance selected: 0.0
72 instance hover: 0.0
73 instance focussed: 0.0
74 fn get_color(self) -> vec4 {
75 return self.color * self.scale;
76 }
77 }
78
79 draw_text: {
80 instance selected: 0.0
81 instance hover: 0.0
82 instance focussed: 0.0
83 fn get_color(self) -> vec4 {
84 return mix(
85 THEME_COLOR_LABEL_OUTER * self.scale,
86 THEME_COLOR_LABEL_OUTER_ACTIVE,
87 self.selected
88 )
89 }
90
91 text_style: <THEME_FONT_REGULAR> {
92 font_size: (THEME_FONT_SIZE_P)
93 }
95 }
96
97 button_open: <FoldButton> {
98 height: 25, width: 15,
99 margin: { left: (THEME_SPACE_2) }
100 animator: { active = { default: off } },
101 draw_bg: {
102 uniform size: 3.75;
103 instance open: 0.0
104
105 fn pixel(self) -> vec4 {
106 let sdf = Sdf2d::viewport(self.pos * self.rect_size)
107 let left = 2;
108 let sz = self.size;
109 let c = vec2(left + sz, self.rect_size.y * 0.5);
110
111 sdf.box(0.5, sz * 3.0, sz * 2.5, sz * 0.7, 1.0); sdf.fill_keep(mix(#8F, #FF, self.hover));
115 sdf.box(sz * 1.0, sz * 2.125, sz * 0.7, sz * 2.5, 1.0); sdf.fill_keep(mix(mix(#8F, #FF, self.hover), #FFF0, self.active))
118
119 return sdf.result
120 }
121 }
122 }
123
124 animator: {
125 hover = {
126 default: off
127 off = {
128 from: {all: Forward {duration: 0.2}}
129 apply: {
130 hover: 0.0
131 draw_bg: {hover: 0.0}
132 draw_text: {hover: 0.0}
133 draw_icon: {hover: 0.0}
134 }
135 }
136
137 on = {
138 cursor: Hand
139 from: {all: Snap}
140 apply: {
141 hover: 1.0
142 draw_bg: {hover: 1.0}
143 draw_text: {hover: 1.0}
144 draw_icon: {hover: 1.0}
145 },
146 }
147 }
148
149 focus = {
150 default: on
151 on = {
152 from: {all: Snap}
153 apply: {focussed: 1.0}
154 }
155
156 off = {
157 from: {all: Forward {duration: 0.1}}
158 apply: {focussed: 0.0}
159 }
160 }
161
162 select = {
163 default: off
164 off = {
165 from: {all: Forward {duration: 0.1}}
166 apply: {
167 selected: 0.0
168 draw_bg: {selected: 0.0}
169 draw_text: {selected: 0.0}
170 draw_icon: {selected: 0.0}
171 }
172 }
173 on = {
174 from: {all: Snap}
175 apply: {
176 selected: 1.0
177 draw_bg: {selected: 1.0}
178 draw_text: {selected: 1.0}
179 draw_icon: {selected: 1.0}
180 }
181 }
182
183 }
184 }
185 }
186
187 STUDIO_PALETTE_1 = #B2FF64
188 STUDIO_PALETTE_2 = #80FFBF
189 STUDIO_PALETTE_3 = #80BFFF
190 STUDIO_PALETTE_4 = #BF80FF
191 STUDIO_PALETTE_5 = #FF80BF
192 STUDIO_PALETTE_6 = #FFB368
193 STUDIO_PALETTE_7 = #FFD864
194
195 STUDIO_COLOR_FILE = (THEME_COLOR_LABEL_OUTER)
196 STUDIO_COLOR_FOLDER = (THEME_COLOR_LABEL_OUTER)
197 STUDIO_COLOR_LAYOUT = (STUDIO_PALETTE_6)
198 STUDIO_COLOR_WIDGET = (STUDIO_PALETTE_2)
199 STUDIO_COLOR_ASSET = (STUDIO_PALETTE_5)
200 STUDIO_COLOR_TEXT = (STUDIO_PALETTE_1)
201
202 pub DesignerOutlineTree = <DesignerOutlineTreeBase> {
203 flow: Down,
204
205 scroll_bars: <ScrollBars> {}
206 scroll_bars: {}
207 node_height: (THEME_DATA_ITEM_HEIGHT),
208 clip_x: true,
209 clip_y: true
210
211 File = <DesignerOutlineTreeNode> {
212 draw_eye: true,
213 draw_icon: {
214 color: (STUDIO_COLOR_FILE)
215 svg_file: dep("crate://self/resources/icons/icon_file.svg"),
216 }
217 }
218
219 Folder = <DesignerOutlineTreeNode> {
220 draw_icon: {
221 color: (STUDIO_COLOR_FOLDER)
222 svg_file: dep("crate://self/resources/icons/icon_folder.svg"),
223 }
224 }
225
226 Layout = <DesignerOutlineTreeNode> {
227 draw_icon: {
228 color: (STUDIO_COLOR_LAYOUT)
229 svg_file: dep("crate://self/resources/icons/icon_layout.svg"),
230 }
231 }
232
233 Widget = <DesignerOutlineTreeNode> {
234 draw_icon: {
235 color: (STUDIO_COLOR_WIDGET)
236 svg_file: dep("crate://self/resources/icons/icon_widget.svg"),
237 }
238 }
239
240 Asset = <DesignerOutlineTreeNode> {
241 draw_icon: {
242 color: (STUDIO_COLOR_ASSET)
243 svg_file: dep("crate://self/resources/icons/icon_image.svg"),
244 }
245 }
246
247 Text = <DesignerOutlineTreeNode> {
248 draw_icon: {
249 color: (STUDIO_COLOR_TEXT)
250 svg_file: dep("crate://self/resources/icons/icon_text.svg"),
251 }
252 }
253
254 filler: {
255 fn pixel(self) -> vec4 {
256 return mix(
257 THEME_COLOR_BG_EVEN,
258 THEME_COLOR_BG_ODD,
259 self.is_even
260 );
261 }
262 }
263 }
264}
265
266#[derive(Live, LiveHook, LiveRegister)]#[repr(C)]
268struct DrawNodeQuad {
269 #[deref] draw_super: DrawQuad,
270 #[live] is_even: f32,
271 #[live] scale: f32,
272}
273
274#[derive(Live, LiveHook, LiveRegister)]#[repr(C)]
276struct DrawNodeIcon {
277 #[deref] draw_super: DrawIcon,
278 #[live] scale: f32,
279}
280
281#[derive(Live, LiveHook, LiveRegister)]#[repr(C)]
283struct DrawNodeText {
284 #[deref] draw_super: DrawText,
285 #[live] scale: f32,
286}
287
288#[derive(Live, LiveHook, LiveRegister)]
289pub struct DesignerOutlineTreeNode {
290 #[live] draw_bg: DrawNodeQuad,
291 #[live] button_open: FoldButton,
292 #[live] draw_icon: DrawNodeIcon,
293 #[live] draw_text: DrawNodeText,
294 #[live] icon_walk: Walk,
295 #[live] button_open_width: f64,
296 #[live] draw_eye: bool,
297 #[layout] layout: Layout,
298
299 #[animator] animator: Animator,
300
301 #[live] min_drag_distance: f64,
302 #[live] indent_width: f64,
303 #[live] indent_shift: f64,
304
305 #[live] selected: f64,
306 #[live] opened: f64,
307 #[live] hover: f64,
308 #[live] focussed: f64
309}
310
311#[derive(Live, Widget)]
312pub struct DesignerOutlineTree {
313 #[redraw] #[live] scroll_bars: ScrollBars,
314
315 #[rust] templates: ComponentMap<LiveId, LivePtr>,
316
317 #[walk] walk: Walk,
318 #[layout] layout: Layout,
319 #[live] filler: DrawNodeQuad,
320
321 #[live] node_height: f64,
322
323 #[live] draw_scroll_shadow: DrawScrollShadow,
324
325 #[rust] draw_state: DrawStateWrap<()>,
326
327 #[rust] dragging_node_id: Option<LiveId>,
328 #[rust] selected_node_id: Option<LiveId>,
329 #[rust] open_nodes: HashSet<LiveId>,
330 #[rust] scroll_into_view_id: Option<LiveId>,
331 #[rust] scroll_into_view_rect: Option<Rect>,
332
333 #[rust] tree_nodes: ComponentMap<LiveId, (DesignerOutlineTreeNode, LiveId)>,
334
335 #[rust] count: usize,
336 #[rust] stack: Vec<f64>,
337}
338
339impl LiveHook for DesignerOutlineTree {
340 fn before_apply(&mut self, _cx: &mut Cx, apply: &mut Apply, _index: usize, _nodes: &[LiveNode]) {
341 if let ApplyFrom::UpdateFromDoc {..} = apply.from {
342 self.templates.clear();
343 }
344 }
345
346 fn apply_value_instance(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]) -> usize {
348 if nodes[index].is_instance_prop() {
349 if let Some(live_ptr) = apply.from.to_live_ptr(cx, index){
350 let id = nodes[index].id;
351 self.templates.insert(id, live_ptr);
352 for (_, (node, templ_id)) in self.tree_nodes.iter_mut() {
353 if *templ_id == id {
354 let opened = node.opened;
355 node.apply(cx, apply, index, nodes);
356 node.opened = opened;
357 }
358 }
359 }
360 }
361 else {
362 cx.apply_error_no_matching_field(live_error_origin!(), index, nodes);
363 }
364 nodes.skip_node(index)
365 }
366
367}
368
369#[derive(Clone, Debug, DefaultNone)]
370pub enum OutlineTreeAction {
371 None,
372 Selected(LiveId, KeyModifiers),
373 EyeClicked(LiveId, bool),
374 ShouldStartDrag(LiveId),
375}
376
377pub enum OutlineTreeNodeAction {
378 Selected(KeyModifiers),
379 Opening,
380 Closing,
381 ShouldStartDrag
382}
383
384impl DesignerOutlineTreeNode {
385 pub fn draw(&mut self, cx: &mut Cx2d, name: &str, is_even: f32, node_height: f64, depth: usize, scale: f64, draw_open_button:bool) {
386 self.draw_bg.is_even = is_even;
387 self.draw_bg.scale = scale as f32;
388 self.draw_icon.scale = scale as f32;
389 self.draw_text.scale = scale as f32;
390
391
392 self.draw_bg.begin(cx, Walk::size(Size::Fill, Size::Fixed(scale * node_height)), self.layout);
393
394 cx.walk_turtle(self.indent_walk(depth));
395 if draw_open_button{
396 self.button_open.draw_all(cx, &mut Scope::empty());
397 }
398 else{
399 cx.walk_turtle(Walk::fixed(self.button_open_width,0.0));
400 }
401 self.draw_icon.draw_walk(cx, self.icon_walk);
402 self.draw_text.draw_walk(cx, Walk::fit(), Align::default(), name);
403 self.draw_bg.end(cx);
404 }
405
406 fn indent_walk(&self, depth: usize) -> Walk {
407 Walk {
408 abs_pos: None,
409 width: Size::Fixed(depth as f64 * self.indent_width + self.indent_shift),
410 height: Size::Fixed(0.0),
411 margin: Margin::default()
412 }
413 }
414
415 fn set_is_selected(&mut self, cx: &mut Cx, is: bool, animate: Animate) {
416 self.animator_toggle(cx, is, animate, id!(select.on), id!(select.off))
417 }
418
419 fn set_is_focussed(&mut self, cx: &mut Cx, is: bool, animate: Animate) {
420 self.animator_toggle(cx, is, animate, id!(focus.on), id!(focus.off))
421 }
422
423 pub fn set_is_open(&mut self, cx: &mut Cx, is: bool, animate: Animate) {
424 if is{
425 self.opened = 1.0
426 }
427 else{
428 self.opened = 0.0
429 }
430 self.button_open.animator_toggle(cx, is, animate, id!(active.on), id!(active.off));
431 }
432
433 pub fn set_folder_is_open(&mut self, cx: &mut Cx, is: bool, animate: Animate) {
434 self.animator_toggle(cx, is, animate, id!(active.on), id!(active.off));
435 }
436
437 pub fn handle_event(
438 &mut self,
439 cx: &mut Cx,
440 event: &Event,
441 node_id: LiveId,
442 scope: &mut Scope,
443 actions_out: &mut Vec<(LiveId, OutlineTreeNodeAction)>,
444 ) {
445 let actions = cx.capture_actions(|cx|{
446 self.button_open.handle_event(cx, event, scope);
447 });
448
449 if let Some(anim) = self.button_open.animating(&actions){
454 self.opened = anim;
455 self.draw_bg.redraw(cx);
456 }
457 if self.button_open.opening(&actions){
458 actions_out.push((node_id, OutlineTreeNodeAction::Opening));
459 }
460 if self.button_open.closing(&actions){
461 actions_out.push((node_id, OutlineTreeNodeAction::Closing));
462 }
463
464 if self.animator_handle_event(cx, event).must_redraw() {
465 self.draw_bg.redraw(cx);
466 }
467
468 match event.hits(cx, self.draw_bg.area()) {
469 Hit::FingerHoverIn(_) => {
470 self.animator_play(cx, id!(hover.on));
471 }
472 Hit::FingerHoverOut(_) => {
473 self.animator_play(cx, id!(hover.off));
474 }
475 Hit::FingerMove(f) => {
476 if f.abs.distance(&f.abs_start) >= self.min_drag_distance {
477 actions_out.push((node_id, OutlineTreeNodeAction::ShouldStartDrag));
478 }
479 }
480 Hit::FingerDown(e) => {
481 self.animator_play(cx, id!(active.on));
482 actions_out.push((node_id, OutlineTreeNodeAction::Selected(e.modifiers)));
483 }
496 _ => {}
497 }
498 }
499}
500
501impl DesignerOutlineTree {
502
503 pub fn begin(&mut self, cx: &mut Cx2d, walk: Walk) {
504 self.scroll_bars.begin(cx, walk, self.layout);
505 self.count = 0;
506 }
507
508 pub fn end(&mut self, cx: &mut Cx2d) {
509 let height_left = cx.turtle().height_left();
511 let mut walk = 0.0;
512 while walk < height_left {
513 self.count += 1;
514 self.filler.is_even = Self::is_even_as_f32(self.count);
515 self.filler.draw_walk(cx, Walk::size(Size::Fill, Size::Fixed(self.node_height.min(height_left - walk))));
516 walk += self.node_height.max(1.0);
517 }
518
519 self.draw_scroll_shadow.draw(cx, dvec2(0., 0.));
520 self.scroll_bars.end(cx);
521
522 if let Some(rect) = self.scroll_into_view_rect.take(){
523 let rect = rect.add_margin(dvec2(0.0,self.node_height*3.0)).translate(self.scroll_bars.get_scroll_pos());
524 self.scroll_bars.scroll_into_view_abs(cx, rect);
525 }
526
527 let selected_node_id = self.selected_node_id;
528 self.tree_nodes.retain_visible_and( | node_id, _ | Some(*node_id) == selected_node_id);
529 }
530
531 pub fn is_even_as_f32(count: usize) -> f32 {
532 if count % 2 == 1 {0.0}else {1.0}
533 }
534
535 pub fn should_node_draw(&mut self, node_id: LiveId, cx: &mut Cx2d) -> bool {
536 let scale = self.stack.last().cloned().unwrap_or(1.0);
537 let height = self.node_height * scale;
538 let walk = Walk::size(Size::Fill, Size::Fixed(height));
539 if scale > 0.01 && cx.walk_turtle_would_be_visible(walk) {
540 if let Some(view_id) = &self.scroll_into_view_id{
541 if *view_id == node_id{
542 self.scroll_into_view_id.take();
543 }
544 }
545 return true
546 }
547 else {
548 let rect = cx.walk_turtle(walk);
550 if let Some(view_id) = &self.scroll_into_view_id{
551 if *view_id == node_id{
552 self.scroll_into_view_id.take();
553 self.scroll_into_view_rect = Some(rect);
554 }
555 }
556 return false
557 }
558 }
559
560 pub fn begin_node(
561 &mut self,
562 cx: &mut Cx2d,
563 node_id: LiveId,
564 name: &str,
565 template: LiveId,
566 ) -> Result<(), ()> {
567 let scale = self.stack.last().cloned().unwrap_or(1.0);
568
569 if scale > 0.2 {
570 self.count += 1;
571 }
572
573 let is_open = self.open_nodes.contains(&node_id);
574 let is_selected = self.selected_node_id == Some(node_id);
575 if self.should_node_draw(node_id, cx) {
576 if let Some(ptr) = self.templates.get(&template){
578 let (tree_node, _) = self.tree_nodes.get_or_insert(cx, node_id, | cx | {
579 let mut tree_node = DesignerOutlineTreeNode::new_from_ptr(cx, Some(*ptr));
580 if is_open {
581 tree_node.set_is_open(cx, true, Animate::No)
582 }
583 if is_selected{
584 tree_node.set_is_selected(cx, true, Animate::No)
585 }
586 (tree_node, template)
587 });
588 tree_node.draw(cx, name, Self::is_even_as_f32(self.count), self.node_height, self.stack.len(), scale, true);
589 self.stack.push(tree_node.opened as f64 * scale);
590 if tree_node.opened <= 0.001 {
591 self.end_node();
592 return Err(());
593 }
594 }
595 else{
596 return Err(());
597 }
598 }
599 else {
600 if is_open {
601 self.stack.push(scale * 1.0);
602 }
603 else {
604 return Err(());
605 }
606 }
607 Ok(())
608 }
609
610 pub fn end_node(&mut self) {
611 self.stack.pop();
612 }
613
614 pub fn node(&mut self, cx: &mut Cx2d, node_id: LiveId, name: &str, template: LiveId) {
615 let scale = self.stack.last().cloned().unwrap_or(1.0);
616
617 if scale > 0.2 {
618 self.count += 1;
619 }
620 let is_selected = self.selected_node_id == Some(node_id);
621 if self.should_node_draw(node_id, cx) {
622 if let Some(ptr) = self.templates.get(&template){
623 let (tree_node, _) = self.tree_nodes.get_or_insert(cx, node_id, | cx | {
624 let mut tree_node = DesignerOutlineTreeNode::new_from_ptr(cx, Some(*ptr));
625 if is_selected{
626 tree_node.set_is_selected(cx, true, Animate::No)
627 }
628 (tree_node, template)
629
630 });
631 tree_node.draw(cx, name, Self::is_even_as_f32(self.count), self.node_height, self.stack.len(), scale, false);
632 }
633 }
634 }
635
636 pub fn forget(&mut self) {
637 self.tree_nodes.clear();
638 }
639
640 pub fn forget_node(&mut self, file_node_id: LiveId) {
641 self.tree_nodes.remove(&file_node_id);
642 }
643
644 pub fn select_and_show_node(&mut self, cx:&mut Cx, id_path:&[LiveId]) {
645 if id_path.len() == 0{
646 return
647 }
648 for i in 0..id_path.len()-1{
649 let id = id_path[i];
650 self.open_nodes.insert(id);
651 if let Some((tree_node,_)) = self.tree_nodes.get_mut(&id){
652 tree_node.set_is_open(cx, true, Animate::No);
653 }
654 }
655 let last = *id_path.last().unwrap();
656 self.scroll_into_view_id = Some(last);
657 self.selected_node_id = Some(last);
658
659 for (id,(tree_node,_)) in self.tree_nodes.iter_mut(){
660 if *id == last{
661 tree_node.set_is_selected(cx, true, Animate::No);
662 }
663 else{
664 tree_node.set_is_selected(cx, false, Animate::No);
665 }
666 }
667 self.redraw(cx);
668 }
669
670 pub fn start_dragging_file_node(
671 &mut self,
672 cx: &mut Cx,
673 node_id: LiveId,
674 items: Vec<DragItem>,
675 ) {
676 self.dragging_node_id = Some(node_id);
677
678 log!("makepad: start_dragging_file_node");
679
680 cx.start_dragging(items);
681 }
682
683 pub fn set_folder_is_open(
684 &mut self,
685 cx: &mut Cx,
686 node_id: LiveId,
687 is_open: bool,
688 animate: Animate,
689 ) {
690 if is_open {
691 self.open_nodes.insert(node_id);
692 }
693 else {
694 self.open_nodes.remove(&node_id);
695 }
696 if let Some((tree_node, _)) = self.tree_nodes.get_mut(&node_id) {
697 tree_node.set_folder_is_open(cx, is_open, animate);
698 }
699 }
700 }
723
724impl Widget for DesignerOutlineTree {
729
730 fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
731 let uid = self.widget_uid();
732
733 self.scroll_bars.handle_event(cx, event, scope);
734
735 match event {
736 Event::DragEnd => self.dragging_node_id = None,
737 _ => ()
738 }
739
740 let mut node_actions = Vec::new();
741
742 for (node_id, (node, _)) in self.tree_nodes.iter_mut() {
743 node.handle_event(cx, event, *node_id, scope, &mut node_actions);
744 }
745
746 for (node_id, node_action) in node_actions {
747 match node_action {
748 OutlineTreeNodeAction::Opening => {
749 self.open_nodes.insert(node_id);
750 }
751 OutlineTreeNodeAction::Closing => {
752 self.open_nodes.remove(&node_id);
753 }
754 OutlineTreeNodeAction::Selected(km) => {
758 cx.widget_action(uid, &scope.path, OutlineTreeAction::Selected(node_id, km));
759 cx.set_key_focus(self.scroll_bars.area());
760 if let Some(last_selected) = self.selected_node_id {
761 if last_selected != node_id {
762 if let Some(node) = self.tree_nodes.get_mut(&last_selected){
763 node.0.set_is_selected(cx, false, Animate::Yes);
764 }
765 }
766 }
767 self.selected_node_id = Some(node_id);
768 }
770 OutlineTreeNodeAction::ShouldStartDrag => {
771 if self.dragging_node_id.is_none() {
772 cx.widget_action(uid, &scope.path, OutlineTreeAction::ShouldStartDrag(node_id));
773 }
774 }
775 }
776 }
777
778 match event.hits(cx, self.scroll_bars.area()) {
779 Hit::KeyFocus(_) => {
780 if let Some(node_id) = self.selected_node_id {
781 self.tree_nodes.get_mut(&node_id).unwrap().0.set_is_focussed(cx, true, Animate::Yes);
782 }
783 }
784 Hit::KeyFocusLost(_) => {
785 if let Some(node_id) = self.selected_node_id {
786 self.tree_nodes.get_mut(&node_id).unwrap().0.set_is_focussed(cx, false, Animate::Yes);
787 }
788 }
789 _ => ()
790 }
791 }
792
793 fn draw_walk(&mut self, cx: &mut Cx2d, _scope:&mut Scope,walk: Walk) -> DrawStep {
794 if self.draw_state.begin(cx, ()) {
795 self.begin(cx, walk);
796 return DrawStep::make_step()
797 }
798 if let Some(()) = self.draw_state.get() {
799 self.end(cx);
800 self.draw_state.end();
801 }
802 DrawStep::done()
803 }
804}
805
806impl DesignerOutlineTreeRef{
807 pub fn should_file_start_drag(&self, actions: &Actions) -> Option<LiveId> {
808 if let Some(item) = actions.find_widget_action(self.widget_uid()) {
809 if let OutlineTreeAction::ShouldStartDrag(file_id) = item.cast() {
810 return Some(file_id)
811 }
812 }
813 None
814 }
815 pub fn select_and_show_node(&self, cx:&mut Cx, id_path:&[LiveId]) {
827 if let Some(mut inner) = self.borrow_mut(){
828 inner.select_and_show_node(cx, id_path);
829 }
830 }
831
832
833 pub fn selected(&self, actions: &Actions) -> Option<(LiveId,KeyModifiers)> {
834 if let Some(item) = actions.find_widget_action(self.widget_uid()) {
835 if let OutlineTreeAction::Selected(file_id, km) = item.cast() {
836 return Some((file_id,km))
837 }
838 }
839 None
840 }
841
842
843 pub fn start_drag(&self, cx: &mut Cx, _file_id: LiveId, item: DragItem) {
844 cx.start_dragging(vec![item]);
845 }
846}