function drawTimedEventGraph2(timedEventGraph) {
const height = 600;
const nodeRadius = 30;
const wrapper = document.createElement("div");
wrapper.setAttribute("class", "teg-wrapper");
const svg = d3.create("svg").attr("width", width).attr("height", height);
wrapper.appendChild(svg.node());
let nodes = [...timedEventGraph.places, ...timedEventGraph.transitions];
let links = timedEventGraph.arcs[timedEventGraph.mode];
let tickCount2 = 0;
const maxTicks = 200;
let simulation = d3
.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(-900))
.force("center", d3.forceCenter(width / 2, height / 2))
.force("link", d3.forceLink(links).distance(200).strength(1))
.force("collide", d3.forceCollide(nodeRadius * 2));
var changeable = { simulation, tickCount: tickCount2, svg, animate: true };
var link = svg.selectAll(".link");
let place = svg.selectAll(".place");
function applyLink(link) {
return link
.data(links)
.join("line")
.attr("class", "link")
.attr("marker-end", "url(#arrowhead)");
}
function applyPlace(place, toolf) {
return place
.data(timedEventGraph.places)
.join("g")
.attr("class", "place")
.call(
d3
.drag()
.on("start", toolf.dragstarted)
.on("drag", toolf.dragged)
.on("end", toolf.dragended)
);
}
function applyTransition(transition, toolf) {
console.log(toolf.dragstarted.lol, "applyTransition update");
return transition
.data(timedEventGraph.transitions)
.join("g")
.attr("class", "transition-container")
.call(
d3
.drag()
.on("start", toolf.dragstarted)
.on("drag", toolf.dragged)
.on("end", toolf.dragended)
);
}
function applyLabel(label) {
return label
.data(nodes)
.join("text")
.attr("class", "label")
.text((d) => d.id)
.attr("text-anchor", "middle")
.attr("dy", ".3em");
}
/* place
.append("circle")
.attr("class", "outer-circle")
.attr("r", nodeRadius * 1.3)
.style("display", (d) => (d.holdingTime ? "block" : "none"));
place
.append("circle")
.attr("class", "inner-circle")
.attr("r", nodeRadius)
.style("display", (d) => "block");*/
let transitionheight = nodeRadius * 4;
// Create transition elements
let transition = svg.selectAll(".transition");
/* transition
.append("rect")
.attr("class", (d) => (d.holdingTime ? "transition" : "transition-filled"))
.attr("width", nodeRadius)
.attr("height", transitionheight)
.attr("rx", 3)
.attr("ry", 3);*/
const marker = svg
.append("defs")
.append("marker")
.attr("id", "arrowhead")
.attr("viewBox", "0 -5 10 10")
.attr("refX", nodeRadius * 1.3 + 5) // adjust the position of the arrowhead along the line
.attr("refY", 0)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,-5L10,0L0,5")
.attr("class", "arrowhead");
let label = applyLabel(svg.selectAll(".label"));
// console.log("before setUpdateCallback", timedEventGraph);
timedEventGraph.setUpdateCallback(updateVisualization);
// updateVisualization();
function updateVisualization({ tools }) {
let toolf = tools(changeable);
console.log("toolf.dragstarted", toolf.dragstarted.lol);
// Update nodes and links data
nodes = [...timedEventGraph.places, ...timedEventGraph.transitions];
links = timedEventGraph.arcs[timedEventGraph.mode];
// Update the simulation's nodes and links
changeable.simulation.nodes(nodes);
changeable.simulation.force("link").links(links);
changeable.simulation.alphaTarget(0.3).restart();
if (changeable.animate) {
// Restart the simulation
changeable.tickCount = 0;
} else {
changeable.tickCount = maxTicks - 2; //it needs to animate at least a bit
}
// Update the visualization elements
link = applyLink(link);
place = applyPlace(place, toolf);
place
.selectAll(".outer-circle")
.data((d) => [d])
.join("circle")
.attr("class", "outer-circle")
.attr("r", nodeRadius * 1.3)
.style("display", (d) => (d.holdingTime ? "block" : "none"));
place
.selectAll(".inner-circle")
.data((d) => [d])
.join("circle")
.attr("class", "inner-circle")
.attr("r", nodeRadius)
.style("display", (d) => "block");
/*transition
.append("rect")
.attr("class", (d) => (d.holdingTime ? "transition" : "transition-filled"))
.attr("width", nodeRadius)
.attr("height", transitionheight)
.attr("rx", 3)
.attr("ry", 3);*/
// Update transition elements
transition = applyTransition(transition, toolf);
transition
.selectAll("rect")
.data((d) => [d])
.join("rect")
.attr("class", (d) =>
d.holdingTime ? "transition" : "transition-filled"
)
.attr("width", nodeRadius)
.attr("height", transitionheight)
.attr("rx", 3)
.attr("ry", 3)
.attr("x", -nodeRadius / 2)
.attr("y", -transitionheight / 2);
// Draw tokens as dots inside the inner circle
// console.log("does this get executed");
place
.selectAll(".token-dot")
.data((d) => (d.tokens < 6 ? Array(d.tokens).fill(d) : []))
.join("circle")
.attr("class", "token-dot")
.attr("r", 3)
.attr(
"cx",
(d, i) => nodeRadius * 0.5 * Math.cos((i * 2 * Math.PI) / d.tokens)
)
.attr(
"cy",
(d, i) => nodeRadius * 0.5 * Math.sin((i * 2 * Math.PI) / d.tokens)
)
.style("display", (d) => "block");
// Display the numeric value for 6 or more tokens in the center
place
.selectAll(".token-count")
.data((d) => [d])
.join("text")
.attr("class", "token-count")
.attr("text-anchor", "middle")
.attr("dy", ".3em")
.text((d) => (d.tokens >= 6 ? d.tokens : ""))
.style("display", (d) => (d.tokens >= 6 ? "block" : "none"));
label = applyLabel(label);
}
function ticked() {
if (changeable.tickCount >= maxTicks) {
changeable.simulation.stop();
} else {
changeable.tickCount++;
}
// console.log("WHAT is link", link);
link
.attr("x1", (d) => d.source.x)
.attr("y1", (d) => d.source.y)
.attr("x2", (d) => d.target.x)
.attr("y2", (d) => d.target.y);
place.attr("transform", (d) => `translate(${d.x}, ${d.y})`);
transition.attr("transform", (d) => `translate(${d.x}, ${d.y})`);
/*transition
.attr("x", (d) => d.x - nodeRadius / 2)
.attr("y", (d) => d.y - transitionheight / 2);*/
//node.attr("cx", (d) => d.x).attr("cy", (d) => d.y);
label.attr("x", (d) => d.x).attr("y", (d) => d.y - transitionheight);
}
changeable.simulation.on("tick", ticked);
return wrapper;
}