123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- /*
- Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
- Available via Academic Free License >= 2.1 OR the modified BSD license.
- see: http://dojotoolkit.org/license for details
- */
- if(!dojo._hasResource["dojox.charting.Element"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
- dojo._hasResource["dojox.charting.Element"] = true;
- dojo.provide("dojox.charting.Element");
- dojo.require("dojox.gfx");
- dojo.declare("dojox.charting.Element", null, {
- // summary:
- // A base class that is used to build other elements of a chart, such as
- // a series.
- // chart: dojox.charting.Chart2D
- // The parent chart for this element.
- // group: dojox.gfx.Group
- // The visual GFX group representing this element.
- // htmlElement: Array
- // Any DOMNodes used as a part of this element (such as HTML-based labels).
- // dirty: Boolean
- // A flag indicating whether or not this element needs to be rendered.
- chart: null,
- group: null,
- htmlElements: null,
- dirty: true,
- constructor: function(chart){
- // summary:
- // Creates a new charting element.
- // chart: dojox.charting.Chart2D
- // The chart that this element belongs to.
- this.chart = chart;
- this.group = null;
- this.htmlElements = [];
- this.dirty = true;
- this.trailingSymbol = "...";
- this._events = [];
- },
- createGroup: function(creator){
- // summary:
- // Convenience function to create a new dojox.gfx.Group.
- // creator: dojox.gfx.Surface?
- // An optional surface in which to create this group.
- // returns: dojox.charting.Element
- // A reference to this object for functional chaining.
- if(!creator){ creator = this.chart.surface; }
- if(!this.group){
- this.group = creator.createGroup();
- }
- return this; // dojox.charting.Element
- },
- purgeGroup: function(){
- // summary:
- // Clear any elements out of our group, and destroy the group.
- // returns: dojox.charting.Element
- // A reference to this object for functional chaining.
- this.destroyHtmlElements();
- if(this.group){
- this.group.clear();
- this.group.removeShape();
- this.group = null;
- }
- this.dirty = true;
- if(this._events.length){
- dojo.forEach(this._events, function(item){
- item.shape.disconnect(item.handle);
- });
- this._events = [];
- }
- return this; // dojox.charting.Element
- },
- cleanGroup: function(creator){
- // summary:
- // Clean any elements (HTML or GFX-based) out of our group, and create a new one.
- // creator: dojox.gfx.Surface?
- // An optional surface to work with.
- // returns: dojox.charting.Element
- // A reference to this object for functional chaining.
- this.destroyHtmlElements();
- if(!creator){ creator = this.chart.surface; }
- if(this.group){
- this.group.clear();
- }else{
- this.group = creator.createGroup();
- }
- this.dirty = true;
- return this; // dojox.charting.Element
- },
- destroyHtmlElements: function(){
- // summary:
- // Destroy any DOMNodes that may have been created as a part of this element.
- if(this.htmlElements.length){
- dojo.forEach(this.htmlElements, dojo.destroy);
- this.htmlElements = [];
- }
- },
- destroy: function(){
- // summary:
- // API addition to conform to the rest of the Dojo Toolkit's standard.
- this.purgeGroup();
- },
- //text utilities
- getTextWidth: function(s, font){
- return dojox.gfx._base._getTextBox(s, {font: font}).w || 0;
- },
- getTextWithLimitLength: function(s, font, limitWidth, truncated){
- // summary:
- // Get the truncated string based on the limited width in px(dichotomy algorithm)
- // s: String?
- // candidate text.
- // font: String?
- // text's font style.
- // limitWidth: Number?
- // text limited width in px.
- // truncated: Boolean?
- // whether the input text(s) has already been truncated.
- // returns: Object
- // {
- // text: processed text, maybe truncated or not
- // truncated: whether text has been truncated
- // }
- if (!s || s.length <= 0) {
- return {
- text: "",
- truncated: truncated || false
- };
- }
- if(!limitWidth || limitWidth <= 0){
- return {
- text: s,
- truncated: truncated || false
- };
- }
- var delta = 2,
- //golden section for dichotomy algorithm
- trucPercentage = 0.618,
- minStr = s.substring(0,1) + this.trailingSymbol,
- minWidth = this.getTextWidth(minStr, font);
- if (limitWidth <= minWidth) {
- return {
- text: minStr,
- truncated: true
- };
- }
- var width = this.getTextWidth(s, font);
- if(width <= limitWidth){
- return {
- text: s,
- truncated: truncated || false
- };
- }else{
- var begin = 0,
- end = s.length;
- while(begin < end){
- if(end - begin <= delta ){
- while (this.getTextWidth(s.substring(0, begin) + this.trailingSymbol, font) > limitWidth) {
- begin -= 1;
- }
- return {
- text: (s.substring(0,begin) + this.trailingSymbol),
- truncated: true
- };
- }
- var index = begin + Math.round((end - begin) * trucPercentage),
- widthIntercepted = this.getTextWidth(s.substring(0, index), font);
- if(widthIntercepted < limitWidth){
- begin = index;
- end = end;
- }else{
- begin = begin;
- end = index;
- }
- }
- }
- },
- getTextWithLimitCharCount: function(s, font, wcLimit, truncated){
- // summary:
- // Get the truncated string based on the limited character count(dichotomy algorithm)
- // s: String?
- // candidate text.
- // font: String?
- // text's font style.
- // wcLimit: Number?
- // text limited character count.
- // truncated: Boolean?
- // whether the input text(s) has already been truncated.
- // returns: Object
- // {
- // text: processed text, maybe truncated or not
- // truncated: whether text has been truncated
- // }
- if (!s || s.length <= 0) {
- return {
- text: "",
- truncated: truncated || false
- };
- }
- if(!wcLimit || wcLimit <= 0 || s.length <= wcLimit){
- return {
- text: s,
- truncated: truncated || false
- };
- }
- return {
- text: s.substring(0, wcLimit) + this.trailingSymbol,
- truncated: true
- };
- },
- // fill utilities
- _plotFill: function(fill, dim, offsets){
- // process a plot-wide fill
- if(!fill || !fill.type || !fill.space){
- return fill;
- }
- var space = fill.space;
- switch(fill.type){
- case "linear":
- if(space === "plot" || space === "shapeX" || space === "shapeY"){
- // clone a fill so we can modify properly directly
- fill = dojox.gfx.makeParameters(dojox.gfx.defaultLinearGradient, fill);
- fill.space = space;
- // process dimensions
- if(space === "plot" || space === "shapeX"){
- // process Y
- var span = dim.height - offsets.t - offsets.b;
- fill.y1 = offsets.t + span * fill.y1 / 100;
- fill.y2 = offsets.t + span * fill.y2 / 100;
- }
- if(space === "plot" || space === "shapeY"){
- // process X
- var span = dim.width - offsets.l - offsets.r;
- fill.x1 = offsets.l + span * fill.x1 / 100;
- fill.x2 = offsets.l + span * fill.x2 / 100;
- }
- }
- break;
- case "radial":
- if(space === "plot"){
- // this one is used exclusively for scatter charts
- // clone a fill so we can modify properly directly
- fill = dojox.gfx.makeParameters(dojox.gfx.defaultRadialGradient, fill);
- fill.space = space;
- // process both dimensions
- var spanX = dim.width - offsets.l - offsets.r,
- spanY = dim.height - offsets.t - offsets.b;
- fill.cx = offsets.l + spanX * fill.cx / 100;
- fill.cy = offsets.t + spanY * fill.cy / 100;
- fill.r = fill.r * Math.sqrt(spanX * spanX + spanY * spanY) / 200;
- }
- break;
- case "pattern":
- if(space === "plot" || space === "shapeX" || space === "shapeY"){
- // clone a fill so we can modify properly directly
- fill = dojox.gfx.makeParameters(dojox.gfx.defaultPattern, fill);
- fill.space = space;
- // process dimensions
- if(space === "plot" || space === "shapeX"){
- // process Y
- var span = dim.height - offsets.t - offsets.b;
- fill.y = offsets.t + span * fill.y / 100;
- fill.height = span * fill.height / 100;
- }
- if(space === "plot" || space === "shapeY"){
- // process X
- var span = dim.width - offsets.l - offsets.r;
- fill.x = offsets.l + span * fill.x / 100;
- fill.width = span * fill.width / 100;
- }
- }
- break;
- }
- return fill;
- },
- _shapeFill: function(fill, bbox){
- // process shape-specific fill
- if(!fill || !fill.space){
- return fill;
- }
- var space = fill.space;
- switch(fill.type){
- case "linear":
- if(space === "shape" || space === "shapeX" || space === "shapeY"){
- // clone a fill so we can modify properly directly
- fill = dojox.gfx.makeParameters(dojox.gfx.defaultLinearGradient, fill);
- fill.space = space;
- // process dimensions
- if(space === "shape" || space === "shapeX"){
- // process X
- var span = bbox.width;
- fill.x1 = bbox.x + span * fill.x1 / 100;
- fill.x2 = bbox.x + span * fill.x2 / 100;
- }
- if(space === "shape" || space === "shapeY"){
- // process Y
- var span = bbox.height;
- fill.y1 = bbox.y + span * fill.y1 / 100;
- fill.y2 = bbox.y + span * fill.y2 / 100;
- }
- }
- break;
- case "radial":
- if(space === "shape"){
- // this one is used exclusively for bubble charts and pie charts
- // clone a fill so we can modify properly directly
- fill = dojox.gfx.makeParameters(dojox.gfx.defaultRadialGradient, fill);
- fill.space = space;
- // process both dimensions
- fill.cx = bbox.x + bbox.width / 2;
- fill.cy = bbox.y + bbox.height / 2;
- fill.r = fill.r * bbox.width / 200;
- }
- break;
- case "pattern":
- if(space === "shape" || space === "shapeX" || space === "shapeY"){
- // clone a fill so we can modify properly directly
- fill = dojox.gfx.makeParameters(dojox.gfx.defaultPattern, fill);
- fill.space = space;
- // process dimensions
- if(space === "shape" || space === "shapeX"){
- // process X
- var span = bbox.width;
- fill.x = bbox.x + span * fill.x / 100;
- fill.width = span * fill.width / 100;
- }
- if(space === "shape" || space === "shapeY"){
- // process Y
- var span = bbox.height;
- fill.y = bbox.y + span * fill.y / 100;
- fill.height = span * fill.height / 100;
- }
- }
- break;
- }
- return fill;
- },
- _pseudoRadialFill: function(fill, center, radius, start, end){
- // process pseudo-radial fills
- if(!fill || fill.type !== "radial" || fill.space !== "shape"){
- return fill;
- }
- // clone and normalize fill
- var space = fill.space;
- fill = dojox.gfx.makeParameters(dojox.gfx.defaultRadialGradient, fill);
- fill.space = space;
- if(arguments.length < 4){
- // process both dimensions
- fill.cx = center.x;
- fill.cy = center.y;
- fill.r = fill.r * radius / 100;
- return fill;
- }
- // convert to a linear gradient
- var angle = arguments.length < 5 ? start : (end + start) / 2;
- return {
- type: "linear",
- x1: center.x,
- y1: center.y,
- x2: center.x + fill.r * radius * Math.cos(angle) / 100,
- y2: center.y + fill.r * radius * Math.sin(angle) / 100,
- colors: fill.colors
- };
- return fill;
- }
- });
- }
|