polardbxengine/storage/ndb/mcc/frontend/dojo/dojox/dgauges/CircularScale.js.uncompress...

277 lines
8.0 KiB
JavaScript

define("dojox/dgauges/CircularScale", ["dojo/_base/declare", "dojox/gfx", "./ScaleBase", "./_circularUtils"], function(declare, gfx, ScaleBase, _circularUtils){
return declare("dojox.dgauges.CircularScale", ScaleBase, {
// summary:
// The circular scale. A scaler must be set to use this class.
// originX: Number
// The origin x-coordinate of the scale in pixels.
originX: 50,
// originY: Number
// The origin y-coordinate of the scale in pixels.
originY: 50,
// radius: Number
// The outer radius in pixels of the scale.
radius: 50,
// startAngle: Number
// The start angle of the scale in degrees.
startAngle: 0,
// endAngle: Number
// The end angle of the scale in degrees.
endAngle: 180,
// orientation: String
// The orientation of the scale. Can be "clockwise" or "cclockwise".
// The default value is "clockwise".
orientation: "clockwise",
constructor: function(){
this.labelPosition = "inside";
this.addInvalidatingProperties(["originX", "originY", "radius", "startAngle", "endAngle", "orientation"]);
},
_getOrientationNum: function(){
// summary:
// Internal method.
// tags:
// private
return this.orientation == "cclockwise" ? -1 : 1;
},
positionForValue: function(/* Number */value){
// summary:
// Transforms a value into an angle using the associated scaler.
// returns: Number
// An angle in degrees.
var totalAngle = _circularUtils.computeTotalAngle(this.startAngle, this.endAngle, this.orientation);
var relativePos = this.scaler.positionForValue(value);
return _circularUtils.modAngle(this.startAngle + this._getOrientationNum() * totalAngle * relativePos, 360);
},
_positionForTickItem: function(tickItem){
// summary:
// Internal method.
// tags:
// private
var totalAngle = _circularUtils.computeTotalAngle(this.startAngle, this.endAngle, this.orientation);
return _circularUtils.modAngle(this.startAngle + this._getOrientationNum() * totalAngle * tickItem.position, 360);
},
valueForPosition: function(/* Number */angle){
// summary:
// Transforms an angle in degrees into a value using the associated scaler.
// returns: Number
// The value represented by angle.
if(!this.positionInRange(angle)){
var min1 = _circularUtils.modAngle(this.startAngle - angle, 360);
var min2 = 360 - min1;
var max1 = _circularUtils.modAngle(this.endAngle - angle, 360);
var max2 = 360 - max1;
var pos;
if(Math.min(min1, min2) < Math.min(max1, max2)){
pos = 0;
}else{
pos = 1;
}
}else{
var relativeAngle = _circularUtils.modAngle(this._getOrientationNum() * (angle - this.startAngle), 360);
var totalAngle = _circularUtils.computeTotalAngle(this.startAngle, this.endAngle, this.orientation);
pos = relativeAngle / totalAngle;
}
return this.scaler.valueForPosition(pos);
},
positionInRange: function(/* Number */value){
// summary:
// Returns true if the value parameter is between the accepted scale positions.
// returns: Boolean
// True if the value parameter is between the accepted scale positions.
if(this.startAngle == this.endAngle){
return true;
}
value = _circularUtils.modAngle(value, 360);
if(this._getOrientationNum() == 1){
if(this.startAngle < this.endAngle){
return value >= this.startAngle && value <= this.endAngle;
}else{
return !(value > this.endAngle && value < this.startAngle);
}
}else{
if(this.startAngle < this.endAngle){
return !(value > this.startAngle && value < this.endAngle);
}else{
return value >= this.endAngle && value <= this.startAngle;
}
}
},
_distance: function(x1, y1, x2, y2){
// summary:
// Internal method.
// tags:
// private
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
},
_layoutLabel: function(label, txt, ox, oy, lrad, angle, labelPlacement){
// summary:
// Internal method.
// tags:
// private
var font = this._getFont();
var box = gfx._base._getTextBox(txt, {
font: gfx.makeFontString(gfx.makeParameters(gfx.defaultFont, font))
});
var tw = box.w;
var fz = font.size;
var th = gfx.normalizedLength(fz);
var tfx = ox + Math.cos(angle) * lrad - tw / 2;
var tfy = oy - Math.sin(angle) * lrad - th / 2;
var side;
var intersections = [];
// Intersection with top segment
side = tfx;
var ipx = side;
var ipy = -Math.tan(angle) * side + oy + Math.tan(angle) * ox;
// Verify if intersection is on segment
if(ipy >= tfy && ipy <= tfy + th){
intersections.push({
x: ipx,
y: ipy
});
}
// Intersection with bottom segment
side = tfx + tw;
ipx = side;
ipy = -Math.tan(angle) * side + oy + Math.tan(angle) * ox;
// Verify if intersection is on segment
if(ipy >= tfy && ipy <= tfy + th){
intersections.push({
x: ipx,
y: ipy
});
}
// Intersection with left segment
side = tfy;
ipx = -1 / Math.tan(angle) * side + ox + 1 / Math.tan(angle) * oy;
ipy = side;
// Verify if intersection is on segment
if(ipx >= tfx && ipx <= tfx + tw){
intersections.push({
x: ipx,
y: ipy
});
}
// Intersection with right segment
side = tfy + th;
ipx = -1 / Math.tan(angle) * side + ox + 1 / Math.tan(angle) * oy;
ipy = side;
// Verify if intersection is on segment
if(ipx >= tfx && ipx <= tfx + tw){
intersections.push({
x: ipx,
y: ipy
});
}
var dif;
if(labelPlacement == "inside"){
for(var it = 0; it < intersections.length; it++){
var ip = intersections[it];
dif = this._distance(ip.x, ip.y, ox, oy) - lrad;
if(dif >= 0){
// Place reference intersection point on reference circle
tfx = ox + Math.cos(angle) * (lrad - dif) - tw / 2;
tfy = oy - Math.sin(angle) * (lrad - dif) - th / 2;
break;
}
}
}else{// "outside" placement
for(it = 0; it < intersections.length; it++){
ip = intersections[it];
dif = this._distance(ip.x, ip.y, ox, oy) - lrad;
if(dif <= 0){
// Place reference intersection point on reference circle
tfx = ox + Math.cos(angle) * (lrad - dif) - tw / 2;
tfy = oy - Math.sin(angle) * (lrad - dif) - th / 2;
break;
}
}
}
if(label){
label.setTransform([{
dx: tfx + tw / 2,
dy: tfy + th
}]);
}
},
refreshRendering: function(){
this.inherited(arguments);
if(!this._gfxGroup || !this.scaler){
return;
}
// Normalize angles
this.startAngle = _circularUtils.modAngle(this.startAngle, 360);
this.endAngle = _circularUtils.modAngle(this.endAngle, 360);
this._ticksGroup.clear();
var renderer;
var label;
var labelText;
// Layout ticks
var allTicks = this.scaler.computeTicks();
var tickBB;
for(var i = 0; i < allTicks.length; i++){
var tickItem = allTicks[i];
renderer = this.tickShapeFunc(this._ticksGroup, this, tickItem);
tickBB = this._gauge._computeBoundingBox(renderer);
var a;
if(tickItem.position){
a = this._positionForTickItem(tickItem);
}else{
a = this.positionForValue(tickItem.value);
}
if(renderer){
renderer.setTransform([{
dx: this.originX,
dy: this.originY
}, gfx.matrix.rotateg(a), {
dx: this.radius - tickBB.width - 2 * tickBB.x,
dy: 0
}]);
}
labelText = this.tickLabelFunc(tickItem);
if(labelText){
label = this._ticksGroup.createText({
x: 0,
y: 0,
text: labelText,
align: "middle"
}).setFont(this._getFont()).setFill(this._getFont().color ? this._getFont().color : "black");
var rad = this.radius;
if(this.labelPosition == "inside"){
rad -= (tickBB.width + this.labelGap);
}else{
rad += this.labelGap;
}
this._layoutLabel(label, labelText, this.originX, this.originY, rad, _circularUtils.toRadians(360 - a), this.labelPosition);
}
}
for(var key in this._indicatorsIndex){
this._indicatorsRenderers[key] = this._indicatorsIndex[key].invalidateRendering();
}
}
});
});