diff --git a/src/bin/sol-fbp-runner/Modal.js b/src/bin/sol-fbp-runner/Modal.js new file mode 100644 index 000000000..ac1a09801 --- /dev/null +++ b/src/bin/sol-fbp-runner/Modal.js @@ -0,0 +1,50 @@ +(function(window) { + + 'use strict' + + function Modal(){ + + var instance = this; + + this.el = $("
").addClass("modal").appendTo("#modal-container"); + this.header = $("
").addClass("modal-header").appendTo(this.el); + this.title = $("").appendTo(this.header).addClass("modal-title"); + this.content = $("
").appendTo(this.el);
+
+		this.el.hide();
+		this.shield = $("
").attr("id","shield"); + + this.closeButton = $("").attr("src","images/ico_close.png").addClass("close").appendTo(this.header) + .click(function(){ + instance.hide(); + }); + + + } + + Modal.prototype.show = function(data, title) { + + var instance = this; + + this.title.empty().append(title); + this.content.empty().append(data); + + //adding click to the shield div + this.shield.insertBefore(this.el) + .click(function() { + instance.hide(); + }); + + this.el.show(400); + }; + + Modal.prototype.hide = function() { + this.title.empty(); + this.content.empty(); + this.el.hide(); + this.shield.remove(); + }; + + window.Modal = Modal; + +})(window) diff --git a/src/bin/sol-fbp-runner/Port.js b/src/bin/sol-fbp-runner/Port.js new file mode 100644 index 000000000..1c744611e --- /dev/null +++ b/src/bin/sol-fbp-runner/Port.js @@ -0,0 +1,122 @@ +(function(window) { + + 'use strict' + + function Port (params) { + + //data properties + var instance = this; //returns the __proto__ of the object + + this.name = params["name"]; + this.value = params["value"]; + this.type = params["type"] || "in"; + this.data_type = params["data_type"]; + this.widget = params["widget"]; + this.port_index = params["port_index"]; + this.required = params["required"] || true; + this.key = "port_" + this.type + "_" + params["key"]; + this.connections = []; //the pair port which this port is connected + this.emitt = false; + + //DOM properties + this.el = $("
") + .attr("id",this.key) + .addClass("port "+this.getPortType()) + .append(this.name); + + //adding the port to the correct container + if(this.type == "in") this.widget.getLeft().append(this.el); + if(this.type == "out") this.widget.getRight().append(this.el); + + //MOUSE AND CUSTOM EVENTS + this.el.click(function (event) { + $(event.target).trigger({ + type:"port-select", + port:instance, + widget:instance.widget, + value:instance.value + }); + + }); + + this.el.mouseover(function (event) { + $(event.target).trigger({ + type:"port-over", + port:instance, + widget:instance.widget, + connections:instance.connections + }); + }); + + this.el.mouseout(function (event) { + $(event.target).trigger({ + type:"port-out", + port:instance, + widget:instance.widget, + connections:instance.connections + }); + }); + } + + Port.prototype.update = function (value) { + + this.value = value; //retrieves only the valu + + var widget = this.widget; + var instance = this.instance; + + if(this.emitt) this.el.trigger( + { + type:"port-update", + widget:widget, + port:instance, + value:value, + }); + } + + Port.prototype.getElement = function() { + return this.el; + } + + Port.prototype.getParentWidget = function() { + return this.widget; + } + + Port.prototype.getPortType = function() { + return (this.type === "in") ? "in" : "out"; + } + + Port.prototype.select = function() { + this.emitt = true; + this.el.addClass("selected"); + } + + Port.prototype.unselect = function() { + this.emitt = false; + this.el.removeClass("selected"); + } + + Port.prototype.connect = function (port) { + + //ERROR TRYING TO CONNECT PORTs! + if(this.connections.indexOf(port.key) == -1) + { + this.connections.push(port.key); + this.widget.autoSelectPort(this); + } + + } + + Port.prototype.hidePort = function() { + this.el.addClass("hidden"); + this.el.addClass("non-selectable"); + this.el.unbind(); + } + + Port.prototype.showPort = function() { + //TODO + } + + window.Port = Port; + +})(window) diff --git a/src/bin/sol-fbp-runner/Widget.js b/src/bin/sol-fbp-runner/Widget.js new file mode 100644 index 000000000..56e553aa0 --- /dev/null +++ b/src/bin/sol-fbp-runner/Widget.js @@ -0,0 +1,222 @@ +(function(window) { + + 'use strict' + + function Widget(payload, key) { + + //caching a secure reference to the instance + var instance = this; + //var selectedPort; + + Widget.prototype.portsCount = 0; + + //unique id for the widget and other unique properties + this.raw = JSON.stringify(payload, null, 4); + this.key = key; + this.widgetName = payload.id; //change to 'name ?' + this.uid = payload.path[payload.path.length-1]; + this.type = payload.type; + this.category = payload.category; + this.description = payload.description; + this.url = payload.url; + this.portsIn = []; + this.portsOut = []; + this.autoSelected = false; + this.hidden = true; + this.selectedPort = null; + this.totalPorts = 0; + + //TODO: we should change the id key to name + this.name = "widget" + payload.id; + + //title and subtitle of the widget + this.title = $("").addClass("widget-title").append(this.widgetName); + this.subtitle = $("").addClass("widget-subtitle").append(this.type); + + //info button + var info = $("").attr("src","images/ico_info.png").addClass("info"); + info.click(function(event) { + window.modal.show(instance.raw, instance.type); + }); + + //creating DOM elements + this.displayValue = $("").addClass("display-value"); + this.el = $("
").addClass("widget").attr("id",this.uid).appendTo("#container"); + $("
").addClass("widget-header").appendTo(this.el).append(this.title).append(this.subtitle).append(info); + $("
").addClass("widget-display").appendTo(this.el).addClass("widget-data").append(this.displayValue); + this.widgetPorts = $("
").addClass("widget-ports").appendTo(this.el); + + //putting the ports in the correct container + this.lports = $("
").addClass("port-container").appendTo("#"+this.uid + " .widget-ports"); + this.rports = $("
").addClass("port-container").appendTo("#"+this.uid + " .widget-ports"); + + //reading all in ports + var port; + payload.ports_in.forEach(function(element, index) { + port = new Port( + { + name:element["name"], + value:undefined, + type:"in", + port_index:element["base_port_idx"], + data_type:element["data_type"], + required:element["required"], + widget:instance, + key:instance.key + "_" + Widget.prototype.portsCount + }); + + instance.portsIn.push(port); + instance.totalPorts++; + port.el.on("port-select", instance.onPortSelect); + Widget.prototype.portsCount ++; + }); + + //reading all out ports + payload.ports_out.forEach(function(element, index) { + port = new Port( + { + name:element["name"], + value:undefined, + type:"out", + port_index:element["base_port_idx"], + data_type:element["data_type"], + required:element["required"], + widget:instance, + key:instance.key + "_" + Widget.prototype.portsCount + }); + instance.portsOut.push(port); + instance.totalPorts++; + port.el.on("port-select", instance.onPortSelect); + Widget.prototype.portsCount ++; + }); + + //Auto Adjusting the size of the Widget Container + var h = Math.max(this.portsIn.length, this.portsOut.length) * 26; + this.widgetPorts.css("height",h); + + } + + Widget.prototype.onPortSelect = function(event) { + event.widget.selectPort(event.port, event.value); + }; + + Widget.prototype.getUID = function() { + return this.uid; + }; + + //UPDATES THE VALUES OF ALL PORTS + Widget.prototype.update = function(type, data) { + + //getting the child ports of the widget + var port = (type === "deliver") ? this.portsIn[data.port_idx] : this.portsOut[data.port_idx]; + + //if the ports have no pair, skip + if(port.connections.length < 0) return; + + //found paired ports, update its value + var packet = data.packet; + var packetType = packet.packet_type; + + if(packetType === "empty"){ + port.update("empty"); + }else if(packetType === "int" || packetType === "float"){ + port.update(packet.payload.value) + }else if(packetType === "byte"){ + port.update(packet.payload); + }else if(packetType === "boolean"){ + port.update(packet.payload.toString()); + } + }; + + Widget.prototype.fadeIn = function(delay) { + var instance = this; + setTimeout(function(){ + instance.el.fadeIn(300); + },delay); + }; + + Widget.prototype.clearPorts = function() { + + this.portsIn.forEach(function(p, i){ + if(p.connections.length === 0){ + p.hidePort(); + } + }) + + this.portsOut.forEach(function(p, i){ + if(p.connections === 0){ + p.hidePort(); + } + }) + }; + + Widget.prototype.autoSelectPort = function(port) { + if(this.selectedPort == null){ + this.selectPort(port,port.value); + } + }; + + Widget.prototype.selectPort = function(port, value) { + + //dealing with repeated port click + if(port === this.selectedPort) { + port.unselect(); + this.unsubscribe(port); + this.selectedPort = null; + return; + } + + //clearing last selected port + if(this.selectedPort != null) { + this.selectedPort.unselect(); + this.unsubscribe(port); + } + + //selecting new port + this.clearDisplay().append(value); + this.selectedPort = port; + this.selectedPort.select(); + this.subscribe(port); + }; + + Widget.prototype.onPortValueChange = function(event) { + event.widget.clearDisplay().append(event.value); + }; + + Widget.prototype.subscribe = function(port) { + port.el.on('port-update', this.onPortValueChange); + }; + + Widget.prototype.unsubscribe = function(port) { + port.el.off('port-update', this.onPortValueChange); + this.clearDisplay(port.widget); + }; + + Widget.prototype.clearDisplay = function() { + var display = $("#" + this.uid + " .display-value").empty(); + return display; + }; + + Widget.prototype.getElement = function() { + return this.el; + }; + + Widget.prototype.getLeft = function() { + return this.lports; + }; + + Widget.prototype.getRight = function() { + return this.rports; + }; + + Widget.prototype.getInByIndex = function(index) { + return this.portsIn[index]; + }; + + Widget.prototype.getOutByIndex = function(index) { + return this.portsOut[index]; + }; + + window.Widget = Widget; + +})(window) diff --git a/src/bin/sol-fbp-runner/css/style.css b/src/bin/sol-fbp-runner/css/style.css new file mode 100644 index 000000000..3d5bce215 --- /dev/null +++ b/src/bin/sol-fbp-runner/css/style.css @@ -0,0 +1,192 @@ +/* + * This file is part of the Soletta Project + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +* { + font-family: Arial, Helvetica, sans-serif; +} +body { + background-color: #4C5155; +} +h1 { + background-color: blue; +} +body { + margin: 0px; + border: 0px; +} +.widget { + width: 180px; + margin: 10px; + overflow: hidden; + float: left; +} +.widget-header { + background-color: #2D3237; + color: white; + width: 100%; + height: 46px; + padding-left: 10px; + padding-top: 10px; +} +.widget-title { + width: 140px; + overflow: hidden; + color: white; + font-size: 1.3em !important; + display: block; +} +.widget-subitle { + width: 140px; + height: 15px; + overflow: hidden; + font-size: 8px !important; + display: block; + background-color: red; +} +.widget-display { + background-Color: white; + width: 100%; + height: 120px; +} +.display-value { + display: block; + word-wrap: break-word; + margin-left: 30px; + margin-right: 30px; + padding-top: 20px; + color: #2D3237; +} +.widget-data { + font-size: 2em; +} +.widget-ports { + width: 100%; + background-color: #777E83; +} +.port { + width: 85px; + /*border-bottom: 1px solid @gray;*/ + color: white; + font-size: .6em; + padding: 8px 0; + cursor: pointer; + overflow: hidden; +} +.port.in { + background-color: #777E83; + float: left; + text-align: left; + border-right: 1px solid white; + padding-left: 8px; +} +.port.out { + background-color: #777E83; + float: right; + text-align: right; + border-left: 1px solid white; + margin-left: -4px; + padding-right: 8px; +} +.port.selected { + background-color: #2D3237; +} +.port.paired-slave { + background-color: #E71C4C; +} +.port.paired-master { + background-color: #39CD89; +} +.port.hidden { + opacity: 0.2; + cursor: default; +} +.port-container { + width: 50%; + min-height: 50px; + float: left; + overflow: hidden; +} +.info { + float: right; + border: 0; + cursor: pointer; + width: 16px; + height: 16px; + margin-right: 18px; + margin-top: -18px; +} +.close { + float: right; + border: 0; + cursor: pointer; + width: 24px; + height: 24px; + -webkit-filter: invert(100%); + filter: invert(100%); +} +.modal { + width: 750px; + height: 500px; + overflow: hidden; + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: white; +} +.modal-header { + background-color: #7595C3; + height: 30px; + padding: .5em; + overflow: hidden; +} +.modal-title { + font-size: 2em; + color: white; + margin: 15px; +} +#shield { + position: fixed; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.7); +} +pre { + position: absolute; + height: 455px; + width: 735px; + left: 15px; + background-color: white; + color: #2D3237; + overflow-y: scroll; + top: 30px; +} +.non-selectable { + -webkit-touch-callout: none; + /* iOS Safari */ + -webkit-user-select: none; + /* Chrome/Safari/Opera */ + -khtml-user-select: none; + /* Konqueror */ + -moz-user-select: none; + /* Firefox */ + -ms-user-select: none; + /* Internet Explorer/Edge */ + user-select: none; + /* Non-prefixed version, currently + not supported by any browser */ +} diff --git a/src/bin/sol-fbp-runner/images/ico_close.png b/src/bin/sol-fbp-runner/images/ico_close.png new file mode 100644 index 000000000..b8cfbb37e Binary files /dev/null and b/src/bin/sol-fbp-runner/images/ico_close.png differ diff --git a/src/bin/sol-fbp-runner/images/ico_info.png b/src/bin/sol-fbp-runner/images/ico_info.png new file mode 100644 index 000000000..7311e9364 Binary files /dev/null and b/src/bin/sol-fbp-runner/images/ico_info.png differ diff --git a/src/bin/sol-fbp-runner/web-inspector.css b/src/bin/sol-fbp-runner/web-inspector.css index 9154bd652..18430e8b6 100644 --- a/src/bin/sol-fbp-runner/web-inspector.css +++ b/src/bin/sol-fbp-runner/web-inspector.css @@ -16,173 +16,37 @@ * limitations under the License. */ -td.fbp-node-ports-in, td.fbp-node-ports-out { - min-width: 300pt; -} - -div.fbp-node-port-names-in, div.fbp-node-port-names-out { - font-family: monospace; - color: #333; -} - -div.fbp-node-port-description-in, div.fbp-node-port-description-out { - font-family: sans-serif; - font-size: smaller; - color: #999; -} - -div.fbp-node-port-data_type-in, div.fbp-node-port-data_type-in, span.fbp-packet { - font-family: monospace; -} - -span.fbp-packet-type-rgb-preview { - margin: 2pt 2pt 2pt 2pt; - padding: 2pt 2pt 2pt 2pt; - display: inline-block; - width: 10pt; - height: 10pt; - border: 1px solid black; -} - -div.fbp-node-port-required-true { - font-weight: bold; -} - -span.fbp-packet-type-int { - color: #0000aa; -} - -span.fbp-packet-type-float { - color: #aa00aa; -} - -span.fbp-packet-type-string { - color: #aa7700; -} - -span.fbp-packet-type-error { - color: #ff0000; -} - -span.fbp-packet-type-boolean { - color: #0077aa; -} - -table#fbp-container-inspector { - width: 100%; -} - -td.fbp-node-ports-in, td.fbp-node-ports-out { - padding-top: 30pt; - vertical-align: top; -} - -td.fbp-node-info h3 { - height: 30pt; - font-size: 1em; -} - -table.fbp-log { - width: 100%; -} - -table.fbp-log thead, table.fbp-log tbody { - display: block; -} - -table.fbp-log tbody { - height: 100pt; - overflow-y: auto; - overflow-x: auto; -} - -table.fbp-log tr td { - font-family: monospace; - font-size: smaller; -} - -td.fbp-log-timestamp { - text-align: right; -} - -td.fbp-node-info { - vertical-align: top; - min-width: 300pt; - border: 1px solid #ccc; - background-color: #d9d9d9; -} - -td.fbp-node-info dl { - font-size: x-small; -} - -td.fbp-node-info dl dt { - color: #666; - float: left; - clear: left; -} - -td.fbp-node-info dl dt:after { - content: ": "; -} - -td.fbp-node-info dl dd { - color: #333; - padding: 0 0 0.5em 0; - -webkit-margin-start: 10pt; -} - -span.fbp-node-option-type-rgb-preview { - margin: 1pt 1pt 1pt 1pt; - padding: 1pt 1pt 1pt 1pt; - display: inline-block; - width: 10pt; - height: 8pt; - border: 1px solid black; -} - -div.fbp-node-port-info-in, div.fbp-node-port-info-out, div.fbp-node-options-info { -} - -div.fbp-node-port-container-in, div.fbp-node-port-container-out { - margin: 1pt 1pt 1pt; - padding: 2pt 2pt 2pt; -} - -div.fbp-node-port-name-in { - margin: 1pt 1pt 1pt; - padding: 2pt 2pt 2pt; - float: right; - clear: right; - background-color: #d9d9d9; - border: 1px solid #ccc; -} - -div.fbp-node-port-value-in { - float: right; -} - -div.fbp-node-port-name-out { - margin: 1pt 1pt 1pt; - padding: 2pt 2pt 2pt; - float: left; - clear: left; - background-color: #d9d9d9; - border: 1px solid #ccc; -} - -div.fbp-node-port-value-out { - float: left; -} - -div.fbp-node-port-data_type-in-float div div div.fbp-node-port-name-in, div.fbp-node-port-data_type-out-float div div div.fbp-node-port-name-out { - background-color: #ff66ff; -} - -div.fbp-node-port-data_type-in-int div div div.fbp-node-port-name-in, div.fbp-node-port-data_type-out-int div div div.fbp-node-port-name-out { - background-color: #6666ff; -} - -div.fbp-node-port-data_type-in-boolean div div div.fbp-node-port-name-in, div.fbp-node-port-data_type-out-boolean div div div.fbp-node-port-name-out { - background-color: #66aaff; -} +.widget{ + background-color: #C0C0C0; + width:350px; + height:360px; + float:left; + margin:10px; + overflow: hidden;; + border-radius: 10px; +} +.widgetHeader{ + background-Color:#A0A0A0; + width: 350px; + height:50px; + padding-left: 10px; + padding-top: 10px +} +.widgetData{ + font-size: 3em; +} + +.port-in{ + width:100px; + height:30px; + background-color: #00FF00; + margin: 1px; + padding: 4px; +} +.port-out{ + width:100px; + height:30px; + background-color: #FF0000; + margin: 1px; + padding: 4px; +} \ No newline at end of file diff --git a/src/bin/sol-fbp-runner/web-inspector.html b/src/bin/sol-fbp-runner/web-inspector.html index a0f83ef8e..af80e96fd 100644 --- a/src/bin/sol-fbp-runner/web-inspector.html +++ b/src/bin/sol-fbp-runner/web-inspector.html @@ -1,57 +1,21 @@ - - - - - - -
- - -
-
- - - - - - - - -
Input PortsNodeOutput Ports
-
-
-
- -
-

Flow Packets Sent

- - - - - - - - - -
TimestampNodePortPacket
-
-
-
- -
-

Flow Packets Delivered

- - - - - - - - - -
TimestampNodePortPacket
-
- + + + + + + + + + + +
+ +
+
+ + + diff --git a/src/bin/sol-fbp-runner/web-inspector.js b/src/bin/sol-fbp-runner/web-inspector.js index e80f2630b..98f8dba5d 100644 --- a/src/bin/sol-fbp-runner/web-inspector.js +++ b/src/bin/sol-fbp-runner/web-inspector.js @@ -16,451 +16,178 @@ * limitations under the License. */ +var widgets = []; +var nodeId = -1; +var isCleared = false; +var max = 2; +var count = 0; + + +String.prototype.replaceAll = function(search, replacement) { + var target = this; + return target.replace(new RegExp(search, 'g'), replacement); +}; + + var FBPInspector = function () { - this.html = { - nodes: this.el("fbp-inspector-nodes"), - logSent: this.el("fbp-log-sent"), - logDelivered: this.el("fbp-log-delivered"), - start: this.el("fbp-start"), - finish: this.el("fbp-finish"), - }; if (!window.EventSource) { alert("Your browser does not support server-side-events (SSE): no EventSource()."); - this.html.start.disabled = true; - this.html.finish.disabled = true; return; } - - this.clearTableRows(this.html.nodes); - this.html.start.disabled = false; - this.html.finish.disabled = true; }; FBPInspector.prototype.el = function (id) { return document.getElementById(id); }; -FBPInspector.prototype.clearTableRows = function (domElem) { - while (domElem.rows.length) - domElem.deleteRow(0); -}; - -FBPInspector.prototype.addTableRow = function (domElem, idx, rowSpec) { - var r = domElem.insertRow(idx); - for (var i = 0; i < rowSpec.length; i++) { - var c = r.insertCell(i); - var rs = rowSpec[i]; - if (rs.content) - c.textContent = rs.content; - if (rs.html) - c.innerHTML = rs.html; - c.className = rs.className; - }; -}; FBPInspector.prototype.start = function () { - this.nodes = {}; - this.events = []; this.source = new EventSource(window.location.origin + '/events'); this.source.fbpInspector = this; this.source.onopen = function (e) { - this.fbpInspector.clearTableRows(this.fbpInspector.html.nodes); - this.fbpInspector.logDeliveredClear(); - this.fbpInspector.logSentClear(); - this.fbpInspector.html.start.disabled = true; - this.fbpInspector.html.finish.disabled = false; + //TODO }; this.source.onerror = function (e) { this.fbpInspector.finish(); }; + var ev; this.source.onmessage = function (e) { - var ev = JSON.parse(e.data); - this.fbpInspector.feedEvent(ev); - }; -}; - -FBPInspector.prototype.logSentClear = function () { - this.clearTableRows(this.html.logSent); -}; - -FBPInspector.prototype.logDeliveredClear = function () { - this.clearTableRows(this.html.logDelivered); -}; - -FBPInspector.prototype.getNodeName = function (node) { - if (this.nodes[node]) - return this.nodes[node].creation.payload.id || node; - return node; -}; - -FBPInspector.prototype.renderPacket = function (packet) { - var packet_type = packet.packet_type; - var payload = packet.payload; - var extraClass = ""; - var body = ""; - - if (packet_type == "empty" || - packet_type == "any") { - } else if (packet_type == "boolean" || - packet_type == "byte" || - packet_type == "timestamp") { - body = payload; - } else if (packet_type == "string") { - body = payload; // TODO: escape - } else if (payload instanceof Array) { - extraClass += " fbp-packet-composed"; - for (var i = 0; i < payload.length; i++) { - if (i > 0) - body += ', '; - body += this.renderPacket(payload[i]); - } - } else { - var keys = []; - for (var key in payload) { - if (!payload.hasOwnProperty(key)) - continue; - keys.push(key); + try { + feed(e.data); + } catch (err){ + var fixed = e.data.toString().replaceAll(":inf,",':"inf",'); + feed(fixed); } - - keys.sort(); - - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - var value = payload[key]; - if (i > 0) - body += ', '; - body += '' + - '' + key + ': ' + // TODO: escape - '' + value + '' + // TODO: escape - ''; - } - - if (packet_type == "rgb" && payload) { - var r = Math.round(255 * (payload.red / payload.red_max)); - var g = Math.round(255 * (payload.green / payload.green_max)); - var b = Math.round(255 * (payload.blue / payload.blue_max)); - - body += ''; + function feed(data){ + ev = JSON.parse(data); + this.fbpInspector.feedEvent(ev); } - } - - return '' + body + ''; + }; }; -FBPInspector.prototype.renderOptionValue = function (data_type, value) { - var extraClass = ""; - var body = ""; - - if (data_type == "boolean" || - data_type == "byte" || - data_type == "timestamp") { - body = value; - } else if (data_type == "string") { - body = value; // TODO: escape - } else { - var keys = []; - for (var key in value) { - if (!value.hasOwnProperty(key)) - continue; - keys.push(key); - } - - keys.sort(); - - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - var val = value[key]; - if (i > 0) - body += ', '; - body += '' + - '' + key + ': ' + // TODO: escape - '' + val + '' + // TODO: escape - ''; - } - - if (data_type == "rgb" && value) { - var r = Math.round(255 * (value.red / value.red_max)); - var g = Math.round(255 * (value.green / value.green_max)); - var b = Math.round(255 * (value.blue / value.blue_max)); - - body += ''; - } +FBPInspector.prototype.finish = function () { + if (this.source) { + this.source.close(); + this.source = null; } +}; - return '' + body + ''; -} - -FBPInspector.prototype.renderNodeInfo = function (node) { - var n = this.nodes[node]; - var payload = n.creation.payload; - var creationTimestamp = n.creation.timestamp; - var destructionTimestamp = n.destruction; +FBPInspector.prototype.logSentClear = function () {}; - // TODO: hadle escaping of html +FBPInspector.prototype.logDeliveredClear = function () {}; - var html = '

' + this.getNodeName(node) + '

' + - '
'; +FBPInspector.prototype.feedEvent = function (data) { - if (payload.type) { - html += '
type
' + - '
' + payload.type + '
'; - } + if (data.event == "open") { - if (payload.category) { - html += '
category
' + - '
' + payload.category + '
'; - } + if(data.payload.id.indexOf(".fbp") > -1) return; - if (payload.description) { - html += '
description
' + - '
' + payload.description + '
'; - } + var widget = new Widget(data.payload, widgets.length); + widgets.push(widget); - if (payload.author) { - html += '
author
' + - '
' + payload.author + '
'; - } + } else if (data.event == "close") { + //TODO - if (payload.url) { - html += '
url
' + - '
' + payload.url + '
'; - } + } else if (data.event == "connect") { + connectPorts(data.payload); - if (payload.license) { - html += '
license
' + - '
' + payload.license + '
'; - } + } else if (data.event == "disconnect") { + //TODO - if (payload.version) { - html += '
version
' + - '
' + payload.version + '
'; - } + } else if (data.event == "send") { - if (payload.options) { - html += '
options
' + - '
' + - '' + - '' + - '' + - '' + - ''; - - for (var i = 0; i < payload.options.length; i++) { - var o = payload.options[i]; - // TODO: hide fbp-node-options-info by default, dettach it and make a floating window on mouse-over row - html += '' + - '' + - '' + - '' + - ''; + if (!isCleared) { + widgets.forEach(function(item, index) { + item.clearPorts(); + }) + isCleared = true; } - html += '
NameValueInfo
' + o.name + '' + this.renderOptionValue(o.data_type, o.value) + '' + - '
' + - '
name
'+ o.name + '
' + - '
required
'+ o.required + '
' + - '
type
' + o.data_type + '
' + - '
default value
' + this.renderOptionValue(o.data_type, o.defvalue) + '
' + - '
description
' + o.description + '
' + - '
'; - } - - html += '
creation
' + - '
' + creationTimestamp + '
'; - - if (destructionTimestamp) { - html += '
destruction
' + - '
' + destructionTimestamp + '
'; - } - - return html; -}; - -FBPInspector.prototype.renderNodePorts = function (node, direction, descriptions) { - var n = this.nodes[node]; - var html = ""; + nodeId = data.payload.node; + widgets.forEach(function(widget, index) { + if (widget.getUID() === nodeId) { - // TODO: hadle escaping of html - - for (var i = 0; i < descriptions.length; i++) { - var pdesc = descriptions[i]; - var uid_prefix = direction + '-' + node + '-'; - var uid = uid_prefix + pdesc.base_port_idx; - - html += '
'; - - html += '
'; - - if (pdesc.array_size == 0) { - var port_uid = uid; - html += '
' + pdesc.name + '
' + - '
'; - } else { - for (var idx = 0; idx < pdesc.array_size; idx++) { - var port_uid = uid_prefix + pdesc.base_port_idx + idx; - html += '
' + pdesc.name + '[' + idx + ']
' + - '
'; + widget.update("send",data.payload); } - } + }); - // TODO: hide fbp-node-port-info by default, dettach it and make a floating window on mouse-over row - html += '
'; + } else if (data.event == "deliver") { //RECEIVED - var infoName = pdesc.name; - if (pdesc.array_size) { - infoName += '[' + pdesc.array_size + ']'; - } - - html += '
name
' + infoName + '
'; - html += '
required
' + pdesc.required + '
'; - html += '
type
' + pdesc.data_type + '
'; - html += '
description
' + pdesc.description + '
'; - - html += '
'; + nodeId = data.payload.node; + widgets.forEach(function(widget, index){ + if (widget.getUID() === nodeId) { + widget.update("deliver",data.payload); + } + }); } - return html; -}; - -FBPInspector.prototype.feedEvent = function (ev) { - this.events.push(ev); - - var payload = ev.payload; - - if (ev.event == "open") { - var path = payload.path; - var node = path[path.length - 1]; - this.nodes[node] = { - creation: ev, - destruction: null, - inputConnections: [], - outputConnections: [], - }; - - var row = this.html.nodes.insertRow(this.html.nodes.rows.length - 1); - row.id = "fbp-node-" + node; - row.className = "fbp-node"; - - var cell; - - cell = row.insertCell(0); - cell.id = "fbp-node-ports-in-" + node; - cell.className = "fbp-node-ports-in"; - cell.innerHTML = this.renderNodePorts(node, 'in', ev.payload.ports_in); - - cell = row.insertCell(1); - cell.id = "fbp-node-info-" + node; - cell.className = "fbp-node-info"; - cell.innerHTML = this.renderNodeInfo(node); - cell = row.insertCell(2); - cell.id = "fbp-node-ports-out-" + node; - cell.className = "fbp-node-ports-out"; - cell.innerHTML = this.renderNodePorts(node, 'out', ev.payload.ports_out); - - } else if (ev.event == "close") { - var node = payload; - - this.nodes[node].destruction = ev.timestamp; - - this.el("fbp-node-info-" + node).innerHTML += '
destruction
' + - '
' + ev.timestamp + '
'; - this.el("fbp-node-" + node).className += "fbp-node-closed"; - - } else if (ev.event == "connect") { - var srcConn = payload.src; - var dstConn = payload.dst; - - var srcNode = this.nodes[srcConn.node]; - var dstNode = this.nodes[dstConn.node]; - - srcNode.outputConnections.push(ev); - dstNode.inputConnections.push(ev); - - // TODO: show - - } else if (ev.event == "disconnect") { - var srcConn = payload.src; - var dstConn = payload.dst; - - var srcNode = this.nodes[srcConn.node]; - var dstNode = this.nodes[dstConn.node]; + function compareNames(a,b) { + return a === b; + } - var i; + var dest; + var src; + function connectPorts(data) { - for (i = 0; i < srcNode.outputConnections.length; i++) { - var c = srcNode.outputConnections[i]; - if (c.payload.src.conn_id == srcConn.conn_id) - srcNode.outputConnections.splice(i, 1); + dest = { + node: data.dst.node, + idx: data.dst.port_idx, + port: null } - for (i = 0; i < dstNode.inputConnections.length; i++) { - var c = dstNode.inputConnections[i]; - if (c.payload.dst.conn_id == dstConn.conn_id) - dstNode.inputConnections.splice(i, 1); + src = { + node: data.src.node, + idx: data.src.port_idx, + port: null } + //getting the source port + widgets.forEach(function(widget, index) { - // TODO: show - - } else if (ev.event == "send") { - var packetHtml = this.renderPacket(payload.packet); + if (widget.getUID() === src.node) { + src.port = widget.getOutByIndex(src.idx); + } else if (widget.getUID() === dest.node) { + dest.port = widget.getInByIndex(dest.idx) + }; - this.addTableRow(this.html.logSent, -1, - [{content: ev.timestamp, className: "fbp-log-timestamp"}, - {content: this.getNodeName(payload.node), className: "fbp-log-node"}, - {content: payload.port_name || payload.port_idx, className: "fbp-log-port"}, - {html: packetHtml, className: "fbp-log-packet"}]); + }); - var valEl = this.el("fbp-node-port-value-out-" + payload.node + "-" + payload.port_idx); - if (valEl) { - valEl.innerHTML = packetHtml; - // TODO: plot graph over timestamp + if (dest.port !== null) { + dest.port.connect(src.port); + dest.port.getElement().on("port-over", onPortMouseEvent); + dest.port.getElement().on("port-out", onPortMouseEvent); } - } else if (ev.event == "deliver") { - var packetHtml = this.renderPacket(payload.packet); - - this.addTableRow(this.html.logDelivered, -1, - [{content: ev.timestamp, className: "fbp-log-timestamp"}, - {content: this.getNodeName(payload.node), className: "fbp-log-node"}, - {content: payload.port_name || payload.port_idx, className: "fbp-log-port"}, - {html: packetHtml, className: "fbp-log-packet"}]); - var valEl = this.el("fbp-node-port-value-in-" + payload.node + "-" + payload.port_idx); - if (valEl) { - valEl.innerHTML = packetHtml; - // TODO: plot graph over timestamp + if (src.port !== null) { + src.port.connect(dest.port); + src.port.getElement().on("port-over", onPortMouseEvent); + src.port.getElement().on("port-out", onPortMouseEvent); } } -}; - -FBPInspector.prototype.finish = function () { - if (this.source) { - this.source.close(); - this.source = null; + function onPortMouseEvent(event){ + if (event.type == "port-over") { + event["connections"].forEach(function(item, index) { + $("#"+item).addClass("paired-slave"); + }); + $("#"+event["port"].key).addClass("paired-master"); + } else { + event["connections"].forEach(function(item, index) { + $("#"+item).removeClass("paired-slave"); + }); + $("#"+event["port"].key).removeClass("paired-master"); + } } - - this.html.start.disabled = false; - this.html.finish.disabled = true; }; window.onload = function () { + + window.modal = new Modal(); + window.fbpInspector = new FBPInspector(); + fbpInspector.start(); + };