/*
* This file is part of Toolkit.
*
* Toolkit is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* Toolkit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General
* Public License along with this program; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
"use strict";
(function(w, TK){
function calculate_overlap(X, Y) {
/* no overlap, return 0 */
if (X[2] < Y[0] || Y[2] < X[0] || X[3] < Y[1] || Y[3] < X[1]) return 0;
return (Math.min(X[2], Y[2]) - Math.max(X[0], Y[0])) *
(Math.min(X[3], Y[3]) - Math.max(X[1], Y[1]));
}
function show_handles() {
var handles = this.handles;
for (var i = 0; i < handles.length; i++) {
this.add_child(handles[i]);
}
}
function hide_handles() {
var handles = this.handles;
for (var i = 0; i < handles.length; i++) {
this.remove_child(handles[i]);
}
}
var STOP = function(e) {
e.preventDefault();
e.stopPropagation();
return false;
}
function draw_key() {
var __key, bb;
var _key = this._key;
var _key_bg = this._key_background;
if (!_key || !_key_bg) return;
while (_key.firstChild !== _key.lastChild)
_key.removeChild(_key.lastChild);
TK.empty(_key.firstChild);
var O = this.options;
var disp = "none";
var gpad = TK.css_space(_key, "padding");
var gmarg = TK.css_space(_key, "margin");
var c = 0;
var w = 0;
var top = 0;
var lines = [];
for (var i = 0; i < this.graphs.length; i++) {
if (this.graphs[i].get("key") !== false) {
var t = TK.make_svg("tspan", {"class": "toolkit-label",
style: "dominant-baseline: central;"
});
t.textContent = this.graphs[i].get("key");
t.setAttribute("x", gpad.left);
_key.firstChild.appendChild(t);
if (!bb) bb = _key.getBoundingClientRect();
top += c ? parseInt(TK.get_style(t, "line-height")) : gpad.top;
t.setAttribute("y", top + bb.height / 2);
lines.push({
x: (parseInt(TK.get_style(t, "margin-right")) || 0),
y: Math.round(top),
width: Math.round(bb.width),
height: Math.round(bb.height),
"class": this.graphs[i].element.getAttribute("class"),
color: (this.graphs[i].element.getAttribute("color") || ""),
style: this.graphs[i].element.getAttribute("style")
})
w = Math.max(w, t.getComputedTextLength());
disp = "block";
c++;
}
}
for (var i = 0; i < lines.length; i++) {
var b = TK.make_svg("rect", {
"class": lines[i]["class"] + " toolkit-rect",
color: lines[i].color,
style: lines[i].style,
x: lines[i].x + 0.5 + w + gpad.left,
y: lines[i].y + 0.5 + parseInt(lines[i].height / 2 - O.key_size.y / 2),
height: O.key_size.y,
width: O.key_size.x
});
_key.appendChild(b);
}
_key_bg.style.display = disp;
_key.style.display = disp;
bb = _key.getBoundingClientRect();
var width = this.range_x.options.basis;
var height = this.range_y.options.basis;
switch (O.key) {
case "top-left":
__key = {
x1: gmarg.left,
y1: gmarg.top,
x2: gmarg.left + parseInt(bb.width) + gpad.left + gpad.right,
y2: gmarg.top + parseInt(bb.height) + gpad.top + gpad.bottom
}
break;
case "top-right":
__key = {
x1: width - gmarg.right - parseInt(bb.width) - gpad.left - gpad.right,
y1: gmarg.top,
x2: width - gmarg.right,
y2: gmarg.top + parseInt(bb.height) + gpad.top + gpad.bottom
}
break;
case "bottom-left":
__key = {
x1: gmarg.left,
y1: height - gmarg.bottom - parseInt(bb.height) - gpad.top - gpad.bottom,
x2: gmarg.left + parseInt(bb.width) + gpad.left + gpad.right,
y2: height - gmarg.bottom
}
break;
case "bottom-right":
__key = {
x1: width - gmarg.right - parseInt(bb.width) - gpad.left - gpad.right,
y1: height -gmarg.bottom - parseInt(bb.height) - gpad.top - gpad.bottom,
x2: width - gmarg.right,
y2: height - gmarg.bottom
}
break;
default:
TK.warn("Unsupported key", O.key);
}
_key.setAttribute("transform", "translate(" + __key.x1 + "," + __key.y1 + ")");
_key_bg.setAttribute("x", __key.x1);
_key_bg.setAttribute("y", __key.y1);
_key_bg.setAttribute("width", __key.x2 - __key.x1);
_key_bg.setAttribute("height", __key.y2 - __key.y1);
}
function draw_title() {
var _title = this._title;
if (!_title) return;
_title.textContent = this.options.title;
/* FORCE_RELAYOUT */
TK.S.add(function() {
var mtop = parseInt(TK.get_style(_title, "margin-top") || 0);
var mleft = parseInt(TK.get_style(_title, "margin-left") || 0);
var mbottom = parseInt(TK.get_style(_title, "margin-bottom") || 0);
var mright = parseInt(TK.get_style(_title, "margin-right") || 0);
var bb = _title.getBoundingClientRect();
var x,y,anchor, range_x = this.range_x, range_y = this.range_y;
switch (this.options.title_position) {
case "top-left":
anchor = "start";
x = mleft;
y = mtop + bb.height / 2;
break;
case "top":
anchor = "middle";
x = range_x.options.basis / 2;
y = mtop + bb.height / 2;
break;
case "top-right":
anchor = "end";
x = range_x.options.basis - mright;
y = mtop + bb.height / 2;
break;
case "left":
anchor = "start";
x = mleft;
y = range_y.options.basis / 2;
break;
case "center":
anchor = "middle";
x = range_x.options.basis / 2;
y = range_y.options.basis / 2;
break;
case "right":
anchor = "end";
x = range_x.options.basis - mright;
y = range_y.options.basis / 2;
break;
case "bottom-left":
anchor = "start";
x = mleft;
y = range_y.options.basis - mtop - bb.height / 2;
break;
case "bottom":
anchor = "middle";
x = range_x.options.basis / 2;
y = range_y.options.basis - mtop - bb.height / 2;
break;
case "bottom-right":
anchor = "end";
x = range_x.options.basis - mright;
y = range_y.options.basis - mtop - bb.height / 2;
break;
default:
TK.warn("Unsupported title_position", this.options.title_position);
}
TK.S.add(function() {
_title.setAttribute("text-anchor", anchor);
_title.setAttribute("x", x);
_title.setAttribute("y", y);
}, 1);
}.bind(this));
}
/**
* TK.Chart is an SVG image containing one or more Graphs. TK.Chart
* extends {@link TK.Widget} and contains a {@link TK.Grid} and two
* {@link TK.Range}s.
*
* @param {Object} [options={ }] - An object containing initial options.
*
* @property {String|Boolean} [options.title=""] - A title for the Chart.
* Set to `false` to remove the title from the DOM.
* @property {String} [options.title_position="top-right"] - Position of the
* title inside of the chart. Possible values are
* "top-left", "top", "top-right",
* "left", "center", "right",
* "bottom-left", "bottom" and
* "bottom-right".
* @property {Boolean|String} [options.key=false] - If set to a string
* a key is rendered into the chart at the given position. The key
* will detail names and colors of the graphs inside of this chart.
* Possible values are "top-left", "top-right",
* "bottom-left" and "bottom-right". Set to `false`
* to remove the key from the DOM.
* @property {Object} [options.key_size={x:20,y:10}] - Size of the colored
* rectangles inside of the key describing individual graphs.
* @property {Array