Files @ 293cba6cec72
Branch filter:

Location: kallithea/kallithea/public/js/graph.js - annotation

Mads Kiilerich
eslint: fix "Unnecessary semicolon"
fb9550946c26
fb9550946c26
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
dba66b0768f4
dba66b0768f4
dba66b0768f4
dba66b0768f4
42bc65838fd1
dba66b0768f4
42d1e1ab41a8
d1addaf7a91e
d1addaf7a91e
97f8ae90566a
48a96c4059df
97f8ae90566a
97f8ae90566a
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
b3dd9cc3a035
b3dd9cc3a035
65f1d42383de
65f1d42383de
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
65f1d42383de
65f1d42383de
65f1d42383de
65f1d42383de
65f1d42383de
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
48a96c4059df
d1addaf7a91e
48a96c4059df
42bc65838fd1
42bc65838fd1
dba66b0768f4
d1addaf7a91e
2346f7b1b82a
2346f7b1b82a
2346f7b1b82a
d7420a74b98d
d7420a74b98d
d7420a74b98d
d7420a74b98d
d7420a74b98d
d7420a74b98d
d7420a74b98d
42bc65838fd1
42bc65838fd1
42bc65838fd1
42bc65838fd1
42bc65838fd1
42bc65838fd1
42bc65838fd1
42bc65838fd1
42bc65838fd1
d1addaf7a91e
d1addaf7a91e
1cc64983363a
d1addaf7a91e
d1addaf7a91e
493f5f62be18
dba66b0768f4
a49953fb84bf
dba66b0768f4
d1addaf7a91e
a49953fb84bf
dba66b0768f4
d1addaf7a91e
42d1e1ab41a8
fb9550946c26
fb9550946c26
fb9550946c26
fb9550946c26
fb9550946c26
fb9550946c26
fb9550946c26
fb9550946c26
fb9550946c26
d1addaf7a91e
5258b66bf5d7
d2053b8ab873
d2053b8ab873
16234f629cfb
16234f629cfb
d1addaf7a91e
d1addaf7a91e
fb9550946c26
fb9550946c26
fb9550946c26
fb9550946c26
fb9550946c26
42d1e1ab41a8
fb9550946c26
65f1d42383de
493f5f62be18
493f5f62be18
493f5f62be18
493f5f62be18
fb9550946c26
fb9550946c26
493f5f62be18
493f5f62be18
493f5f62be18
493f5f62be18
493f5f62be18
493f5f62be18
362652e72e29
362652e72e29
493f5f62be18
493f5f62be18
493f5f62be18
493f5f62be18
493f5f62be18
493f5f62be18
493f5f62be18
493f5f62be18
493f5f62be18
65f1d42383de
65f1d42383de
65f1d42383de
493f5f62be18
65f1d42383de
65f1d42383de
65f1d42383de
65f1d42383de
65f1d42383de
65f1d42383de
65f1d42383de
65f1d42383de
65f1d42383de
65f1d42383de
65f1d42383de
42d1e1ab41a8
d1addaf7a91e
d1addaf7a91e
46d42b34cf3e
46d42b34cf3e
46d42b34cf3e
46d42b34cf3e
46d42b34cf3e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
1cc64983363a
d1addaf7a91e
46d42b34cf3e
46d42b34cf3e
46d42b34cf3e
46d42b34cf3e
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
46d42b34cf3e
d1addaf7a91e
42d1e1ab41a8
fb9550946c26
fb9550946c26
42d1e1ab41a8
fb9550946c26
42d1e1ab41a8
d1addaf7a91e
9c1fe6f96146
9c1fe6f96146
9c1fe6f96146
9c1fe6f96146
64659280e466
fb9550946c26
64659280e466
64659280e466
64659280e466
64659280e466
64659280e466
64659280e466
64659280e466
64659280e466
64659280e466
64659280e466
b3dd9cc3a035
b3dd9cc3a035
b3dd9cc3a035
b3dd9cc3a035
b3dd9cc3a035
b3dd9cc3a035
b3dd9cc3a035
64659280e466
b3dd9cc3a035
b3dd9cc3a035
b3dd9cc3a035
d1addaf7a91e
d1addaf7a91e
42d1e1ab41a8
d1addaf7a91e
d1addaf7a91e
d1addaf7a91e
'use strict';

