1 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); 350