odoo/addons/web_graph/static/lib/flotr2/js/types/gantt.js

230 lines
6.9 KiB
JavaScript

/** Gantt
* Base on data in form [s,y,d] where:
* y - executor or simply y value
* s - task start value
* d - task duration
* **/
Flotr.addType('gantt', {
options: {
show: false, // => setting to true will show gantt, false will hide
lineWidth: 2, // => in pixels
barWidth: 1, // => in units of the x axis
fill: true, // => true to fill the area from the line to the x axis, false for (transparent) no fill
fillColor: null, // => fill color
fillOpacity: 0.4, // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill
centered: true // => center the bars to their x axis value
},
/**
* Draws gantt series in the canvas element.
* @param {Object} series - Series with options.gantt.show = true.
*/
draw: function(series) {
var ctx = this.ctx,
bw = series.gantt.barWidth,
lw = Math.min(series.gantt.lineWidth, bw);
ctx.save();
ctx.translate(this.plotOffset.left, this.plotOffset.top);
ctx.lineJoin = 'miter';
/**
* @todo linewidth not interpreted the right way.
*/
ctx.lineWidth = lw;
ctx.strokeStyle = series.color;
ctx.save();
this.gantt.plotShadows(series, bw, 0, series.gantt.fill);
ctx.restore();
if(series.gantt.fill){
var color = series.gantt.fillColor || series.color;
ctx.fillStyle = this.processColor(color, {opacity: series.gantt.fillOpacity});
}
this.gantt.plot(series, bw, 0, series.gantt.fill);
ctx.restore();
},
plot: function(series, barWidth, offset, fill){
var data = series.data;
if(data.length < 1) return;
var xa = series.xaxis,
ya = series.yaxis,
ctx = this.ctx, i;
for(i = 0; i < data.length; i++){
var y = data[i][0],
s = data[i][1],
d = data[i][2],
drawLeft = true, drawTop = true, drawRight = true;
if (s === null || d === null) continue;
var left = s,
right = s + d,
bottom = y - (series.gantt.centered ? barWidth/2 : 0),
top = y + barWidth - (series.gantt.centered ? barWidth/2 : 0);
if(right < xa.min || left > xa.max || top < ya.min || bottom > ya.max)
continue;
if(left < xa.min){
left = xa.min;
drawLeft = false;
}
if(right > xa.max){
right = xa.max;
if (xa.lastSerie != series)
drawTop = false;
}
if(bottom < ya.min)
bottom = ya.min;
if(top > ya.max){
top = ya.max;
if (ya.lastSerie != series)
drawTop = false;
}
/**
* Fill the bar.
*/
if(fill){
ctx.beginPath();
ctx.moveTo(xa.d2p(left), ya.d2p(bottom) + offset);
ctx.lineTo(xa.d2p(left), ya.d2p(top) + offset);
ctx.lineTo(xa.d2p(right), ya.d2p(top) + offset);
ctx.lineTo(xa.d2p(right), ya.d2p(bottom) + offset);
ctx.fill();
ctx.closePath();
}
/**
* Draw bar outline/border.
*/
if(series.gantt.lineWidth && (drawLeft || drawRight || drawTop)){
ctx.beginPath();
ctx.moveTo(xa.d2p(left), ya.d2p(bottom) + offset);
ctx[drawLeft ?'lineTo':'moveTo'](xa.d2p(left), ya.d2p(top) + offset);
ctx[drawTop ?'lineTo':'moveTo'](xa.d2p(right), ya.d2p(top) + offset);
ctx[drawRight?'lineTo':'moveTo'](xa.d2p(right), ya.d2p(bottom) + offset);
ctx.stroke();
ctx.closePath();
}
}
},
plotShadows: function(series, barWidth, offset){
var data = series.data;
if(data.length < 1) return;
var i, y, s, d,
xa = series.xaxis,
ya = series.yaxis,
ctx = this.ctx,
sw = this.options.shadowSize;
for(i = 0; i < data.length; i++){
y = data[i][0];
s = data[i][1];
d = data[i][2];
if (s === null || d === null) continue;
var left = s,
right = s + d,
bottom = y - (series.gantt.centered ? barWidth/2 : 0),
top = y + barWidth - (series.gantt.centered ? barWidth/2 : 0);
if(right < xa.min || left > xa.max || top < ya.min || bottom > ya.max)
continue;
if(left < xa.min) left = xa.min;
if(right > xa.max) right = xa.max;
if(bottom < ya.min) bottom = ya.min;
if(top > ya.max) top = ya.max;
var width = xa.d2p(right)-xa.d2p(left)-((xa.d2p(right)+sw <= this.plotWidth) ? 0 : sw);
var height = ya.d2p(bottom)-ya.d2p(top)-((ya.d2p(bottom)+sw <= this.plotHeight) ? 0 : sw );
ctx.fillStyle = 'rgba(0,0,0,0.05)';
ctx.fillRect(Math.min(xa.d2p(left)+sw, this.plotWidth), Math.min(ya.d2p(top)+sw, this.plotHeight), width, height);
}
},
extendXRange: function(axis) {
if(axis.options.max === null){
var newmin = axis.min,
newmax = axis.max,
i, j, x, s, g,
stackedSumsPos = {},
stackedSumsNeg = {},
lastSerie = null;
for(i = 0; i < this.series.length; ++i){
s = this.series[i];
g = s.gantt;
if(g.show && s.xaxis == axis) {
for (j = 0; j < s.data.length; j++) {
if (g.show) {
y = s.data[j][0]+'';
stackedSumsPos[y] = Math.max((stackedSumsPos[y] || 0), s.data[j][1]+s.data[j][2]);
lastSerie = s;
}
}
for (j in stackedSumsPos) {
newmax = Math.max(stackedSumsPos[j], newmax);
}
}
}
axis.lastSerie = lastSerie;
axis.max = newmax;
axis.min = newmin;
}
},
extendYRange: function(axis){
if(axis.options.max === null){
var newmax = Number.MIN_VALUE,
newmin = Number.MAX_VALUE,
i, j, s, g,
stackedSumsPos = {},
stackedSumsNeg = {},
lastSerie = null;
for(i = 0; i < this.series.length; ++i){
s = this.series[i];
g = s.gantt;
if (g.show && !s.hide && s.yaxis == axis) {
var datamax = Number.MIN_VALUE, datamin = Number.MAX_VALUE;
for(j=0; j < s.data.length; j++){
datamax = Math.max(datamax,s.data[j][0]);
datamin = Math.min(datamin,s.data[j][0]);
}
if (g.centered) {
newmax = Math.max(datamax + 0.5, newmax);
newmin = Math.min(datamin - 0.5, newmin);
}
else {
newmax = Math.max(datamax + 1, newmax);
newmin = Math.min(datamin, newmin);
}
// For normal horizontal bars
if (g.barWidth + datamax > newmax){
newmax = axis.max + g.barWidth;
}
}
}
axis.lastSerie = lastSerie;
axis.max = newmax;
axis.min = newmin;
axis.tickSize = Flotr.getTickSize(axis.options.noTicks, newmin, newmax, axis.options.tickDecimals);
}
}
});