blob: 04d61ba5438017718f95f51d964cad185a6b096e [file] [log] [blame]
Jeremy Kerr9b0e0ba2015-09-14 21:49:21 +08001
2var g_bus;
3var initial_state = {
4 'bus': 'session',
5};
6
7function populate_tree_services(node, cb, bus)
8{
9 jQuery.getJSON('/bus/' + bus.name, function(data) {
10 var children = [];
11 for (var i in data.objects) {
12 var service = data.objects[i];
13 if (service.name[0] == ':')
14 continue;
15 children.push({
16 'text': service.name,
17 'children': true,
18 'type': 'service',
19 'bus': bus,
20 'service': service,
21 });
22 }
23 cb(children);
24 });
25}
26
27function populate_tree_objects(node, cb)
28{
29 var ctx = node.original;
30 jQuery.getJSON('/bus/' + ctx.bus.name + '/' + ctx.service.name,
31 function(data) {
32 var children = [];
33 for (var i in data.objects) {
34 var obj = data.objects[i];
35 children.push({
36 'text': obj.path,
37 'children': true,
38 'type': 'object',
39 'bus': ctx.bus,
40 'service': ctx.service,
41 'object': obj,
42 });
43 }
44 cb(children);
45 });
46}
47
48function populate_tree_interfaces(node, cb)
49{
50 var ctx = node.original;
51 jQuery.getJSON('/bus/' + ctx.bus.name + '/' + ctx.service.name +
52 ctx.object.path,
53 function(data) {
54 console.log(data);
55 var children = [];
56 for (var i in data.interfaces) {
57 var iface = data.interfaces[i];
58 children.push({
59 'text': iface.name,
60 'children': true,
61 'type': 'interface',
62 'bus': ctx.bus,
63 'service': ctx.service,
64 'object': ctx.object,
65 'interface': iface,
66 });
67 }
68 cb(children);
69 });
70}
71
72function format_one_type(type)
73{
74 var ret = Object();
75 var basic_types = {
76 'v': 'variant',
77 'i': 'int32',
78 'x': 'int64',
79 'u': 'uint32',
80 't': 'uint64',
81 'g': 'type',
82 'h': 'file',
83 'd': 'double',
84 's': 'string',
85 'o': 'objpath',
86 'y': 'byte',
87 'b': 'boolean',
88 }
89
90 var c = type[0];
91 if (basic_types[c]) {
92 ret.type = basic_types[c];
93 ret.left = type.substring(1);
94 return ret;
95 }
96
97 if (c == '(') {
98 var i;
99 var n;
100 for (i = 1, n = 1; i < type.length; i++) {
101 var c = type[i];
102 if (c == '(')
103 n++;
104 if (c == ')')
105 if (--n == 0)
106 break;
107
108 }
109 if (i == type.length)
110 return ret;
111 var content = type.substring(1, i);
112 ret.type = 'struct {' + format_types(content).join(', ') + '}';
113 ret.left = type.substring(i+1);
114 return ret;
115 }
116
117 if (c == 'a') {
118 var content = type.substring(1);
119 if (content[0] == '{') {
120 var i;
121 var n;
122 for (i = 1, n = 1; i < content.length; i++) {
123 var c = content[i];
124 if (c == '{')
125 n++;
126 if (c == '}')
127 if (--n == 0)
128 break;
129
130 }
131 content = content.substring(1, i);
132 var types = format_types(content);
133 console.log("{", content, "}", types);
134 ret.type = 'dict {' + types[0] + ' → ' + types[1] + '}';
135 ret.left = type.substring(i+1);
136 } else {
137 var t = format_one_type(content);
138 ret.type = '[' + t.type + ']';
139 ret.left = t.left;
140 }
141 return ret;
142 }
143
144 ret.type = c;
145 ret.left = type.substring(1);
146 return ret;
147
148}
149
150function format_types(type)
151{
152 var t;
153 var ts = [];
154 for (;;) {
155 t = format_one_type(type);
156 ts.push(t.type);
157
158 if (!t.left || !t.left.length)
159 break;
160 type = t.left;
161 }
162 return ts;
163}
164
165function format_type(type)
166{
167 return format_types(type)[0];
168}
169
170function format_method_arg(arg)
171{
172 return '<span class="method-arg">' +
173 '<span class="method-arg-type">' + format_type(arg.type) +
174 '</span> ' +
175 '<span class="method-arg-name">' + arg.name + '</span></span>';
176}
177
178function format_method(method)
179{
180 var in_args = [];
181 var out_args = [];
182 for (var i in method.args) {
183 var arg = method.args[i];
184 var str = format_method_arg(arg);
185 if (arg.direction == 'in')
186 in_args.push(str);
187 else
188 out_args.push(str);
189 }
190 return '<span class="method">' +
191 '<span class="method-name">' + method.name + "</span>" +
192 '<span class="method-args">(' + in_args.join(', ') + ')</span>' +
193 ' → ' +
194 '<span class="method-args">' + out_args.join(', ') + '</span>' +
195 '</span>'
196}
197
198function format_property(name, value)
199{
200 return '<span class="property">' +
201 '<span class="property-name">' + name + '</span>' +
202 ' = ' +
203 '<span class="property-value">' + value + '</span>' +
204 '</span>'
205}
206
207function populate_tree_interface_items(node, cb)
208{
209 var ctx = node.original;
210 jQuery.getJSON('/bus/' + ctx.bus.name + '/' + ctx.service.name +
211 ctx.object.path + '/' + ctx.interface.name,
212 function(data) {
213 console.log(data);
214 var children = [];
215 for (var i in data.methods) {
216 var method = data.methods[i];
217 children.push({
218 'text': format_method(method),
219 'children': [],
220 'type': 'method',
221 'method': method,
222 'bus': ctx.bus,
223 'service': ctx.service,
224 'object': ctx.object,
225 'interface': ctx.interface,
226 });
227 }
228 for (var i in data.properties) {
229 var property = data.properties[i];
230 children.push({
231 'text': format_property(i, property),
232 'children': [],
233 });
234 }
235 cb(children);
236 });
237}
238function populate_tree(node, cb)
239{
240 if (!node.original) {
241 populate_tree_services(node, cb, g_bus);
242 return;
243 }
244
245 var type = node.original.type;
246 if (type == 'service') {
247 populate_tree_objects(node, cb);
248 } else if (type == 'object') {
249 populate_tree_interfaces(node, cb);
250 } else if (type == 'interface') {
251 populate_tree_interface_items(node, cb);
252 }
253}
254
255function select_node(evt, data)
256{
257 var ctx = data.node.original;
258 if (!ctx || ctx.type != 'method')
259 return;
260
261 var method = ctx.method;
262 jQuery("#method-call-ui").remove();
263
264 var container = data.instance.get_node(data.node, true);
265
266 var in_args = []
267 for (var i in method.args) {
268 var arg = method.args[i];
269 if (arg.direction != 'in')
270 continue;
271 in_args.push({
272 'type': format_method_arg(arg),
273 'idx': i,
274 });
275 }
276 method.nargs = in_args.length;
277
278 var template = jQuery.templates('#method-call-ui-template');
279 container.append(template.render({
280 'method': method,
281 'in_args': in_args,
282 }));
283 jQuery("form", container).submit(function(e) {
284 var form = jQuery(e.target);
285 var n = jQuery("input[name=argN]", form).val();
286 var data = [];
287 for (var i = 0; i < n; i++) {
288 var val = jQuery("input[name=arg" + i + ']', form).val();
289 try {
290 data.push(JSON.parse(val));
291 } catch (e) {
292 data.push(null);
293 }
294 }
295 jQuery.ajax(form.attr("action"),
296 {
297 'method': 'POST',
298 'contentType': 'text/json',
299 'data': JSON.stringify(data),
300 'dataType': 'text',
301 'success': function(data, status) {
302 jQuery('#method-call-ui-result').text(data);
303 },
304 });
305 return false;
306 });
307}
308
309function set_bus(b)
310{
311 g_bus = b;
312 $('#container').jstree({
313 'core': {
314 'data': populate_tree,
315 'multiple': false,
316 'themes': {
317 'icons': false,
318 },
319 }
320 }).on('select_node.jstree', select_node);
321}
322
323function init()
324{
325 var select = jQuery('select#bus');
326 select.empty();
327 select.append(jQuery('<option>').text('---'));
328 jQuery.getJSON('/bus/', function(data) {
329 for (var i in data.busses) {
330 var bus = data.busses[i];
331 var elem = jQuery('<option>');
332 elem.text(bus.name);
333 elem.data('bus', bus);
334 select.append(elem);
335 if (initial_state.bus == bus.name) {
336 elem.attr('selected', 'true');
337 set_bus(bus);
338 }
339 }
340 select.bind('change', function(e) {
341 var elem = jQuery("option:selected", e.target);
342 var b = elem.data('bus');
343 if (b)
344 set_bus(b);
345 });
346 })
347}
348
349jQuery(document).ready(init);