Skip to content

Commit

Permalink
the-graph-thumb: Move rendering out of Polymer element
Browse files Browse the repository at this point in the history
  • Loading branch information
jonnor committed Jan 5, 2017
1 parent 22724a1 commit 10a1062
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 163 deletions.
4 changes: 3 additions & 1 deletion examples/demo-thumbnail.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
<title>the-graph-thumb documentation</title>
<meta charset="utf-8">

<!-- Polymer deps -->
<!-- Deps -->
<script src="../node_modules/webcomponents.js/webcomponents.js"></script>
<script src="../node_modules/react/dist/react.js"></script>
<script src="../node_modules/react-dom/dist/react-dom.js"></script>
<script src="../dist/the-graph.js"></script>

<link rel="import" href="../bower_components/polymer/polymer.html">
Expand Down
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ require("./the-graph/the-graph-menu.js").register(g);
require("./the-graph/the-graph-clipboard.js").register(g);
require("./the-graph/font-awesome-unicode-map.js").register(g);

g.TheGraph.thumb = require('./the-graph-thumb/the-graph-thumb.js');

module.exports = g.TheGraph;
176 changes: 14 additions & 162 deletions the-graph-thumb/the-graph-thumb.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
this.themeChanged();
},
themeChanged: function () {
// TODO: move to JS
if (this.theme === "dark") {
this.fillStyle = "hsl(184, 8%, 10%)";
this.strokeStyle = "hsl(180, 11%, 70%)";
Expand Down Expand Up @@ -85,25 +86,6 @@
// Redraw
this.redrawGraph();
},
drawEdge: function (context, scale, source, target, route) {
// Draw path
try {
context.strokeStyle = this.edgeColors[0];
if (route) {
// Color if route defined
context.strokeStyle = this.edgeColors[route];
}
var fromX = Math.round(source.metadata.x*scale)-0.5;
var fromY = Math.round(source.metadata.y*scale)-0.5;
var toX = Math.round(target.metadata.x*scale)-0.5;
var toY = Math.round(target.metadata.y*scale)-0.5;
context.beginPath();
context.moveTo(fromX, fromY);
context.lineTo(toX, toY);
context.stroke();
} catch (error) {
}
},
redrawGraph: function () {
if (!this.graph) {
return;
Expand All @@ -117,149 +99,19 @@
// Need the actual context, not polymer-wrapped one
context = unwrap(context);

// Reset origin
context.setTransform(1,0,0,1,0,0);
// Clear
context.clearRect(0, 0, this.width, this.height);
context.lineWidth = this.lineWidth;
// Find dimensions
var toDraw = [];
var minX = Infinity;
var minY = Infinity;
var maxX = -Infinity;
var maxY = -Infinity;
var nodes = {};

// Process nodes
this.graph.nodes.forEach(function(process){
if ( process.metadata && !isNaN(process.metadata.x) && !isNaN(process.metadata.y) ) {
toDraw.push(process);
nodes[process.id] = process;
minX = Math.min(minX, process.metadata.x);
minY = Math.min(minY, process.metadata.y);
maxX = Math.max(maxX, process.metadata.x);
maxY = Math.max(maxY, process.metadata.y);
}
}.bind(this));

// Process exported ports
if (this.graph.inports) {
Object.keys(this.graph.inports).forEach(function(key){
var exp = this.graph.inports[key];
if ( exp.metadata && !isNaN(exp.metadata.x) && !isNaN(exp.metadata.y) ) {
toDraw.push(exp);
minX = Math.min(minX, exp.metadata.x);
minY = Math.min(minY, exp.metadata.y);
maxX = Math.max(maxX, exp.metadata.x);
maxY = Math.max(maxY, exp.metadata.y);
}
}.bind(this));
}
if (this.graph.outports) {
Object.keys(this.graph.outports).forEach(function(key){
var exp = this.graph.outports[key];
if ( exp.metadata && !isNaN(exp.metadata.x) && !isNaN(exp.metadata.y) ) {
toDraw.push(exp);
minX = Math.min(minX, exp.metadata.x);
minY = Math.min(minY, exp.metadata.y);
maxX = Math.max(maxX, exp.metadata.x);
maxY = Math.max(maxY, exp.metadata.y);
}
}.bind(this));
}

// Sanity check graph size
if (!isFinite(minX) || !isFinite(minY) || !isFinite(maxX) || !isFinite(maxY) ) {
return;
}

minX -= this.nodeSize;
minY -= this.nodeSize;
maxX += this.nodeSize*2;
maxY += this.nodeSize*2;
var w = maxX - minX;
var h = maxY - minY;
// For the-graph-nav to bind
this.thumbrectangle[0] = minX;
this.thumbrectangle[1] = minY;
this.thumbrectangle[2] = w;
this.thumbrectangle[3] = h;
// Scale dimensions
var scale = (w > h) ? this.width/w : this.height/h;
this.thumbscale = scale;
var size = Math.round(this.nodeSize * scale);
var sizeHalf = size / 2;
// Translate origin to match
context.setTransform(1,0,0,1,0-minX*scale,0-minY*scale);

// Draw connection from inports to nodes
if (this.graph.inports) {
Object.keys(this.graph.inports).forEach(function(key){
var exp = this.graph.inports[key];
if ( exp.metadata && !isNaN(exp.metadata.x) && !isNaN(exp.metadata.y) ) {
var target = nodes[exp.process];
if (!target) {
return;
}
this.drawEdge(context, scale, exp, target, 2);
}
}.bind(this));
}
// Draw connection from nodes to outports
if (this.graph.outports) {
Object.keys(this.graph.outports).forEach(function(key){
var exp = this.graph.outports[key];
if ( exp.metadata && !isNaN(exp.metadata.x) && !isNaN(exp.metadata.y) ) {
var source = nodes[exp.process];
if (!source) {
return;
}
this.drawEdge(context, scale, source, exp, 5);
}
}.bind(this));
}

// Draw edges
this.graph.edges.forEach(function (connection){
var source = nodes[connection.from.node];
var target = nodes[connection.to.node];
if (!source || !target) {
return;
}
this.drawEdge(context, scale, source, target, connection.metadata.route);
}.bind(this));

// Draw nodes
toDraw.forEach(function (node){
var x = Math.round(node.metadata.x * scale);
var y = Math.round(node.metadata.y * scale);

// Outer circle
context.strokeStyle = this.strokeStyle;
context.fillStyle = this.fillStyle;
context.beginPath();
if (node.process && !node.component) {
context.arc(x, y, sizeHalf / 2, 0, 2*Math.PI, false);
} else {
context.arc(x, y, sizeHalf, 0, 2*Math.PI, false);
}
context.fill();
context.stroke();

// Inner circle
context.beginPath();
var smallRadius = Math.max(sizeHalf-1.5, 1);
if (node.process && !node.component) {
// Exported port
context.arc(x, y, smallRadius / 2, 0, 2*Math.PI, false);
} else {
// Regular node
context.arc(x, y, smallRadius, 0, 2*Math.PI, false);
}
context.fill();

}.bind(this));

var properties = {
width: this.width,
height: this.height,
edgeColors: this.edgeColors,
nodeSize: this.nodeSize,
strokeStyle: this.strokeStyle,
fillStyle: this.fillStyle,
lineWidth: this.lineWidth,
};
var thumb = TheGraph.thumb.render(context, this.graph, properties);

this.thumbrectangle = thumb.rectangle;
this.thumbscale = thumb.scale;
},
listener: null,
graphChanged: function (oldGraph, newGraph) {
Expand Down
179 changes: 179 additions & 0 deletions the-graph-thumb/the-graph-thumb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@

function drawEdge(context, scale, source, target, route, properties) {
// Draw path
try {
context.strokeStyle = properties.edgeColors[0];
if (route) {
// Color if route defined
context.strokeStyle = properties.edgeColors[route];
}
var fromX = Math.round(source.metadata.x*scale)-0.5;
var fromY = Math.round(source.metadata.y*scale)-0.5;
var toX = Math.round(target.metadata.x*scale)-0.5;
var toY = Math.round(target.metadata.y*scale)-0.5;
context.beginPath();
context.moveTo(fromX, fromY);
context.lineTo(toX, toY);
context.stroke();
} catch (error) {
// FIXME: handle?
}
}


function renderThumbnail(context, graph, properties) {

// Reset origin
context.setTransform(1,0,0,1,0,0);
// Clear
context.clearRect(0, 0, properties.width, properties.height);
context.lineWidth = properties.lineWidth;

// Find dimensions
var toDraw = [];
var minX = Infinity;
var minY = Infinity;
var maxX = -Infinity;
var maxY = -Infinity;
var nodes = {};

// Process nodes
graph.nodes.forEach(function(process){
if ( process.metadata && !isNaN(process.metadata.x) && !isNaN(process.metadata.y) ) {
toDraw.push(process);
nodes[process.id] = process;
minX = Math.min(minX, process.metadata.x);
minY = Math.min(minY, process.metadata.y);
maxX = Math.max(maxX, process.metadata.x);
maxY = Math.max(maxY, process.metadata.y);
}
}.bind(this));

// Process exported ports
if (graph.inports) {
Object.keys(graph.inports).forEach(function(key){
var exp = graph.inports[key];
if ( exp.metadata && !isNaN(exp.metadata.x) && !isNaN(exp.metadata.y) ) {
toDraw.push(exp);
minX = Math.min(minX, exp.metadata.x);
minY = Math.min(minY, exp.metadata.y);
maxX = Math.max(maxX, exp.metadata.x);
maxY = Math.max(maxY, exp.metadata.y);
}
}.bind(this));
}
if (graph.outports) {
Object.keys(graph.outports).forEach(function(key){
var exp = graph.outports[key];
if ( exp.metadata && !isNaN(exp.metadata.x) && !isNaN(exp.metadata.y) ) {
toDraw.push(exp);
minX = Math.min(minX, exp.metadata.x);
minY = Math.min(minY, exp.metadata.y);
maxX = Math.max(maxX, exp.metadata.x);
maxY = Math.max(maxY, exp.metadata.y);
}
}.bind(this));
}

// Sanity check graph size
if (!isFinite(minX) || !isFinite(minY) || !isFinite(maxX) || !isFinite(maxY) ) {
return;
}

minX -= properties.nodeSize;
minY -= properties.nodeSize;
maxX += properties.nodeSize*2;
maxY += properties.nodeSize*2;
var w = maxX - minX;
var h = maxY - minY;
// For the-graph-nav to bind
var thumbrectangle = [];
thumbrectangle[0] = minX;
thumbrectangle[1] = minY;
thumbrectangle[2] = w;
thumbrectangle[3] = h;
// Scale dimensions
var scale = (w > h) ? properties.width/w : properties.height/h;
var thumbscale = scale;
var size = Math.round(properties.nodeSize * scale);
var sizeHalf = size / 2;
// Translate origin to match
context.setTransform(1,0,0,1,0-minX*scale,0-minY*scale);

// Draw connection from inports to nodes
if (graph.inports) {
Object.keys(graph.inports).forEach(function(key){
var exp = graph.inports[key];
if ( exp.metadata && !isNaN(exp.metadata.x) && !isNaN(exp.metadata.y) ) {
var target = nodes[exp.process];
if (!target) {
return;
}
drawEdge(context, scale, exp, target, 2, properties);
}
}.bind(this));
}
// Draw connection from nodes to outports
if (graph.outports) {
Object.keys(graph.outports).forEach(function(key){
var exp = graph.outports[key];
if ( exp.metadata && !isNaN(exp.metadata.x) && !isNaN(exp.metadata.y) ) {
var source = nodes[exp.process];
if (!source) {
return;
}
drawEdge(context, scale, source, exp, 5, properties);
}
}.bind(this));
}

// Draw edges
graph.edges.forEach(function (connection){
var source = nodes[connection.from.node];
var target = nodes[connection.to.node];
if (!source || !target) {
return;
}
drawEdge(context, scale, source, target, connection.metadata.route, properties);
}.bind(this));

// Draw nodes
toDraw.forEach(function (node){
var x = Math.round(node.metadata.x * scale);
var y = Math.round(node.metadata.y * scale);

// Outer circle
context.strokeStyle = properties.strokeStyle;
context.fillStyle = properties.fillStyle;
context.beginPath();
if (node.process && !node.component) {
context.arc(x, y, sizeHalf / 2, 0, 2*Math.PI, false);
} else {
context.arc(x, y, sizeHalf, 0, 2*Math.PI, false);
}
context.fill();
context.stroke();

// Inner circle
context.beginPath();
var smallRadius = Math.max(sizeHalf-1.5, 1);
if (node.process && !node.component) {
// Exported port
context.arc(x, y, smallRadius / 2, 0, 2*Math.PI, false);
} else {
// Regular node
context.arc(x, y, smallRadius, 0, 2*Math.PI, false);
}
context.fill();

}.bind(this));

return {
rectangle: thumbrectangle,
scale: thumbscale
};
}

module.exports = {
render: renderThumbnail,
};

0 comments on commit 10a1062

Please sign in to comment.