Debugging environment for Dynamic Structure DEVS in HTML + JS (d3/w2ui).
', parameters['default'], this.toolbar, this.controller, this.inports['button_ui_input']);
} else if ('action' in parameters) {
this.action = parameters['action'];
this.btn = ui.create_button(this.button_id, parameters['description'], parameters['icon'], this.toolbar, this.controller, this.inports['button_ui_input']);
} else {
this.command = parameters['command'];
this.btn = ui.create_button(this.button_id, parameters['description'], parameters['icon'], this.toolbar, this.controller, this.inports['button_ui_input']);
}
]]>
this.visualized_simulator = "NETLOGO"
the_controller = this.controller;
this.simulation_info = d3.select("body").append("div")
.attr("class", "simulationInfo")
.style("margin", "5px")
.style("display", "block");
this.simulation_time = this.simulation_info.append("span")
.append("text")
.text("SIMULATION TIME: (not started)")
.style("float", "left");
this.simulation_steps = this.simulation_info.append("span")
.style("margin", "5px")
.style("float", "left")
.attr("class", "invisibleInfo")
.attr("id", "smallStepInfo");
this.simulation_steps.selectAll("div").data([0,1,2,3,4,5,6,7])
.enter()
.append("div")
.attr("id", function(d) {return "smallStepInfo_" + d})
.attr("class", "smallStepInfo inactive")
.style("transform", function(d) {return "translate(" + d * 5 + "px, -4px) rotate(45deg)"});
d3.select("body").append("br");
this.breakpoint_info = d3.select("body").append("div")
.attr("class", "breakpointInfo")
.style("margin", "5px")
.style("display", "block");
this.breakpoint_text = this.breakpoint_info.append("span")
.append("text")
.text("BREAKPOINTS: ")
.style("float", "left");
this.breakpoint_infos = this.breakpoint_info.append("span")
.style("margin", "5px")
.style("float", "left")
.attr("id", "breakpointInfos");
this.breakpoints = [];
this.port_connections = [];
this.loc_to_item = {};
event_to_inject = undefined;
god_event_to_process = undefined;
// TODO: this is domain-specific!
this.particle_id_to_item = {};
var margin = {top: 50, right: 0, bottom: 0, left: 0},
width = 960 - margin.right - margin.left,
height = 1024 - margin.top - margin.bottom;
this.node_id = 0;
if (this.visualized_simulator == "NETLOGO") {
this.data = [{'name': '<root>', 'children': [], 'loc': '', 'id': this.node_id}];
this.node_id++;
} else {
this.data = [];
}
this.tree = d3.layout.tree()
.size([width, height]);
this.diagonal = d3.svg.diagonal();
this.port_connection_diagonal = d3.svg.diagonal().projection(function(d) {return [d.x, d.y]});
this.parent_svg = d3.select("body").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom);
var defs = this.parent_svg.append('svg:defs')
var markers = [{name: 'arrow', path: 'M2,2 L2,11 L10,6 L2,2', fill: "red"},
{name: 'arrow_green', path: 'M2,2 L2,11 L10,6 L2,2', fill: "green"}];
var marker = defs.selectAll('marker')
.data(markers)
.enter()
.append('svg:marker')
.attr('id', function(d){ return 'marker_' + d.name})
.attr('markerHeight', 13)
.attr('markerWidth', 13)
.attr('markerUnits', 'strokeWidth')
.attr('orient', 'auto')
.attr('refX', 2)
.attr('refY', 6)
.append('svg:path')
.attr('d', function(d){ return d.path })
.attr('fill', function(d){ return d.fill });
this.svg = this.parent_svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
this_object = this;
function godEvent() {
if (this_object.visualized_simulator == "NETLOGO") {
god_event_to_process = {'turtle': $('#currLoc').text(), 'attribute': $('#godEventName').val(), 'value': eval($('#godEventValue').val())};
the_controller.addInput(new Event("process_god_event", "ui_input", [god_event_to_process]), 0.0);
dialog.dialog("close");
} else {
god_event_to_process = {'model': $('#currLoc').text(), 'attribute': $('#godEventName').val(), 'value': eval($('#godEventValue').val())};
the_controller.addInput(new Event("process_god_event", "ui_input", [god_event_to_process]), 0.0);
dialog.dialog("close");
}
}
dialog = $( "#godEventPopup" ).dialog({
autoOpen: false,
height: 200,
width: 325,
modal: true,
buttons: {
"Submit": godEvent,
Cancel: function() {
dialog.dialog( "close" );
}
},
close: function() {
form[ 0 ].reset();
}
}).css("font-size", "14px");;
form = dialog.find( "form" ).on( "submit", function( event ) {
event.preventDefault();
godEvent();
});
function injectEvent() {
event_to_inject = {'port': $('#currLoc').text(), 'event': eval($('#injectEvent').val()), 'time': eval($('#injectTime').val())};
the_controller.addInput(new Event("inject_event", "ui_input", [event_to_inject]), 0.0);
inject_dialog.dialog("close");
}
inject_dialog = $( "#injectEventPopup" ).dialog({
autoOpen: false,
height: 200,
width: 325,
modal: true,
buttons: {
"Submit": injectEvent,
Cancel: function() {
inject_dialog.dialog( "close" );
}
},
close: function() {
inject_form[ 0 ].reset();
}
}).css("font-size", "14px");
inject_form = inject_dialog.find( "form" ).on( "submit", function( event ) {
event.preventDefault();
injectEvent();
});
if (this.visualized_simulator == "NETLOGO") {
$('#breakpointFunction').text("def breakpoint(time, turtles):\n")
}
function addBreakpoint() {
breakpoint_to_add = [$('#breakpointName').val(), $('#breakpointFunction').val(), $('#breakpointEnabled').is(":checked"), $('#breakpointDisableOnTrigger').is(":checked")];
the_controller.addInput(new Event("add_breakpoint", "ui_input", [breakpoint_to_add]), 0.0);
breakpoint_dialog.dialog("close");
}
breakpoint_dialog = $( "#breakpointPopup" ).dialog({
autoOpen: false,
height: 400,
width: 600,
modal: true,
buttons: {
"Submit": addBreakpoint,
Cancel: function() {
breakpoint_dialog.dialog( "close" );
}
},
close: function() {
breakpoint_form[ 0 ].reset();
}
}).css("font-size", "14px");
breakpoint_form = breakpoint_dialog.find( "form" ).on( "submit", function( event ) {
event.preventDefault();
addBreakpoint();
});
if (this.visualized_simulator == "NETLOGO") {
var created_turtles = [],
deleted_turtles = [];
if ('CREATED_TURTLES' in structural_changes) {
created_turtles = structural_changes['CREATED_TURTLES'];
}
if ('DELETED_TURTLES' in structural_changes) {
deleted_turtles = structural_changes['DELETED_TURTLES'];
}
var node_id = this.node_id;
var loc_to_item = this.loc_to_item;
var data = this.data;
created_turtles.forEach(function(item) {
var node = {'name': 'turtle[' + item + ']', 'children': [], 'id': node_id++, 'turtle_id': item}
if (!data[0].hasOwnProperty('children')) {
data[0]['children'] = [];
}
data[0].children.push(node);
loc_to_item[item] = node;
});
deleted_turtles.forEach(function(item) {
curr_array = data;
data[0]['children'] = data[0]['children'].filter(function(el) {return el['name'] != ('turtle[' + item + ']')});
});
this.node_id = node_id;
this.data = data;
var nodes = this.tree.nodes(this.data[0]),
links = this.tree.links(nodes);
nodes.forEach(function(d, i) {
d.y = d.depth * 100 + i * 40;
});
// Declare the nodes...
var node = this.svg.selectAll("g.node")
.data(nodes, function(d) { return d.id; });
// Enter the nodes.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("id", function(d) {return 'instance_' + d.id;})
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
nodeEnter.append("rect")
.attr("width", 120)
.attr("height", 25)
.attr("transform", "translate(-60, 0)")
.on("click", function(d) {
console.log(JSON.stringify(d.state, null, 2));
})
.on("mouseover", function(d) {
var node = d3.select("#instance_" + d.id)
var stateInfo = node.selectAll(".stateInfo")
.data(function(n) {if (n.state) {return [n.state]} else {return []}}, function(d) {return d.id});
var stateInfoEnter = stateInfo.enter().append("text")
.attr("transform", "translate(-60, 60)")
.attr("id", this.node_id++)
.attr("class", "stateInfo");
var stateInfoText = stateInfo.selectAll("tspan")
.data(function(d) {return JSON.stringify(d, null, 2).split("\n")});
var stateInfoTextEnter = stateInfoText.enter().append("tspan")
.attr("x", "0.0")
.attr("dy", "1.4em")
.attr("xml:space", "preserve")
.text(function(d) {return d});
})
.on("mouseout", function(d) {
var node = d3.select("#instance_" + d.id)
var stateInfo = node.selectAll(".stateInfo");
stateInfo.selectAll("tspan").data([]).exit().remove();
})
.on("contextmenu", function (d, i) {
$( "#currLoc" ).html(d.turtle_id);
d3.event.preventDefault();
if (!d.children) {
dialog.dialog( "open" );
}
});
nodeEnter.append("text")
.attr("y", 12)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.name; })
.style("fill-opacity", 1);
// Declare the links...
var link = this.svg.selectAll("path.link")
.data(links);
// Enter the links.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", this.diagonal);
// Update the nodes.
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.classed("coupled", function(d) {return d.name == '<root>'});
// Transition links to their new position.
link.attr("d", this.diagonal);
// Remove nodes and links.
node.exit().remove();
link.exit().remove();
} else {
d3.select("#smallStepInfo_7").classed("inactive", false);
var created_models = [],
created_ports = [],
connected_ports = [],
deleted_models = [],
deleted_ports = [],
disconnected_ports = [];
if ('CREATED_MODELS' in structural_changes) {
created_models = structural_changes['CREATED_MODELS'];
}
if ('CREATED_PORTS' in structural_changes) {
created_ports = structural_changes['CREATED_PORTS'];
}
if ('CONNECTED_PORTS' in structural_changes) {
connected_ports = structural_changes['CONNECTED_PORTS'];
}
if ('DELETED_MODELS' in structural_changes) {
deleted_models = structural_changes['DELETED_MODELS'];
}
if ('DELETED_PORTS' in structural_changes) {
deleted_ports = structural_changes['DELETED_PORTS'];
}
if ('DISCONNECTED_PORTS' in structural_changes) {
disconnected_ports = structural_changes['DISCONNECTED_PORTS'];
}
// sort according to their depth (amounts of dots in their name)
created_models.sort(function(a, b) {
return (a.match(/./g) || []).length - (b.match(/./g) || []).length
})
data = this.data;
var node_id = this.node_id;
var loc_to_item = this.loc_to_item;
created_models.forEach(function(item) {
splitted_path = item.split('.');
element_to_insert = data;
while (splitted_path.length > 1) {
curr_name = splitted_path.shift();
element_to_insert = element_to_insert.find(function(el) {return el['name'] == curr_name}).children;
}
var node = {'name': splitted_path[0], 'children': [], 'ports': [], 'loc': item, 'id': node_id++}
element_to_insert.push(node);
loc_to_item[item] = node;
});
created_ports.forEach(function(item) {
splitted_path = item[0].split('.');
curr_array = data;
while (splitted_path.length > 2) {
curr_name = splitted_path.shift();
curr_array = curr_array.find(function(el) {return el['name'] == curr_name}).children;
}
ports = curr_array.find(function(el) {return el['name'] == splitted_path[0]})['ports'];
var node = {'name': splitted_path[1], 'is_input': item[1], 'loc': item[0], 'id': node_id++};
ports.push(node);
loc_to_item[item[0]] = node;
});
this.node_id = node_id;
port_connections = this.port_connections
connected_ports.forEach(function(item) {
splitted_path_src = item[0].split('.');
curr_array = data;
while (splitted_path_src.length > 2) {
curr_name = splitted_path_src.shift();
curr_array = curr_array.find(function(el) {return el['name'] == curr_name}).children;
}
src_parent = curr_array.find(function(el) {return el['name'] == splitted_path_src[0]});
src = src_parent['ports'].find(function(el) {return el['name'] == splitted_path_src[1]});
splitted_path_dst = item[1].split('.');
curr_array = data;
while (splitted_path_dst.length > 2) {
curr_name = splitted_path_dst.shift();
curr_array = curr_array.find(function(el) {return el['name'] == curr_name}).children;
}
dst_parent = curr_array.find(function(el) {return el['name'] == splitted_path_dst[0]});
dst = dst_parent['ports'].find(function(el) {return el['name'] == splitted_path_dst[1]});
port_connections.push({'source': src, 'target': dst});
});
disconnected_ports.forEach(function(item) {
port_connections = port_connections.filter(function(el) {return el.source.loc != item[0] || el.target.loc != item[1];});
});
this.port_connections = port_connections
deleted_ports.forEach(function(item) {
splitted_path = item.split('.');
curr_array = data;
while (splitted_path.length > 2) {
curr_name = splitted_path.shift();
curr_array = curr_array.find(function(el) {return el['name'] == curr_name}).children;
}
parent = curr_array.find(function(el) {return el['name'] == splitted_path[0]});
parent['ports'] = parent['ports'].filter(function(el) {return el['name'] != splitted_path[1]});
});
deleted_models.forEach(function(item) {
splitted_path = item.split('.');
curr_array = data;
while (splitted_path.length > 2) {
curr_name = splitted_path.shift();
curr_array = element_to_insert.find(function(el) {return el['name'] == curr_name}).children;
}
parent = curr_array.find(function(el) {return el['name'] == splitted_path[0]});
parent['children'] = parent['children'].filter(function(el) {return el['name'] != splitted_path[1]});
});
this.data = data;
var nodes = this.tree.nodes(this.data[0]),
links = this.tree.links(nodes);
nodes.forEach(function(d, i) {
d.y = d.depth * 100 + i * 40
d.ports.forEach(function(p, i) {p.dx = 13, p.dy = 18; p.x = (d.x - 40) + i * p.dx; p.y = d.y + p.dy;});
});
// Declare the nodes...
var node = this.svg.selectAll("g.node")
.data(nodes, function(d) { return d.id; });
// Enter the nodes.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("id", function(d) {return 'instance_' + d.id;})
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
nodeEnter.append("rect")
.attr("width", 120)
.attr("height", 25)
.attr("transform", "translate(-60, 0)")
.on("click", function(d) {
console.log(JSON.stringify(d.state, null, 2));
})
.on("mouseover", function(d) {
var node = d3.select("#instance_" + d.id)
var stateInfo = node.selectAll(".stateInfo")
.data(function(n) {if (n.state) {return [n.state]} else {return []}}, function(d) {return d.id});
var stateInfoEnter = stateInfo.enter().append("text")
.attr("transform", "translate(-60, 60)")
.attr("id", this.node_id++)
.attr("class", "stateInfo");
var stateInfoText = stateInfo.selectAll("tspan")
.data(function(d) {return JSON.stringify(d, null, 2).split("\n")});
var stateInfoTextEnter = stateInfoText.enter().append("tspan")
.attr("x", "0.0")
.attr("dy", "1.4em")
.attr("xml:space", "preserve")
.text(function(d) {return d});
})
.on("mouseout", function(d) {
var node = d3.select("#instance_" + d.id)
var stateInfo = node.selectAll(".stateInfo");
stateInfo.selectAll("tspan").data([]).exit().remove();
})
.on("contextmenu", function (d, i) {
$( "#currLoc" ).html(d.loc);
d3.event.preventDefault();
if (!d.children) {
dialog.dialog( "open" );
}
});
nodeEnter.append("text")
.attr("y", 12)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.name; })
.style("fill-opacity", 1);
nodeEnter.append("text")
.attr("class", "timeNext")
.attr("y", -10)
.attr("x", 30)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text("TN: --")
.style("fill-opacity", 1);
port = node.selectAll("g.port")
.data(function(n) {return n.ports}, function(d) { return d.id; })
portEnter = port.enter().append("g")
.attr("class", "port invisible")
.attr("id", function(d) {return 'port_' + d.id;})
.on("mouseover", function(d) {
d3.selectAll(".source_" + d.id).classed("invisibleLink", false)
.classed("input", false);
d3.selectAll(".target_" + d.id).classed("invisibleLink", false)
.classed("input", true);
port_connections.forEach(function(port_connection) {
if (port_connection.source.id == d.id) {
d3.select('#port_' + port_connection.target.id).attr("class", "port visible");
} else if (port_connection.target.id == d.id) {
d3.select('#port_' + port_connection.source.id).attr("class", "port visible");
}
});
d3.select(this).attr("class", "port visible");
})
.on("mouseout", function(d) {
d3.selectAll(".source_" + d.id).classed("invisibleLink", true);
d3.selectAll(".target_" + d.id).classed("invisibleLink", true);
d3.selectAll(".port").attr("class", "port invisible");
})
.on("click", function (d, i) {
$('#currLoc').html(d.loc);
d3.event.preventDefault();
if (d.is_input) {
inject_dialog.dialog( "open" );
}
});
portEnter.append("rect")
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d) {return d.is_input ? "green" : "purple";})
.attr("transform", "rotate(45)");
portEnter.append("text")
.attr("dy", ".35em")
.attr("text-anchor", "left")
.text(function(d) {return d.name;})
.attr("transform", "translate(0, 20) rotate(30)");
port.attr("transform", function(d, i) {return "translate(" + (-40 + i * d.dx) + ", " + d.dy + ")"});
// Declare the links...
var link = this.svg.selectAll("path.link")
.data(links);
// Enter the links.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", this.diagonal);
// Declare port connections...
var port_connection = this.svg.selectAll("path.portConnection")
.data(port_connections);
// Enter port connections.
port_connection.enter().insert("path", "g")
.attr("class", "invisibleLink portConnection");
// Update the nodes.
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.classed("coupled", function(d) {return d.children});
// Transition links to their new position.
link.attr("d", this.diagonal);
// Transition links to their new position.
port_connection.attr("d", function(d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy)/4,
mx = d.source.x + dx/2,
my = d.source.y + dy/2 + 30;
return [
"M",d.source.x,d.source.y+5,
"T",mx,my,
"T",d.target.x,d.target.y+5
].join(" ");
})
.attr("class", function(d) {return "invisibleLink portConnection source_" + d.source.id + " target_" + d.target.id});
// Remove nodes and links.
node.exit().remove();
link.exit().remove();
port.exit().remove();
port_connection.exit().remove();
}
if (this.visualized_simulator == "NETLOGO") {
for (var loc in initial_states) {
var item = this.loc_to_item[loc];
item.state = initial_states[loc];
}
} else {
d3.select("#smallStepInfo").classed("invisibleInfo", true);
d3.selectAll("g.node").attr("class", "node")
.classed("coupled", function(d) {return d.children});
d3.selectAll("circle.inmessage").data([]).exit().remove();
d3.selectAll("circle.outmessage").data([]).exit().remove();
d3.selectAll(".portConnection").classed("invisibleLink", true);
d3.selectAll(".port").classed("visible", false);
d3.selectAll(".port").classed("invisible", true);
d3.selectAll(".stateInfo").data([]).exit().remove();
for (var loc in initial_states) {
var item = this.loc_to_item[loc];
d3.select("#instance_" + item.id + " .timeNext").text("TN: " + initial_states[loc][0][0] + "/" + initial_states[loc][0][1])
item.state = initial_states[loc][1];
if (item.state.particle_id) {
this.particle_id_to_item[item.state.particle_id] = item; // TODO: this is somewhat ugly, we're making a lot of assumptions here and it's no longer domain-independent!
}
}
}
d3.select("#smallStepInfo").classed("invisibleInfo", true);
d3.selectAll("g.node").attr("class", "node")
.classed("coupled", function(d) {return d.children});
d3.selectAll("circle.inmessage").data([]).exit().remove();
d3.selectAll("circle.outmessage").data([]).exit().remove();
d3.selectAll(".portConnection").classed("invisibleLink", true);
d3.selectAll(".port").classed("visible", false);
d3.selectAll(".port").classed("invisible", true);
d3.selectAll(".stateInfo").data([]).exit().remove();
for (var loc in new_tn) {
var item = this.loc_to_item[loc];
d3.select("#instance_" + item.id + " .timeNext").text("TN: " + new_tn[loc][0] + "/" + new_tn[loc][1])
item.state = new_states[loc];
if (item.state.particle_id != undefined) {
this.particle_id_to_item[item.state.particle_id] = item; // TODO: this is somewhat ugly, we're making a lot of assumptions here and it's no longer domain-independent!
}
}
d3.selectAll(".portConnection").classed("invisibleLink", true);
d3.selectAll(".port").classed("visible", false);
d3.selectAll(".port").classed("invisible", true);
d3.selectAll("circle.inmessage").data([]).exit().remove();
d3.selectAll("circle.outmessage").data([]).exit().remove();
if (this.transitioning_nodes) {
this.transitioning_nodes.forEach(function(n) {n.attr("class", "node")
.classed("coupled", function(d) {return d.children});});
}
d3.select("#smallStepInfo").classed("invisibleInfo", false);
d3.selectAll(".smallStepInfo").classed("inactive", true);
d3.select("#smallStepInfo_0").classed("inactive", false);
var loc_to_item = this.loc_to_item;
this.imminents = imminents;
imminents.forEach(function(imminent) {
d3.select("#instance_" + loc_to_item[imminent].id).classed("imminent", true);
})
d3.select("#smallStepInfo_1").classed("inactive", false);
var loc_to_item = this.loc_to_item;
this.imminents.forEach(function(imminent) {
if (!(imminent == selected_imminent)) {
d3.select("#instance_" + loc_to_item[imminent].id).classed("imminent", false);
}
})
var total_msgs = [];
for (var key in bag) {
var msgs = bag[key];
var port = this.loc_to_item[key];
if (port != undefined) {
msgs[0].port = port;
Array.prototype.push.apply(total_msgs, msgs);
}
}
var msgs_vis = this.svg.selectAll("circle." + msg_type)
.data(total_msgs);
var msg_enter = msgs_vis.enter().append("circle")
.attr("class", msg_type)
.attr("id", function(m) {return "msg_" + m.port.id;})
.attr("r", 5)
.attr("transform", function(m) {return "translate(" + m.port.x + "," + (m.port.y + 22) + ")"})
.on("click", function(d) {console.log(d[0])});
d3.select("#smallStepInfo_3").classed("inactive", false);
function transition(circle, path, source_port_vis, target_port_vis) {
circle.transition()
.duration(3000)
.attrTween("transform", translateAlong(path.node()))
.each("end", function() {
path.classed("invisibleLink", true);
source_port_vis.classed("invisible", true);
target_port_vis.classed("invisible", true);
source_port_vis.classed("visible", false);
target_port_vis.classed("visible", false);
circle.attr("class", "inmessage");
});
}
// Returns an attrTween for translating along the specified path element.
function translateAlong(path) {
var l = path.getTotalLength();
return function(d, i, a) {
return function(t) {
var p = path.getPointAtLength(t * l);
return "translate(" + p.x + "," + (p.y + 17) + ")";
};
};
}
var outports_visited = []
for (var key in inbags) {
if (inbags[key].length == 2) {
var msgs = inbags[key][1];
var inport = this.loc_to_item[key];
if (inport != undefined) {
var circle = undefined;
var outport_id = this.loc_to_item[inbags[key][0]].id;
if (outports_visited.indexOf(outport_id) > -1) {
circle = d3.select('#msg_' + outport_id);
var parent = d3.select(circle.node().parentNode);
circle = parent.append("circle")
.attr("class", "outmessage")
.attr("id", circle.id + outports_visited.indexOf(outport_id))
.attr("r", 5)
.attr("transform", circle.transform)
.on("click", (function(msgs) {return function(d) {console.log(msgs[0])}})(msgs));
} else {
circle = d3.select('#msg_' + outport_id);
circle.on("click", (function(msgs) {return function(d) {console.log(msgs[0])}})(msgs));
}
var path = d3.select(".source_" + outport_id + ".target_" + inport.id);
var source_port_vis = d3.select("#port_" + outport_id)
var target_port_vis = d3.select("#port_" + inport.id)
source_port_vis.classed("invisible", false);
target_port_vis.classed("invisible", false);
source_port_vis.classed("visible", true);
target_port_vis.classed("visible", true);
path.classed("invisibleLink", false);
transition(circle, path, source_port_vis, target_port_vis);
outports_visited.push(outport_id);
}
} else {
var msgs = inbags[key][0];
var inport = this.loc_to_item[key];
this.svg.append("circle")
.attr("class", "inmessage")
.attr("id", "msg_" + inport.id)
.attr("r", 5)
.attr("transform", "translate(" + inport.x + "," + (inport.y + 22) + ")")
.on("click", (function(msgs) {return function(d) {console.log(msgs[0])}})(msgs));
}
}
var transitioning_nodes = [];
var loc_to_item = this.loc_to_item;
Object.keys(transitioning).forEach(function(key) {
transitioning_nodes.push(d3.select("#instance_" + loc_to_item[key].id).classed(transitioning[key], true));
});
this.transitioning_nodes = transitioning_nodes;
d3.select("#smallStepInfo_5").classed("inactive", false);
for (var loc in new_internal_states) {
var item = this.loc_to_item[loc];
item.state = new_internal_states[loc];
}
if (this.transitioning_nodes) {
this.transitioning_nodes.forEach(function(n) {n.attr("class", "node")
.classed("coupled", function(d) {return d.children});});
}
var node = this.svg.selectAll("g.node");
var stateInfo = node.selectAll("g.state");
stateInfo.text(function(d) {return JSON.stringify(d);});
d3.select("#smallStepInfo_6").classed("inactive", false);
for (var loc in new_tn) {
var item = this.loc_to_item[loc];
d3.select("#instance_" + item.id + " .timeNext").text("TN: " + new_tn[loc][0] + "/" + new_tn[loc][1])
}
d3.selectAll(".stateInfo").data([]).exit().remove();
if (instance_id in this.particle_id_to_item) {
var d = this.particle_id_to_item[instance_id];
var node = d3.select("#instance_" + d.id)
var stateInfo = node.selectAll(".stateInfo")
.data(function(n) {if (n.state) {return [n.state]} else {return []}}, function(d) {return d.id});
var stateInfoEnter = stateInfo.enter().append("text")
.attr("transform", "translate(-60, 60)")
.attr("id", this.node_id++)
.attr("class", "stateInfo");
var stateInfoText = stateInfo.selectAll("tspan")
.data(function(d) {return JSON.stringify(d, null, 2).split("\n")});
var stateInfoTextEnter = stateInfoText.enter().append("tspan")
.attr("x", "0.0")
.attr("dy", "1.4em")
.attr("xml:space", "preserve")
.text(function(d) {return d});
}
if (this.visualized_simulator == "PYDEVS") {
for (idx in this.breakpoints) {
var curr_bp = this.breakpoints[idx];
if (curr_bp.triggered) {
this.visualize_messages(curr_bp.outbag, 'outmessage');
for (var key in curr_bp.inbags) {
if (curr_bp.inbags[key].length == 2) {
curr_bp.inbags[key] = [curr_bp.inbags[key][1]];
}
}
this.visualize_messages(curr_bp.inbags, 'inmessage');
this.visualize_transitioning(curr_bp.transitioned);
}
}
}
var curr_bps = this.breakpoint_infos.selectAll("div").data(this.breakpoints)
curr_bps_enter = curr_bps.enter().append("div")
.attr("id", function(d) {return "breakpoint_" + d.name})
.attr("class", "breakpoint")
.style("transform", function(d, i) {return "translate(" + i * 5 + "px, -8px)"})
.style("float", "left");
curr_bps_enter.append("text")
.text(function(d) {return d.name})
.on("click", function(d) {
d.enabled = !d.enabled;
the_controller.addInput(new Event("toggle_breakpoint", "ui_input", [d.name, d.enabled]), 0.0);
})
.on('mouseover', function() {
d3.event.preventDefault();
});
curr_bps_enter.append("img")
.attr('src', 'img/delete-bp.png')
.style('transform', 'translate(1px, 2px)')
.on("click", function(d) {
the_controller.addInput(new Event("del_breakpoint", "ui_input", [d.name]), 0.0);
});
curr_bps.exit().remove();
curr_bps.style("background-color", function(d) {
if (d.triggered) {
d.triggered = false;
if (d.disable_on_trigger) {
d.enabled = false;
}
return "red";
} else {
return "transparent";
}});
curr_bps.select("text").style("opacity", function(d) {if (d.enabled) return "1"; else return "0.5";});