// branch_renderer.js - Rendering of branch DAGs on the client side
//
// Copyright 2010 Marcin Kuzminski <marcin AT python-works DOT com>
// Copyright 2008 Jesper Noehr <jesper AT noehr DOT org>
// Copyright 2008 Dirkjan Ochtman <dirkjan AT ochtman DOT nl>
// Copyright 2006 Alexander Schremmer <alex AT alexanderweb DOT de>
//
// derived from code written by Scott James Remnant <scott@ubuntu.com>
// Copyright 2005 Canonical Ltd.
//
// This software may be used and distributed according to the terms
// of the GNU General Public License, incorporated herein by reference.

var colors = [
	[ 1.0, 0.0, 0.0 ],
	[ 1.0, 1.0, 0.0 ],
	[ 0.0, 1.0, 0.0 ],
	[ 0.0, 1.0, 1.0 ],
	[ 0.0, 0.0, 1.0 ],
	[ 1.0, 0.0, 1.0 ],
	[ 1.0, 1.0, 0.0 ],
	[ 0.0, 0.0, 0.0 ]
];

function BranchRenderer(canvas_id, content_id, row_id_prefix) {
	// canvas_id is canvas to render into
	// content_id's height is applied to canvas
	// row_id_prefix is prefix that is applied to get row id's
	this.canvas = document.getElementById(canvas_id);
	var content = document.getElementById(content_id);

	if (!document.createElement("canvas").getContext)
		this.canvas = window.G_vmlCanvasManager.initElement(this.canvas);
	if (!this.canvas) { // canvas creation did for some reason fail - fail silently
		this.render = function(data) {};
		return;
	}
	this.ctx = this.canvas.getContext('2d');
	this.ctx.strokeStyle = 'rgb(0, 0, 0)';
	this.ctx.fillStyle = 'rgb(0, 0, 0)';
	this.cur = [0, 0];
	this.line_width = 2.0;
	this.dot_radius = 3.5;
	this.close_x = 1.5 * this.dot_radius;
	this.close_y = 0.5 * this.dot_radius;

	this.calcColor = function(color, bg, fg) {
		color %= colors.length;
		var red = (colors[color][0] * fg) || bg;
		var green = (colors[color][1] * fg) || bg;
		var blue = (colors[color][2] * fg) || bg;
		red = Math.round(red * 255);
		green = Math.round(green * 255);
		blue = Math.round(blue * 255);
		var s = 'rgb(' + red + ', ' + green + ', ' + blue + ')';
		return s;
	}

	this.setColor = function(color, bg, fg) {
		var s = this.calcColor(color, bg, fg);
		this.ctx.strokeStyle = s;
		this.ctx.fillStyle = s;
	}

	this.render = function(data) {
		var idx = 1;
		var canvasWidth = $(this.canvas).parent().width();

		this.canvas.setAttribute('width',canvasWidth);
		this.canvas.setAttribute('height',content.clientHeight);

		// HiDPI version needs to be scaled by 2x then halved via css
		// Note: Firefox on OS X fails scaling if the canvas height is more than 32k
		if (window.devicePixelRatio && content.clientHeight * window.devicePixelRatio < 32768) {
			this.canvas.setAttribute('width', canvasWidth * window.devicePixelRatio);
			this.canvas.setAttribute('height', content.clientHeight * window.devicePixelRatio);
			this.canvas.style.width = canvasWidth + "px";
			this.canvas.style.height = content.clientHeight + "px";
			this.ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
		}

		var lineCount = 1;
		for (var i=0;i<data.length;i++) {
			var in_l = data[i][1];
			for (var j in in_l) {
				var m = in_l[j][0];
				if (m > lineCount)
					lineCount = m;
			}
		}

		var edge_pad = this.dot_radius + 2;
		var box_size = Math.min(18, (canvasWidth - edge_pad * 2) / lineCount);
		var base_x = canvasWidth - edge_pad;

		for (var i=0; i < data.length; ++i) {
			var row = document.getElementById(row_id_prefix+idx);
			if (row == null) {
				console.log("error: row "+row_id_prefix+idx+" not found");
				continue;
			}
			var next = document.getElementById(row_id_prefix+(idx+1));
			var extra = 0;

			const cur = data[i];
			const node = cur[0];
			const in_l = cur[1];
			const closing = cur[2];
			const obsolete_node = cur[3];
			const bumped_node = cur[4];
			const divergent_node = cur[5];
			const extinct_node = cur[6];
			const unstable_node = cur[7];

			// center dots on the first element in a td (not necessarily the first one, but there must be one)
			var firstincell = $(row).find('td>*:visible')[0];
			var nextFirstincell = $(next).find('td>*:visible')[0];
			var rowY = Math.floor(row.offsetTop + firstincell.offsetTop + firstincell.offsetHeight/2);
			var nextY = Math.floor((next == null) ? rowY + row.offsetHeight/2 : next.offsetTop + nextFirstincell.offsetTop + nextFirstincell.offsetHeight/2);

			for (var j in in_l) {
				const line = in_l[j];
				const start = line[0];
				const end = line[1];
				const color = line[2];
				const obsolete_line = line[3];

				const x = Math.floor(base_x - box_size * start);

				// figure out if this is a dead-end;
				// we want to fade away this line
				var dead_end = true;
				if (next != null) {
					const nextdata = data[i+1];
					const next_l = nextdata[1];
					for (var k=0; k < next_l.length; ++k) {
						if (next_l[k][0] == end) {
							dead_end = false;
							break;
						}
					}
					if (nextdata[0][0] == end) // this is a root - not a dead end
						dead_end = false;
				}

				if (dead_end) {
					var gradient = this.ctx.createLinearGradient(x,rowY,x,nextY);
					gradient.addColorStop(0,this.calcColor(color, 0.0, 0.65));
					gradient.addColorStop(1,this.calcColor(color, 1.0, 0.0));
					this.ctx.strokeStyle = gradient;
					this.ctx.fillStyle = gradient;
				}
				// if this is a merge of differently
				// colored line, make it a gradient towards
				// the merged color
				else if (color != node[1] && start == node[0])
				{
					var gradient = this.ctx.createLinearGradient(x,rowY,x,nextY);
					gradient.addColorStop(0,this.calcColor(node[1], 0.0, 0.65));
					gradient.addColorStop(1,this.calcColor(color, 0.0, 0.65));
					this.ctx.strokeStyle = gradient;
					this.ctx.fillStyle = gradient;
				}
				else
				{
					this.setColor(color, 0.0, 0.65);
				}

				this.ctx.lineWidth=this.line_width;
				this.ctx.beginPath();
				if (obsolete_line)
				{
					this.ctx.setLineDash([5]);
				}
				this.ctx.beginPath();
				this.ctx.moveTo(x, rowY);
				if (start == end)
				{
					this.ctx.lineTo(x,nextY+extra,3);
				}
				else
				{
					var x2 = Math.floor(base_x - box_size * end);
					var ymid = (rowY+nextY) / 2;
					if (obsolete_node)
					{
						this.ctx.setLineDash([5]);
					}
					this.ctx.bezierCurveTo (x,ymid,x2,ymid,x2,nextY);
				}
				this.ctx.stroke();
				this.ctx.setLineDash([]); // reset the dashed line, if any
			}

			const column = node[0];
			const color = node[1];

			const x = Math.floor(base_x - box_size * column);

			this.setColor(color, 0.25, 0.75);
			if(unstable_node)
			{
				this.ctx.fillStyle = 'rgb(255, 0, 0)';
			}

			let r = this.dot_radius
			if (obsolete_node)
			{
				this.ctx.beginPath();
				this.ctx.moveTo(x - this.close_x, rowY - this.close_y - 3);
				this.ctx.lineTo(x - this.close_x + 2*this.close_x, rowY - this.close_y + 4*this.close_y - 1);
				this.ctx.moveTo(x - this.close_x, rowY - this.close_y + 4*this.close_y - 1);
				this.ctx.lineTo(x - this.close_x + 2*this.close_x, rowY - this.close_y - 3);
				this.ctx.stroke();
				r -= 0.5
			}
			if (closing)
			{
				this.ctx.fillRect(x - this.close_x, rowY - this.close_y, 2*this.close_x, 2*this.close_y);
			}
			else
			{
				this.ctx.beginPath();
				this.ctx.arc(x, rowY, r, 0, Math.PI * 2, true);
				this.ctx.fill();
			}

			idx++;
		}

	}

}