source: Dev/branches/rest-dojo-ui/client/dojox/charting/axis2d/Default.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 29.0 KB
Line 
1define(["dojo/_base/lang", "dojo/_base/array","dojo/_base/sniff", "dojo/_base/declare",
2        "dojo/_base/connect", "dojo/_base/html", "dojo/dom-geometry", "./Invisible",
3        "../scaler/common", "../scaler/linear", "./common", "dojox/gfx", "dojox/lang/utils"],
4        function(lang, arr, has, declare, connect, html, domGeom, Invisible, scommon,
5                        lin, acommon, g, du){
6
7        /*=====
8                dojox.charting.axis2d.__AxisCtorArgs = function(
9                        vertical, fixUpper, fixLower, natural, leftBottom,
10                        includeZero, fixed, majorLabels, minorTicks, minorLabels, microTicks, htmlLabels,
11                        min, max, from, to, majorTickStep, minorTickStep, microTickStep,
12                        labels, labelFunc, maxLabelSize,
13                        stroke, majorTick, minorTick, microTick, tick,
14                        font, fontColor
15                ){
16                //      summary:
17                //              Optional arguments used in the definition of an axis.
18                //
19                //      vertical: Boolean?
20                //              A flag that says whether an axis is vertical (i.e. y axis) or horizontal. Default is false (horizontal).
21                //      fixUpper: String?
22                //              Align the greatest value on the axis with the specified tick level. Options are "major", "minor", "micro", or "none".  Defaults to "none".
23                //      fixLower: String?
24                //              Align the smallest value on the axis with the specified tick level. Options are "major", "minor", "micro", or "none".  Defaults to "none".
25                //      natural: Boolean?
26                //              Ensure tick marks are made on "natural" numbers. Defaults to false.
27                //      leftBottom: Boolean?
28                //              The position of a vertical axis; if true, will be placed against the left-bottom corner of the chart.  Defaults to true.
29                //      includeZero: Boolean?
30                //              Include 0 on the axis rendering.  Default is false.
31                //      fixed: Boolean?
32                //              Force all axis labels to be fixed numbers.  Default is true.
33                //      majorLabels: Boolean?
34                //              Flag to draw all labels at major ticks. Default is true.
35                //      minorTicks: Boolean?
36                //              Flag to draw minor ticks on an axis.  Default is true.
37                //      minorLabels: Boolean?
38                //              Flag to draw labels on minor ticks. Default is true.
39                //      microTicks: Boolean?
40                //              Flag to draw micro ticks on an axis. Default is false.
41                //      htmlLabels: Boolean?
42                //              Flag to use HTML (as opposed to the native vector graphics engine) to draw labels. Default is true.
43                //      min: Number?
44                //              The smallest value on an axis. Default is 0.
45                //      max: Number?
46                //              The largest value on an axis. Default is 1.
47                //      from: Number?
48                //              Force the chart to render data visible from this value. Default is 0.
49                //      to: Number?
50                //              Force the chart to render data visible to this value. Default is 1.
51                //      majorTickStep: Number?
52                //              The amount to skip before a major tick is drawn.  Default is 4.
53                //      minorTickStep: Number?
54                //              The amount to skip before a minor tick is drawn. Default is 2.
55                //      microTickStep: Number?
56                //              The amount to skip before a micro tick is drawn. Default is 1.
57                //      labels: Object[]?
58                //              An array of labels for major ticks, with corresponding numeric values, ordered by value.
59                //      labelFunc: Function?
60                //              An optional function used to compute label values.
61                //      maxLabelSize: Number?
62                //              The maximum size, in pixels, for a label.  To be used with the optional label function.
63                //      stroke: dojox.gfx.Stroke?
64                //              An optional stroke to be used for drawing an axis.
65                //      majorTick: Object?
66                //              An object containing a dojox.gfx.Stroke, and a length (number) for a major tick.
67                //      minorTick: Object?
68                //              An object containing a dojox.gfx.Stroke, and a length (number) for a minor tick.
69                //      microTick: Object?
70                //              An object containing a dojox.gfx.Stroke, and a length (number) for a micro tick.
71                //      tick: Object?
72                //              An object containing a dojox.gfx.Stroke, and a length (number) for a tick.
73                //      font: String?
74                //              An optional font definition (as used in the CSS font property) for labels.
75                //      fontColor: String|dojo.Color?
76                //              An optional color to be used in drawing labels.
77                //      enableCache: Boolean?
78                //              Whether the ticks and labels are cached from one rendering to another. This improves the rendering performance of
79                //              successive rendering but penalize the first rendering. For labels it is only working with gfx labels
80                //              not html ones.  Default false.
81       
82                this.vertical = vertical;
83                this.fixUpper = fixUpper;
84                this.fixLower = fixLower;
85                this.natural = natural;
86                this.leftBottom = leftBottom;
87                this.includeZero = includeZero;
88                this.fixed = fixed;
89                this.majorLabels = majorLabels;
90                this.minorTicks = minorTicks;
91                this.minorLabels = minorLabels;
92                this.microTicks = microTicks;
93                this.htmlLabels = htmlLabels;
94                this.min = min;
95                this.max = max;
96                this.from = from;
97                this.to = to;
98                this.majorTickStep = majorTickStep;
99                this.minorTickStep = minorTickStep;
100                this.microTickStep = microTickStep;
101                this.labels = labels;
102                this.labelFunc = labelFunc;
103                this.maxLabelSize = maxLabelSize;
104                this.stroke = stroke;
105                this.majorTick = majorTick;
106                this.minorTick = minorTick;
107                this.microTick = microTick;
108                this.tick = tick;
109                this.font = font;
110                this.fontColor = fontColor;
111                this.enableCache = enableCache;
112        }
113        var Invisible = dojox.charting.axis2d.Invisible
114        =====*/
115
116        var labelGap = 4,                       // in pixels
117                centerAnchorLimit = 45; // in degrees
118
119        return declare("dojox.charting.axis2d.Default", Invisible, {
120                //      summary:
121                //              The default axis object used in dojox.charting.  See dojox.charting.Chart.addAxis for details.
122                //
123                //      defaultParams: Object
124                //              The default parameters used to define any axis.
125                //      optionalParams: Object
126                //              Any optional parameters needed to define an axis.
127
128                /*
129                //      TODO: the documentation tools need these to be pre-defined in order to pick them up
130                //      correctly, but the code here is partially predicated on whether or not the properties
131                //      actually exist.  For now, we will leave these undocumented but in the code for later. -- TRT
132
133                //      opt: Object
134                //              The actual options used to define this axis, created at initialization.
135                //      scalar: Object
136                //              The calculated helper object to tell charts how to draw an axis and any data.
137                //      ticks: Object
138                //              The calculated tick object that helps a chart draw the scaling on an axis.
139                //      dirty: Boolean
140                //              The state of the axis (whether it needs to be redrawn or not)
141                //      scale: Number
142                //              The current scale of the axis.
143                //      offset: Number
144                //              The current offset of the axis.
145
146                opt: null,
147                scalar: null,
148                ticks: null,
149                dirty: true,
150                scale: 1,
151                offset: 0,
152                */
153                defaultParams: {
154                        vertical:    false,             // true for vertical axis
155                        fixUpper:    "none",    // align the upper on ticks: "major", "minor", "micro", "none"
156                        fixLower:    "none",    // align the lower on ticks: "major", "minor", "micro", "none"
157                        natural:     false,             // all tick marks should be made on natural numbers
158                        leftBottom:  true,              // position of the axis, used with "vertical"
159                        includeZero: false,             // 0 should be included
160                        fixed:       true,              // all labels are fixed numbers
161                        majorLabels: true,              // draw major labels
162                        minorTicks:  true,              // draw minor ticks
163                        minorLabels: true,              // draw minor labels
164                        microTicks:  false,             // draw micro ticks
165                        rotation:    0,                 // label rotation angle in degrees
166                        htmlLabels:  true,              // use HTML to draw labels
167                        enableCache: false              // whether we cache or not
168                },
169                optionalParams: {
170                        min:                    0,      // minimal value on this axis
171                        max:                    1,      // maximal value on this axis
172                        from:                   0,      // visible from this value
173                        to:                             1,      // visible to this value
174                        majorTickStep:  4,      // major tick step
175                        minorTickStep:  2,      // minor tick step
176                        microTickStep:  1,      // micro tick step
177                        labels:                 [],     // array of labels for major ticks
178                                                                // with corresponding numeric values
179                                                                // ordered by values
180                        labelFunc:              null, // function to compute label values
181                        maxLabelSize:   0,      // size in px. For use with labelFunc
182                        maxLabelCharCount:      0,      // size in word count.
183                        trailingSymbol: null,
184
185                        // TODO: add support for minRange!
186                        // minRange:            1,      // smallest distance from min allowed on the axis
187
188                        // theme components
189                        stroke:                 {},     // stroke for an axis
190                        majorTick:              {},     // stroke + length for a tick
191                        minorTick:              {},     // stroke + length for a tick
192                        microTick:              {},     // stroke + length for a tick
193                        tick:           {},     // stroke + length for a tick
194                        font:                   "",     // font for labels
195                        fontColor:              "",     // color for labels as a string
196                        title:                          "",     // axis title
197                        titleGap:                       0,              // gap between axis title and axis label
198                        titleFont:                      "",             // axis title font
199                        titleFontColor:         "",             // axis title font color
200                        titleOrientation:       ""              // "axis" means the title facing the axis, "away" means facing away
201                },
202
203                constructor: function(chart, kwArgs){
204                        //      summary:
205                        //              The constructor for an axis.
206                        //      chart: dojox.charting.Chart
207                        //              The chart the axis belongs to.
208                        //      kwArgs: dojox.charting.axis2d.__AxisCtorArgs?
209                        //              Any optional keyword arguments to be used to define this axis.
210                        this.opt = lang.clone(this.defaultParams);
211            du.updateWithObject(this.opt, kwArgs);
212                        du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
213                        if(this.opt.enableCache){
214                                this._textFreePool = [];
215                                this._lineFreePool = [];
216                                this._textUsePool = [];
217                                this._lineUsePool = [];
218                        }
219                },
220                getOffsets: function(){
221                        //      summary:
222                        //              Get the physical offset values for this axis (used in drawing data series).
223                        //      returns: Object
224                        //              The calculated offsets in the form of { l, r, t, b } (left, right, top, bottom).
225                        var s = this.scaler, offsets = { l: 0, r: 0, t: 0, b: 0 };
226                        if(!s){
227                                return offsets;
228                        }
229                        var o = this.opt, labelWidth = 0, a, b, c, d,
230                                gl = scommon.getNumericLabel,
231                                offset = 0, ma = s.major, mi = s.minor,
232                                ta = this.chart.theme.axis,
233                                // TODO: we use one font --- of major tick, we need to use major and minor fonts
234                                taFont = o.font || (ta.majorTick && ta.majorTick.font) || (ta.tick && ta.tick.font),
235                                taTitleFont = o.titleFont || (ta.tick && ta.tick.titleFont),
236                                taTitleGap = (o.titleGap==0) ? 0 : o.titleGap || (ta.tick && ta.tick.titleGap) || 15,
237                                taMajorTick = this.chart.theme.getTick("major", o),
238                                taMinorTick = this.chart.theme.getTick("minor", o),
239                                size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0,
240                                tsize = taTitleFont ? g.normalizedLength(g.splitFontString(taTitleFont).size) : 0,
241                                rotation = o.rotation % 360, leftBottom = o.leftBottom,
242                                cosr = Math.abs(Math.cos(rotation * Math.PI / 180)),
243                                sinr = Math.abs(Math.sin(rotation * Math.PI / 180));
244                        this.trailingSymbol = (o.trailingSymbol === undefined || o.trailingSymbol === null) ? this.trailingSymbol : o.trailingSymbol;
245                        if(rotation < 0){
246                                rotation += 360;
247                        }
248
249                        if(size){
250                                // we need width of all labels
251                                if(this.labels){
252                                        labelWidth = this._groupLabelWidth(this.labels, taFont, o.maxLabelCharCount);
253                                }else{
254                                        labelWidth = this._groupLabelWidth([
255                                                gl(ma.start, ma.prec, o),
256                                                gl(ma.start + ma.count * ma.tick, ma.prec, o),
257                                                gl(mi.start, mi.prec, o),
258                                                gl(mi.start + mi.count * mi.tick, mi.prec, o)
259                                        ], taFont, o.maxLabelCharCount);
260                                }
261                                labelWidth = o.maxLabelSize ? Math.min(o.maxLabelSize, labelWidth) : labelWidth;
262                                if(this.vertical){
263                                        var side = leftBottom ? "l" : "r";
264                                        switch(rotation){
265                                                case 0:
266                                                case 180:
267                                                        offsets[side] = labelWidth;
268                                                        offsets.t = offsets.b = size / 2;
269                                                        break;
270                                                case 90:
271                                                case 270:
272                                                        offsets[side] = size;
273                                                        offsets.t = offsets.b = labelWidth / 2;
274                                                        break;
275                                                default:
276                                                        if(rotation <= centerAnchorLimit || (180 < rotation && rotation <= (180 + centerAnchorLimit))){
277                                                                offsets[side] = size * sinr / 2 + labelWidth * cosr;
278                                                                offsets[leftBottom ? "t" : "b"] = size * cosr / 2 + labelWidth * sinr;
279                                                                offsets[leftBottom ? "b" : "t"] = size * cosr / 2;
280                                                        }else if(rotation > (360 - centerAnchorLimit) || (180 > rotation && rotation > (180 - centerAnchorLimit))){
281                                                                offsets[side] = size * sinr / 2 + labelWidth * cosr;
282                                                                offsets[leftBottom ? "b" : "t"] = size * cosr / 2 + labelWidth * sinr;
283                                                                offsets[leftBottom ? "t" : "b"] = size * cosr / 2;
284                                                        }else if(rotation < 90 || (180 < rotation && rotation < 270)){
285                                                                offsets[side] = size * sinr + labelWidth * cosr;
286                                                                offsets[leftBottom ? "t" : "b"] = size * cosr + labelWidth * sinr;
287                                                        }else{
288                                                                offsets[side] = size * sinr + labelWidth * cosr;
289                                                                offsets[leftBottom ? "b" : "t"] = size * cosr + labelWidth * sinr;
290                                                        }
291                                                        break;
292                                        }
293                                        offsets[side] += labelGap + Math.max(taMajorTick.length, taMinorTick.length) + (o.title ? (tsize + taTitleGap) : 0);
294                                }else{
295                                        var side = leftBottom ? "b" : "t";
296                                        switch(rotation){
297                                                case 0:
298                                                case 180:
299                                                        offsets[side] = size;
300                                                        offsets.l = offsets.r = labelWidth / 2;
301                                                        break;
302                                                case 90:
303                                                case 270:
304                                                        offsets[side] = labelWidth;
305                                                        offsets.l = offsets.r = size / 2;
306                                                        break;
307                                                default:
308                                                        if((90 - centerAnchorLimit) <= rotation && rotation <= 90 || (270 - centerAnchorLimit) <= rotation && rotation <= 270){
309                                                                offsets[side] = size * sinr / 2 + labelWidth * cosr;
310                                                                offsets[leftBottom ? "r" : "l"] = size * cosr / 2 + labelWidth * sinr;
311                                                                offsets[leftBottom ? "l" : "r"] = size * cosr / 2;
312                                                        }else if(90 <= rotation && rotation <= (90 + centerAnchorLimit) || 270 <= rotation && rotation <= (270 + centerAnchorLimit)){
313                                                                offsets[side] = size * sinr / 2 + labelWidth * cosr;
314                                                                offsets[leftBottom ? "l" : "r"] = size * cosr / 2 + labelWidth * sinr;
315                                                                offsets[leftBottom ? "r" : "l"] = size * cosr / 2;
316                                                        }else if(rotation < centerAnchorLimit || (180 < rotation && rotation < (180 - centerAnchorLimit))){
317                                                                offsets[side] = size * sinr + labelWidth * cosr;
318                                                                offsets[leftBottom ? "r" : "l"] = size * cosr + labelWidth * sinr;
319                                                        }else{
320                                                                offsets[side] = size * sinr + labelWidth * cosr;
321                                                                offsets[leftBottom ? "l" : "r"] = size * cosr + labelWidth * sinr;
322                                                        }
323                                                        break;
324                                        }
325                                        offsets[side] += labelGap + Math.max(taMajorTick.length, taMinorTick.length) + (o.title ? (tsize + taTitleGap) : 0);
326                                }
327                        }
328                        if(labelWidth){
329                                this._cachedLabelWidth = labelWidth;
330                        }
331                        return offsets; //      Object
332                },
333                cleanGroup: function(creator){
334                        if(this.opt.enableCache && this.group){
335                                this._lineFreePool = this._lineFreePool.concat(this._lineUsePool);
336                                this._lineUsePool = [];
337                                this._textFreePool = this._textFreePool.concat(this._textUsePool);
338                                this._textUsePool = [];
339                        }
340                        this.inherited(arguments);
341                },
342                createText: function(labelType, creator, x, y, align, textContent, font, fontColor, labelWidth){
343                        if(!this.opt.enableCache || labelType=="html"){
344                                return acommon.createText[labelType](
345                                                this.chart,
346                                                creator,
347                                                x,
348                                                y,
349                                                align,
350                                                textContent,
351                                                font,
352                                                fontColor,
353                                                labelWidth
354                                        );
355                        }
356                        var text;
357                        if (this._textFreePool.length > 0){
358                                text = this._textFreePool.pop();
359                                text.setShape({x: x, y: y, text: textContent, align: align});
360                                // For now all items share the same font, no need to re-set it
361                                //.setFont(font).setFill(fontColor);
362                                // was cleared, add it back
363                                creator.add(text);
364                        }else{
365                                text = acommon.createText[labelType](
366                                                this.chart,
367                                                creator,
368                                                x,
369                                                y,
370                                                align,
371                                                textContent,
372                                                font,
373                                                fontColor,
374                                                labelWidth
375                                        );                      }
376                        this._textUsePool.push(text);
377                        return text;
378                },
379                createLine: function(creator, params){
380                        var line;
381                        if(this.opt.enableCache && this._lineFreePool.length > 0){
382                                line = this._lineFreePool.pop();
383                                line.setShape(params);
384                                // was cleared, add it back
385                                creator.add(line);
386                        }else{
387                                line = creator.createLine(params);
388                        }
389                        if(this.opt.enableCache){
390                                this._lineUsePool.push(line);
391                        }
392                        return line;
393                },
394                render: function(dim, offsets){
395                        //      summary:
396                        //              Render/draw the axis.
397                        //      dim: Object
398                        //              An object of the form { width, height}.
399                        //      offsets: Object
400                        //              An object of the form { l, r, t, b }.
401                        //      returns: dojox.charting.axis2d.Default
402                        //              The reference to the axis for functional chaining.
403                        if(!this.dirty){
404                                return this;    //      dojox.charting.axis2d.Default
405                        }
406                        // prepare variable
407                        var o = this.opt, ta = this.chart.theme.axis, leftBottom = o.leftBottom, rotation = o.rotation % 360,
408                                start, stop, titlePos, titleRotation=0, titleOffset, axisVector, tickVector, anchorOffset, labelOffset, labelAlign,
409
410                                // TODO: we use one font --- of major tick, we need to use major and minor fonts
411                                taFont = o.font || (ta.majorTick && ta.majorTick.font) || (ta.tick && ta.tick.font),
412                                taTitleFont = o.titleFont || (ta.tick && ta.tick.titleFont),
413                                // TODO: we use one font color --- we need to use different colors
414                                taFontColor = o.fontColor || (ta.majorTick && ta.majorTick.fontColor) || (ta.tick && ta.tick.fontColor) || "black",
415                                taTitleFontColor = o.titleFontColor || (ta.tick && ta.tick.titleFontColor) || "black",
416                                taTitleGap = (o.titleGap==0) ? 0 : o.titleGap || (ta.tick && ta.tick.titleGap) || 15,
417                                taTitleOrientation = o.titleOrientation || (ta.tick && ta.tick.titleOrientation) || "axis",
418                                taMajorTick = this.chart.theme.getTick("major", o),
419                                taMinorTick = this.chart.theme.getTick("minor", o),
420                                taMicroTick = this.chart.theme.getTick("micro", o),
421
422                                tickSize = Math.max(taMajorTick.length, taMinorTick.length, taMicroTick.length),
423                                taStroke = "stroke" in o ? o.stroke : ta.stroke,
424                                size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0,
425                                cosr = Math.abs(Math.cos(rotation * Math.PI / 180)),
426                                sinr = Math.abs(Math.sin(rotation * Math.PI / 180)),
427                                tsize = taTitleFont ? g.normalizedLength(g.splitFontString(taTitleFont).size) : 0;
428                        if(rotation < 0){
429                                rotation += 360;
430                        }
431                        if(this.vertical){
432                                start = {y: dim.height - offsets.b};
433                                stop  = {y: offsets.t};
434                                titlePos = {y: (dim.height - offsets.b + offsets.t)/2};
435                                titleOffset = size * sinr + (this._cachedLabelWidth || 0) * cosr + labelGap + Math.max(taMajorTick.length, taMinorTick.length) + tsize + taTitleGap;
436                                axisVector = {x: 0, y: -1};
437                                labelOffset = {x: 0, y: 0};
438                                tickVector = {x: 1, y: 0};
439                                anchorOffset = {x: labelGap, y: 0};
440                                switch(rotation){
441                                        case 0:
442                                                labelAlign = "end";
443                                                labelOffset.y = size * 0.4;
444                                                break;
445                                        case 90:
446                                                labelAlign = "middle";
447                                                labelOffset.x = -size;
448                                                break;
449                                        case 180:
450                                                labelAlign = "start";
451                                                labelOffset.y = -size * 0.4;
452                                                break;
453                                        case 270:
454                                                labelAlign = "middle";
455                                                break;
456                                        default:
457                                                if(rotation < centerAnchorLimit){
458                                                        labelAlign = "end";
459                                                        labelOffset.y = size * 0.4;
460                                                }else if(rotation < 90){
461                                                        labelAlign = "end";
462                                                        labelOffset.y = size * 0.4;
463                                                }else if(rotation < (180 - centerAnchorLimit)){
464                                                        labelAlign = "start";
465                                                }else if(rotation < (180 + centerAnchorLimit)){
466                                                        labelAlign = "start";
467                                                        labelOffset.y = -size * 0.4;
468                                                }else if(rotation < 270){
469                                                        labelAlign = "start";
470                                                        labelOffset.x = leftBottom ? 0 : size * 0.4;
471                                                }else if(rotation < (360 - centerAnchorLimit)){
472                                                        labelAlign = "end";
473                                                        labelOffset.x = leftBottom ? 0 : size * 0.4;
474                                                }else{
475                                                        labelAlign = "end";
476                                                        labelOffset.y = size * 0.4;
477                                                }
478                                }
479                                if(leftBottom){
480                                        start.x = stop.x = offsets.l;
481                                        titleRotation = (taTitleOrientation && taTitleOrientation == "away") ? 90 : 270;
482                                        titlePos.x = offsets.l - titleOffset + (titleRotation == 270 ? tsize : 0);
483                                        tickVector.x = -1;
484                                        anchorOffset.x = -anchorOffset.x;
485                                }else{
486                                        start.x = stop.x = dim.width - offsets.r;
487                                        titleRotation = (taTitleOrientation && taTitleOrientation == "axis") ? 90 : 270;
488                                        titlePos.x = dim.width - offsets.r + titleOffset - (titleRotation == 270 ? 0 : tsize);
489                                        switch(labelAlign){
490                                                case "start":
491                                                        labelAlign = "end";
492                                                        break;
493                                                case "end":
494                                                        labelAlign = "start";
495                                                        break;
496                                                case "middle":
497                                                        labelOffset.x += size;
498                                                        break;
499                                        }
500                                }
501                        }else{
502                                start = {x: offsets.l};
503                                stop  = {x: dim.width - offsets.r};
504                                titlePos = {x: (dim.width - offsets.r + offsets.l)/2};
505                                titleOffset = size * cosr + (this._cachedLabelWidth || 0) * sinr + labelGap + Math.max(taMajorTick.length, taMinorTick.length) + tsize + taTitleGap;
506                                axisVector = {x: 1, y: 0};
507                                labelOffset = {x: 0, y: 0};
508                                tickVector = {x: 0, y: 1};
509                                anchorOffset = {x: 0, y: labelGap};
510                                switch(rotation){
511                                        case 0:
512                                                labelAlign = "middle";
513                                                labelOffset.y = size;
514                                                break;
515                                        case 90:
516                                                labelAlign = "start";
517                                                labelOffset.x = -size * 0.4;
518                                                break;
519                                        case 180:
520                                                labelAlign = "middle";
521                                                break;
522                                        case 270:
523                                                labelAlign = "end";
524                                                labelOffset.x = size * 0.4;
525                                                break;
526                                        default:
527                                                if(rotation < (90 - centerAnchorLimit)){
528                                                        labelAlign = "start";
529                                                        labelOffset.y = leftBottom ? size : 0;
530                                                }else if(rotation < (90 + centerAnchorLimit)){
531                                                        labelAlign = "start";
532                                                        labelOffset.x = -size * 0.4;
533                                                }else if(rotation < 180){
534                                                        labelAlign = "start";
535                                                        labelOffset.y = leftBottom ? 0 : -size;
536                                                }else if(rotation < (270 - centerAnchorLimit)){
537                                                        labelAlign = "end";
538                                                        labelOffset.y = leftBottom ? 0 : -size;
539                                                }else if(rotation < (270 + centerAnchorLimit)){
540                                                        labelAlign = "end";
541                                                        labelOffset.y = leftBottom ? size * 0.4 : 0;
542                                                }else{
543                                                        labelAlign = "end";
544                                                        labelOffset.y = leftBottom ? size : 0;
545                                                }
546                                }
547                                if(leftBottom){
548                                        start.y = stop.y = dim.height - offsets.b;
549                                        titleRotation = (taTitleOrientation && taTitleOrientation == "axis") ? 180 : 0;
550                                        titlePos.y = dim.height - offsets.b + titleOffset - (titleRotation ? tsize : 0);
551                                }else{
552                                        start.y = stop.y = offsets.t;
553                                        titleRotation = (taTitleOrientation && taTitleOrientation == "away") ? 180 : 0;
554                                        titlePos.y = offsets.t - titleOffset + (titleRotation ? 0 : tsize);
555                                        tickVector.y = -1;
556                                        anchorOffset.y = -anchorOffset.y;
557                                        switch(labelAlign){
558                                                case "start":
559                                                        labelAlign = "end";
560                                                        break;
561                                                case "end":
562                                                        labelAlign = "start";
563                                                        break;
564                                                case "middle":
565                                                        labelOffset.y -= size;
566                                                        break;
567                                        }
568                                }
569                        }
570
571                        // render shapes
572
573                        this.cleanGroup();
574
575                        try{
576                                var s = this.group,
577                                        c = this.scaler,
578                                        t = this.ticks,
579                                        canLabel,
580                                        f = lin.getTransformerFromModel(this.scaler),
581                                        // GFX Canvas now supports labels, so let's _not_ fallback to HTML anymore on canvas, just use
582                                        // HTML labels if explicitly asked + no rotation + no IE + no Opera
583                                        labelType = (!o.title || !titleRotation) && !rotation && this.opt.htmlLabels && !has("ie") && !has("opera") ? "html" : "gfx",
584                                        dx = tickVector.x * taMajorTick.length,
585                                        dy = tickVector.y * taMajorTick.length;
586
587                                s.createLine({
588                                        x1: start.x,
589                                        y1: start.y,
590                                        x2: stop.x,
591                                        y2: stop.y
592                                }).setStroke(taStroke);
593                               
594                                //create axis title
595                                if(o.title){
596                                        var axisTitle = acommon.createText[labelType](
597                                                this.chart,
598                                                s,
599                                                titlePos.x,
600                                                titlePos.y,
601                                                "middle",
602                                                o.title,
603                                                taTitleFont,
604                                                taTitleFontColor
605                                        );
606                                        if(labelType == "html"){
607                                                this.htmlElements.push(axisTitle);
608                                        }else{
609                                                //as soon as rotation is provided, labelType won't be "html"
610                                                //rotate gfx labels
611                                                axisTitle.setTransform(g.matrix.rotategAt(titleRotation, titlePos.x, titlePos.y));
612                                        }
613                                }
614                               
615                                // go out nicely instead of try/catch
616                                if(t==null){
617                                        this.dirty = false;
618                                        return this;
619                                }
620
621                                arr.forEach(t.major, function(tick){
622                                        var offset = f(tick.value), elem,
623                                                x = start.x + axisVector.x * offset,
624                                                y = start.y + axisVector.y * offset;
625                                                this.createLine(s, {
626                                                        x1: x, y1: y,
627                                                        x2: x + dx,
628                                                        y2: y + dy
629                                                }).setStroke(taMajorTick);
630                                                if(tick.label){
631                                                        var label = o.maxLabelCharCount ? this.getTextWithLimitCharCount(tick.label, taFont, o.maxLabelCharCount) : {
632                                                                text: tick.label,
633                                                                truncated: false
634                                                        };
635                                                        label = o.maxLabelSize ? this.getTextWithLimitLength(label.text, taFont, o.maxLabelSize, label.truncated) : label;
636                                                        elem = this.createText(labelType,
637                                                                s,
638                                                                x + dx + anchorOffset.x + (rotation ? 0 : labelOffset.x),
639                                                                y + dy + anchorOffset.y + (rotation ? 0 : labelOffset.y),
640                                                                labelAlign,
641                                                                label.text,
642                                                                taFont,
643                                                                taFontColor
644                                                                //this._cachedLabelWidth
645                                                        );
646                                                       
647                                                        // if bidi support was required, the textDir is "auto" and truncation
648                                                        // took place, we need to update the dir of the element for cases as:
649                                                        // Fool label: 111111W (W for bidi character)
650                                                        // truncated label: 11...
651                                                        // in this case for auto textDir the dir will be "ltr" which is wrong.
652                                                        if(this.chart.truncateBidi  && label.truncated){
653                                                                this.chart.truncateBidi(elem, tick.label, labelType);
654                                                        }
655                                                        label.truncated && this.labelTooltip(elem, this.chart, tick.label, label.text, taFont, labelType);
656                                                        if(labelType == "html"){
657                                                                this.htmlElements.push(elem);
658                                                        }else if(rotation){
659                                                                elem.setTransform([
660                                                                        {dx: labelOffset.x, dy: labelOffset.y},
661                                                                        g.matrix.rotategAt(
662                                                                                rotation,
663                                                                                x + dx + anchorOffset.x,
664                                                                                y + dy + anchorOffset.y
665                                                                        )
666                                                                ]);
667                                                        }
668                                                }
669                                }, this);
670
671                                dx = tickVector.x * taMinorTick.length;
672                                dy = tickVector.y * taMinorTick.length;
673                                canLabel = c.minMinorStep <= c.minor.tick * c.bounds.scale;
674                                arr.forEach(t.minor, function(tick){
675                                        var offset = f(tick.value), elem,
676                                                x = start.x + axisVector.x * offset,
677                                                y = start.y + axisVector.y * offset;
678                                                this.createLine(s, {
679                                                        x1: x, y1: y,
680                                                        x2: x + dx,
681                                                        y2: y + dy
682                                                }).setStroke(taMinorTick);
683                                                if(canLabel && tick.label){
684                                                        var label = o.maxLabelCharCount ? this.getTextWithLimitCharCount(tick.label, taFont, o.maxLabelCharCount) : {
685                                                                text: tick.label,
686                                                                truncated: false
687                                                        };
688                                                        label = o.maxLabelSize ? this.getTextWithLimitLength(label.text, taFont, o.maxLabelSize, label.truncated) : label;
689                                                        elem = this.createText(labelType,
690                                                                s,
691                                                                x + dx + anchorOffset.x + (rotation ? 0 : labelOffset.x),
692                                                                y + dy + anchorOffset.y + (rotation ? 0 : labelOffset.y),
693                                                                labelAlign,
694                                                                label.text,
695                                                                taFont,
696                                                                taFontColor
697                                                                //this._cachedLabelWidth
698                                                        );
699                                                        // if bidi support was required, the textDir is "auto" and truncation
700                                                        // took place, we need to update the dir of the element for cases as:
701                                                        // Fool label: 111111W (W for bidi character)
702                                                        // truncated label: 11...
703                                                        // in this case for auto textDir the dir will be "ltr" which is wrong.
704                                                        if(this.chart.getTextDir && label.truncated){
705                                                                this.chart.truncateBidi(elem, tick.label, labelType);
706                                                        }
707                                                        label.truncated && this.labelTooltip(elem, this.chart, tick.label, label.text, taFont, labelType);
708                                                        if(labelType == "html"){
709                                                                this.htmlElements.push(elem);
710                                                        }else if(rotation){
711                                                                elem.setTransform([
712                                                                        {dx: labelOffset.x, dy: labelOffset.y},
713                                                                        g.matrix.rotategAt(
714                                                                                rotation,
715                                                                                x + dx + anchorOffset.x,
716                                                                                y + dy + anchorOffset.y
717                                                                        )
718                                                                ]);
719                                                        }
720                                                }
721                                }, this);
722
723                                dx = tickVector.x * taMicroTick.length;
724                                dy = tickVector.y * taMicroTick.length;
725                                arr.forEach(t.micro, function(tick){
726                                        var offset = f(tick.value), elem,
727                                                x = start.x + axisVector.x * offset,
728                                                y = start.y + axisVector.y * offset;
729                                                this.createLine(s, {
730                                                        x1: x, y1: y,
731                                                        x2: x + dx,
732                                                        y2: y + dy
733                                                }).setStroke(taMicroTick);
734                                }, this);
735                        }catch(e){
736                                // squelch
737                        }
738
739                        this.dirty = false;
740                        return this;    //      dojox.charting.axis2d.Default
741                },
742                labelTooltip: function(elem, chart, label, truncatedLabel, font, elemType){
743                        var modules = ["dijit/Tooltip"];
744                        var aroundRect = {type: "rect"}, position = ["above", "below"],
745                                fontWidth = g._base._getTextBox(truncatedLabel, {font: font}).w || 0,
746                                fontHeight = font ? g.normalizedLength(g.splitFontString(font).size) : 0;
747                        if(elemType == "html"){
748                                lang.mixin(aroundRect, html.coords(elem.firstChild, true));
749                                aroundRect.width = Math.ceil(fontWidth);
750                                aroundRect.height = Math.ceil(fontHeight);
751                                this._events.push({
752                                        shape:  dojo,
753                                        handle: connect.connect(elem.firstChild, "onmouseover", this, function(e){
754                                                require(modules, function(Tooltip){
755                                                        Tooltip.show(label, aroundRect, position);
756                                                });
757                                        })
758                                });
759                                this._events.push({
760                                        shape:  dojo,
761                                        handle: connect.connect(elem.firstChild, "onmouseout", this, function(e){
762                                                require(modules, function(Tooltip){
763                                                        Tooltip.hide(aroundRect);
764                                                });
765                                        })
766                                });
767                        }else{
768                                var shp = elem.getShape(),
769                                        lt = html.coords(chart.node, true);
770                                aroundRect = lang.mixin(aroundRect, {
771                                        x: shp.x - fontWidth / 2,
772                                        y: shp.y
773                                });
774                                aroundRect.x += lt.x;
775                                aroundRect.y += lt.y;
776                                aroundRect.x = Math.round(aroundRect.x);
777                                aroundRect.y = Math.round(aroundRect.y);
778                                aroundRect.width = Math.ceil(fontWidth);
779                                aroundRect.height = Math.ceil(fontHeight);
780                                this._events.push({
781                                        shape:  elem,
782                                        handle: elem.connect("onmouseenter", this, function(e){
783                                                require(modules, function(Tooltip){
784                                                        Tooltip.show(label, aroundRect, position);
785                                                });
786                                        })
787                                });
788                                this._events.push({
789                                        shape:  elem,
790                                        handle: elem.connect("onmouseleave", this, function(e){
791                                                require(modules, function(Tooltip){
792                                                        Tooltip.hide(aroundRect);
793                                                });
794                                        })
795                                });
796                        }
797                }
798        });
799});
Note: See TracBrowser for help on using the repository browser.