cacert-testmgr/external/ZendFramework-1.9.5/externals/dojo/dojox/charting/axis2d/Default.js

341 lines
12 KiB
JavaScript
Raw Permalink Normal View History

dojo.provide("dojox.charting.axis2d.Default");
dojo.require("dojox.charting.scaler.linear");
dojo.require("dojox.charting.axis2d.common");
dojo.require("dojox.charting.axis2d.Base");
dojo.require("dojo.colors");
dojo.require("dojo.string");
dojo.require("dojox.gfx");
dojo.require("dojox.lang.functional");
dojo.require("dojox.lang.utils");
(function(){
var dc = dojox.charting,
df = dojox.lang.functional,
du = dojox.lang.utils,
g = dojox.gfx,
lin = dc.scaler.linear,
labelGap = 4; // in pixels
dojo.declare("dojox.charting.axis2d.Default", dojox.charting.axis2d.Base, {
defaultParams: {
vertical: false, // true for vertical axis
fixUpper: "none", // align the upper on ticks: "major", "minor", "micro", "none"
fixLower: "none", // align the lower on ticks: "major", "minor", "micro", "none"
natural: false, // all tick marks should be made on natural numbers
leftBottom: true, // position of the axis, used with "vertical"
includeZero: false, // 0 should be included
fixed: true, // all labels are fixed numbers
majorLabels: true, // draw major labels
minorTicks: true, // draw minor ticks
minorLabels: true, // draw minor labels
microTicks: false, // draw micro ticks
htmlLabels: true // use HTML to draw labels
},
optionalParams: {
min: 0, // minimal value on this axis
max: 1, // maximal value on this axis
from: 0, // visible from this value
to: 1, // visible to this value
majorTickStep: 4, // major tick step
minorTickStep: 2, // minor tick step
microTickStep: 1, // micro tick step
labels: [], // array of labels for major ticks
// with corresponding numeric values
// ordered by values
labelFunc: null, // function to compute label values
maxLabelSize: 0, // size in px. For use with labelFunc
// TODO: add support for minRange!
// minRange: 1, // smallest distance from min allowed on the axis
// theme components
stroke: {}, // stroke for an axis
majorTick: {}, // stroke + length for a tick
minorTick: {}, // stroke + length for a tick
microTick: {}, // stroke + length for a tick
font: "", // font for labels
fontColor: "" // color for labels as a string
},
constructor: function(chart, kwArgs){
this.opt = dojo.delegate(this.defaultParams, kwArgs);
// du.updateWithObject(this.opt, kwArgs);
du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
},
dependOnData: function(){
return !("min" in this.opt) || !("max" in this.opt);
},
clear: function(){
delete this.scaler;
delete this.ticks;
this.dirty = true;
return this;
},
initialized: function(){
return "scaler" in this && !(this.dirty && this.dependOnData());
},
setWindow: function(scale, offset){
this.scale = scale;
this.offset = offset;
return this.clear();
},
getWindowScale: function(){
return "scale" in this ? this.scale : 1;
},
getWindowOffset: function(){
return "offset" in this ? this.offset : 0;
},
calculate: function(min, max, span, labels){
if(this.initialized()){ return this; }
this.labels = "labels" in this.opt ? this.opt.labels : labels;
this.scaler = lin.buildScaler(min, max, span, this.opt);
if("scale" in this){
// calculate new range
this.opt.from = this.scaler.bounds.lower + this.offset;
this.opt.to = (this.scaler.bounds.upper - this.scaler.bounds.lower) / this.scale + this.opt.from;
// make sure that bounds are correct
if(!isFinite(this.opt.from) || isNaN(this.opt.from) || !isFinite(this.opt.to) || isNaN(this.opt.to) ||
this.opt.to - this.opt.from >= this.scaler.bounds.upper - this.scaler.bounds.lower){
// any error --- remove from/to bounds
delete this.opt.from;
delete this.opt.to;
delete this.scale;
delete this.offset;
}else{
// shift the window, if we are out of bounds
if(this.opt.from < this.scaler.bounds.lower){
this.opt.to += this.scaler.bounds.lower - this.opt.from;
this.opt.from = this.scaler.bounds.lower;
}else if(this.opt.to > this.scaler.bounds.upper){
this.opt.from += this.scaler.bounds.upper - this.opt.to;
this.opt.to = this.scaler.bounds.upper;
}
// update the offset
this.offset = this.opt.from - this.scaler.bounds.lower;
}
// re-calculate the scaler
this.scaler = lin.buildScaler(min, max, span, this.opt);
// cleanup
if(this.scale == 1 && this.offset == 0){
delete this.scale;
delete this.offset;
}
}
var minMinorStep = 0, ta = this.chart.theme.axis,
taFont = "font" in this.opt ? this.opt.font : ta.font,
size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0;
if(this.vertical){
if(size){
minMinorStep = size + labelGap;
}
}else{
if(size){
var labelWidth, i;
if(this.opt.labelFunc && this.opt.maxLabelSize){
labelWidth = this.opt.maxLabelSize;
}else if(this.labels){
labelWidth = df.foldl(df.map(this.labels, function(label){
return dojox.gfx._base._getTextBox(label.text, {font: taFont}).w;
}), "Math.max(a, b)", 0);
}else{
var labelLength = Math.ceil(Math.log(Math.max(Math.abs(this.scaler.bounds.from),
Math.abs(this.scaler.bounds.to))) / Math.LN10),
t = [];
if(this.scaler.bounds.from < 0 || this.scaler.bounds.to < 0){ t.push("-"); }
t.push(dojo.string.rep("9", labelLength));
var precision = Math.floor(Math.log(this.scaler.bounds.to - this.scaler.bounds.from) / Math.LN10);
if(precision > 0){
t.push(".");
for(i = 0; i < precision; ++i){ t.push("9"); }
}
labelWidth = dojox.gfx._base._getTextBox(t.join(""), {font: taFont}).w;
}
minMinorStep = labelWidth + labelGap;
}
}
this.scaler.minMinorStep = minMinorStep;
this.ticks = lin.buildTicks(this.scaler, this.opt);
return this;
},
getScaler: function(){
return this.scaler;
},
getTicks: function(){
return this.ticks;
},
getOffsets: function(){
var offsets = {l: 0, r: 0, t: 0, b: 0}, labelWidth, a, b, c, d,
gtb = dojox.gfx._base._getTextBox, gl = dc.scaler.common.getNumericLabel,
offset = 0, ta = this.chart.theme.axis,
taFont = "font" in this.opt ? this.opt.font : ta.font,
taMajorTick = "majorTick" in this.opt ? this.opt.majorTick : ta.majorTick,
taMinorTick = "minorTick" in this.opt ? this.opt.minorTick : ta.minorTick,
size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0,
s = this.scaler;
if(!s){
return offsets;
}
if(this.vertical){
if(size){
if(this.opt.labelFunc && this.opt.maxLabelSize){
labelWidth = this.opt.maxLabelSize;
}else if(this.labels){
labelWidth = df.foldl(df.map(this.labels, function(label){
return dojox.gfx._base._getTextBox(label.text, {font: taFont}).w;
}), "Math.max(a, b)", 0);
}else{
a = gtb(gl(s.major.start, s.major.prec, this.opt), {font: taFont}).w;
b = gtb(gl(s.major.start + s.major.count * s.major.tick, s.major.prec, this.opt), {font: taFont}).w;
c = gtb(gl(s.minor.start, s.minor.prec, this.opt), {font: taFont}).w;
d = gtb(gl(s.minor.start + s.minor.count * s.minor.tick, s.minor.prec, this.opt), {font: taFont}).w;
labelWidth = Math.max(a, b, c, d);
}
offset = labelWidth + labelGap;
}
offset += labelGap + Math.max(taMajorTick.length, taMinorTick.length);
offsets[this.opt.leftBottom ? "l" : "r"] = offset;
offsets.t = offsets.b = size / 2;
}else{
if(size){
offset = size + labelGap;
}
offset += labelGap + Math.max(taMajorTick.length, taMinorTick.length);
offsets[this.opt.leftBottom ? "b" : "t"] = offset;
if(size){
if(this.opt.labelFunc && this.opt.maxLabelSize){
labelWidth = this.opt.maxLabelSize;
}else if(this.labels){
labelWidth = df.foldl(df.map(this.labels, function(label){
return dojox.gfx._base._getTextBox(label.text, {font: taFont}).w;
}), "Math.max(a, b)", 0);
}else{
a = gtb(gl(s.major.start, s.major.prec, this.opt), {font: taFont}).w;
b = gtb(gl(s.major.start + s.major.count * s.major.tick, s.major.prec, this.opt), {font: taFont}).w;
c = gtb(gl(s.minor.start, s.minor.prec, this.opt), {font: taFont}).w;
d = gtb(gl(s.minor.start + s.minor.count * s.minor.tick, s.minor.prec, this.opt), {font: taFont}).w;
labelWidth = Math.max(a, b, c, d);
}
offsets.l = offsets.r = labelWidth / 2;
}
}
return offsets;
},
render: function(dim, offsets){
if(!this.dirty){ return this; }
// prepare variable
var start, stop, axisVector, tickVector, labelOffset, labelAlign,
ta = this.chart.theme.axis,
taStroke = "stroke" in this.opt ? this.opt.stroke : ta.stroke,
taMajorTick = "majorTick" in this.opt ? this.opt.majorTick : ta.majorTick,
taMinorTick = "minorTick" in this.opt ? this.opt.minorTick : ta.minorTick,
taMicroTick = "microTick" in this.opt ? this.opt.microTick : ta.minorTick,
taFont = "font" in this.opt ? this.opt.font : ta.font,
taFontColor = "fontColor" in this.opt ? this.opt.fontColor : ta.fontColor,
tickSize = Math.max(taMajorTick.length, taMinorTick.length),
size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0;
if(this.vertical){
start = {y: dim.height - offsets.b};
stop = {y: offsets.t};
axisVector = {x: 0, y: -1};
if(this.opt.leftBottom){
start.x = stop.x = offsets.l;
tickVector = {x: -1, y: 0};
labelAlign = "end";
}else{
start.x = stop.x = dim.width - offsets.r;
tickVector = {x: 1, y: 0};
labelAlign = "start";
}
labelOffset = {x: tickVector.x * (tickSize + labelGap), y: size * 0.4};
}else{
start = {x: offsets.l};
stop = {x: dim.width - offsets.r};
axisVector = {x: 1, y: 0};
labelAlign = "middle";
if(this.opt.leftBottom){
start.y = stop.y = dim.height - offsets.b;
tickVector = {x: 0, y: 1};
labelOffset = {y: tickSize + labelGap + size};
}else{
start.y = stop.y = offsets.t;
tickVector = {x: 0, y: -1};
labelOffset = {y: -tickSize - labelGap};
}
labelOffset.x = 0;
}
// render shapes
this.cleanGroup();
try{
var s = this.group, c = this.scaler, t = this.ticks, canLabel,
f = lin.getTransformerFromModel(this.scaler),
forceHtmlLabels = dojox.gfx.renderer == "canvas",
labelType = forceHtmlLabels || this.opt.htmlLabels && !dojo.isIE && !dojo.isOpera ? "html" : "gfx",
dx = tickVector.x * taMajorTick.length,
dy = tickVector.y * taMajorTick.length;
s.createLine({x1: start.x, y1: start.y, x2: stop.x, y2: stop.y}).setStroke(taStroke);
dojo.forEach(t.major, function(tick){
var offset = f(tick.value), elem,
x = start.x + axisVector.x * offset,
y = start.y + axisVector.y * offset;
s.createLine({
x1: x, y1: y,
x2: x + dx,
y2: y + dy
}).setStroke(taMajorTick);
if(tick.label){
elem = dc.axis2d.common.createText[labelType]
(this.chart, s, x + labelOffset.x, y + labelOffset.y, labelAlign,
tick.label, taFont, taFontColor);
if(labelType == "html"){ this.htmlElements.push(elem); }
}
}, this);
dx = tickVector.x * taMinorTick.length;
dy = tickVector.y * taMinorTick.length;
canLabel = c.minMinorStep <= c.minor.tick * c.bounds.scale;
dojo.forEach(t.minor, function(tick){
var offset = f(tick.value), elem,
x = start.x + axisVector.x * offset,
y = start.y + axisVector.y * offset;
s.createLine({
x1: x, y1: y,
x2: x + dx,
y2: y + dy
}).setStroke(taMinorTick);
if(canLabel && tick.label){
elem = dc.axis2d.common.createText[labelType]
(this.chart, s, x + labelOffset.x, y + labelOffset.y, labelAlign,
tick.label, taFont, taFontColor);
if(labelType == "html"){ this.htmlElements.push(elem); }
}
}, this);
dx = tickVector.x * taMicroTick.length;
dy = tickVector.y * taMicroTick.length;
dojo.forEach(t.micro, function(tick){
var offset = f(tick.value), elem,
x = start.x + axisVector.x * offset,
y = start.y + axisVector.y * offset;
s.createLine({
x1: x, y1: y,
x2: x + dx,
y2: y + dy
}).setStroke(taMicroTick);
}, this);
}catch(e){
// squelch
}
this.dirty = false;
return this;
}
});
})();