1use crate::{
2 makepad_draw::*,
3 file_tree::*,
4 view::View,
5 widget::*,
6};
7
8live_design!{
9 import makepad_widgets::base::*
10 import makepad_widgets::theme_desktop_dark::*
11 import makepad_draw::shader::std::*
12
13 Designer = {{Designer}} {
14 has_view: true,
15 flow: Right
16 container: <RoundedView> {
17 draw_bg: {color: #3}
18 width: Fill, height: 400
19 flow: Down, spacing: 10, padding:10
20 <RoundedView>{
21 width: Fill, height: Fit
22 padding:5
23 draw_bg:{color:#5}
24 label = <Label> {text: "HI", draw_text:{color:#f}}
25 }
26 inner = <HookWidget> {}
27 }
28 <Splitter> {
29 align: FromStart(300),
30 a: <View> {
31 outline = <FileTree> {
32 }
33 },
34 b: <CachedScrollXY> {
35 dpi_factor: 1.5
36 draw_bg: {color: #4}
37 width: Fill, height: Fill
38 flow: Down
39 design = <HookWidget> {}
40 },
41 }
42 }
43}
44
45#[allow(dead_code)]
46enum OutlineNode {
47 Global {
48 uid: FileNodeId,
49 name: LiveId,
50 ptr: LivePtr
51 },
52 Component {
53 uid: FileNodeId,
54 name: LiveId,
55 class: LiveId,
56 prop_type: LivePropType,
57 ptr: LivePtr,
58 children: Vec<OutlineNode>
59 }
60}
61
62#[derive(Live)]
63pub struct Designer {
64 #[live] container: Option<LivePtr>,
65 #[rust] outline_nodes: Vec<OutlineNode>,
66 #[rust] components: ComponentMap<LivePtr, (WidgetRef, WidgetRef)>,
67 #[deref] ui: View,
68}
69
70impl LiveHook for Designer {
71 fn before_live_design(cx: &mut Cx) {
72 register_widget!(cx, Designer)
73 }
74
75 fn after_new_from_doc(&mut self, cx: &mut Cx) {
76 let live_registry_rc = cx.live_registry.clone();
78 let live_registry = &*live_registry_rc.borrow();
79 let file_id = live_registry.file_name_to_file_id("examples/ironfish/src/app_desktop.rs").unwrap();
80 let file = live_registry.file_id_to_file(file_id);
83 let nodes = &file.expanded.nodes;
84 fn recur_walk(live_registry: &LiveRegistry, base_ptr: LivePtr, mut index: usize, nodes: &[LiveNode], out: &mut Vec<OutlineNode>) -> usize {
86 while index < nodes.len() - 1 {
87 if let LiveValue::Class {class_parent, ..} = &nodes[index].value {
88 let mut children = Vec::new();
90 let name = nodes[index].id;
91 let class = live_registry.ptr_to_node(class_parent.unwrap()).id;
92 let ptr = base_ptr.with_index(index);
93 index = recur_walk(live_registry, base_ptr, index + 1, nodes, &mut children);
94 out.insert(0, OutlineNode::Component {
95 uid: LiveId::unique().into(),
96 name,
97 prop_type: nodes[index].origin.prop_type(),
98 class,
99 ptr,
100 children
101 });
102 }
103 else if nodes[index].value.is_close() {
104 return index + 1;
105 }
106 else {
107 index = nodes.skip_node(index);
108 }
109 }
110 index
111 }
112 let base_ptr = live_registry.file_id_index_to_live_ptr(file_id, 0);
113 recur_walk(live_registry, base_ptr, 1, nodes, &mut self.outline_nodes);
114 }
115 }
118
119impl Designer {
120
121 fn draw_design(&mut self, cx: &mut Cx2d) {
122 let mut count = 0;
124 for node in &self.outline_nodes {
125 if let OutlineNode::Component {ptr, name, class, ..} = node {
126 count += 1;
127 if count > 5{
128 break;
129 }
130 let container_ptr = self.container;
131 let (widget, container) = self.components.get_or_insert(cx, *ptr, | cx | {
132 (
133 WidgetRef::new_from_ptr(cx, Some(*ptr)),
134 WidgetRef::new_from_ptr(cx, container_ptr),
135 )
136 });
137 container.widget(id!(label)).set_text(&format!("{}=<{}>", name, class));
138 while let Some(_) = container.draw_widget(cx).hook_widget() {
140 widget.draw_widget_all(cx);
141 }
142 }
143 }
144
145 }
146
147 fn draw_outline(&mut self, cx: &mut Cx2d, outline: &mut FileTree) {
148 fn recur_walk(cx: &mut Cx2d, outline: &mut FileTree, children: &[OutlineNode]) {
149 for child in children {
150 match child {
151 OutlineNode::Global {..} => {}
152 OutlineNode::Component {name, children, uid, class, prop_type, ..} => {
153 if outline.begin_folder(cx, *uid, &if !name.is_unique(){
154 if let LivePropType::Field = prop_type {
155 format!("{}: <{}>", name, class)
156 }
157 else {
158 format!("{}=<{}>", name, class)
159 }
160 }else {
161 format!("<{}>", class)
162 }).is_ok() {
163 recur_walk(cx, outline, children);
164 outline.end_folder();
165 }
166 }
167 }
168 }
169 }
170 recur_walk(cx, outline, &self.outline_nodes);
171 }
172
173}
174
175impl Widget for Designer {
176 fn handle_widget_event_with(&mut self, cx: &mut Cx, event: &Event, _dispatch_action: &mut dyn FnMut(&mut Cx, WidgetActionItem)) {
177 let _actions = self.ui.handle_widget_event(cx, event);
178 for (component, container) in self.components.values_mut() {
179 component.handle_widget_event(cx, event);
180 container.handle_widget_event(cx, event);
181 }
182 }
183
184 fn redraw(&mut self, cx: &mut Cx) {
185 self.ui.redraw(cx)
186 }
187
188 fn draw_walk_widget(&mut self, cx: &mut Cx2d, _walk: Walk) -> WidgetDraw {
189 let outline = self.ui.file_tree(id!(outline));
190 while let Some(next) = self.ui.draw_widget(cx).hook_widget() {
191 if let Some(mut outline) = outline.has_widget(&next).borrow_mut() {
192 self.draw_outline(cx, &mut *outline);
193 }
194 else if next == self.ui.widget(id!(design)) {
195 self.draw_design(cx);
196 }
197 }
198 WidgetDraw::done()
199 }
200}