001 /*
002 * Copyright 2007,2008 John C. Gunther
003 *
004 * Licensed under the Apache License, Version 2.0 (the
005 * "License"); you may not use this file except in compliance
006 * with the License. You may obtain a copy of the License at:
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing,
011 * software distributed under the License is distributed on an
012 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific
014 * language governing permissions and limitations under the
015 * License.
016 *
017 */
018 package com.googlecode.gchart.client;
019
020 import com.google.gwt.i18n.client.DateTimeFormat;
021 import com.google.gwt.i18n.client.NumberFormat;
022 import com.google.gwt.user.client.DOM;
023 import com.google.gwt.user.client.Event;
024 import com.google.gwt.user.client.ui.AbsolutePanel;
025 import com.google.gwt.user.client.ui.Composite;
026 import com.google.gwt.user.client.ui.Grid;
027 import com.google.gwt.user.client.ui.HasHTML;
028 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
029 import com.google.gwt.user.client.ui.HasText;
030 import com.google.gwt.user.client.ui.HasVerticalAlignment;
031 import com.google.gwt.user.client.ui.HTML;
032 import com.google.gwt.user.client.ui.Image;
033 import com.google.gwt.user.client.ui.SimplePanel;
034 import com.google.gwt.user.client.ui.UIObject;
035 import com.google.gwt.user.client.ui.Widget;
036 import java.util.ArrayList;
037 import java.util.Date;
038
039 /**
040 * A GChart can represent and display a line chart, a bar chart,
041 * a pie chart, an area chart, or a chart that contains arbitrary
042 * combinations of line, bar, pie, and/or area based curves.
043 *
044 * <p>
045 * For detailed examples, with screen shots, visit the
046 * <a href="package-summary.html#ChartGallery">
047 * Chart Gallery</a>.
048 *
049 * <p>
050 * For detailed instructions on how to integrate Client-side GChart
051 * into your GWT application, see
052 * <a href="package-summary.html#InstallingGChart">
053 * Installing Client-side GChart</a>.
054 *
055 * <p>
056 * <b>CSS Style Rule</b>
057 * <ul>
058 * .gchart-GChart { the GChart's primary top-level styles }
059 * </ul>
060 *
061 *
062 * It is sometimes more natural to consider certain CSS
063 * attributes as properties of a GChart Java object. So, GChart
064 * supports "CSS convenience methods" that let you (optionally) use
065 * Java to specify GChart CSS attributes such as
066 * <tt>border-color</tt> and <tt>background-color</tt>. See
067 * {@link #USE_CSS USE_CSS} for a detailed description of these
068 * CSS convenience methods--which won't interfere with standard
069 * CSS-based specifications if you never invoke them.
070 *
071 *
072 **/
073
074 public class GChart extends Composite {
075
076
077 /**
078 ** Defines the location of a data point's annotation (text
079 ** label) relative to the location of that point's symbol.
080 ** The default annotation location is {@link
081 ** AnnotationLocation#SOUTH SOUTH}. The "Field Summary"
082 ** section below lists all available annotation locations.
083 **
084 ** <p>
085 **
086 ** You can further adjust the position of a point's
087 ** annotation by specifying non-zero positional shifts via
088 ** the <tt>setAnnotationXShift</tt> and
089 ** <tt>setAnnotationYShift</tt> methods.
090 **
091 ** @see Curve.Point#setAnnotationLocation Point.setAnnotationLocation
092 ** @see Curve.Point#setAnnotationXShift Point.setAnnotationXShift
093 ** @see Curve.Point#setAnnotationYShift Point.setAnnotationYShift
094 **
095 **/
096 public static final class AnnotationLocation {
097 /**
098 ** Specifies that a point's annotation (label) should
099 ** be positioned so as to be centered on the symbol
100 ** used to represent the point.
101 **
102 ** @see Curve.Point#setAnnotationLocation setAnnotationLocation
103 **/
104 public static final AnnotationLocation CENTER =
105 new AnnotationLocation(0,0);
106
107 private static final AnnotationLocation north =
108 new AnnotationLocation(0,-1);
109 private static final AnnotationLocation west =
110 new AnnotationLocation(-1, 0);
111 private static final AnnotationLocation south =
112 new AnnotationLocation(0, 1);
113
114 /**
115 ** Specifies that a point's annotation (label) should be
116 ** placed just above, and centered horizontally on,
117 ** vertical bars that grow down from a horizontal
118 ** baseline, and just below, and centered horizontally on,
119 ** vertical bars that grow up from a horizontal baseline.
120 **
121 ** <p>
122 **
123 ** This another name for
124 ** <tt>AnnotationLocation.NORTH</tt>. Its sole purpose is
125 ** to clarify/document the behavior of this location type
126 ** when used in conjunction with curves that employ
127 ** <tt>VBAR_BASELINE_*</tt> symbol types.
128 **
129 ** @see Curve.Point#setAnnotationLocation setAnnotationLocation
130 ** @see SymbolType#VBAR_BASELINE_CENTER SymbolType.VBAR_BASELINE_CENTER
131 **
132 **/
133 public static final AnnotationLocation
134 CLOSEST_TO_HORIZONTAL_BASELINE = north;
135
136 /**
137 ** Specifies that a point's annotation (label) should be
138 ** placed just to the right of, and centered vertically
139 ** on, horizontal bars that grow left from a vertical
140 ** baseline, and just to the left of, and centered
141 ** vertically on, horizontal bars that grow right from a
142 ** vertical baseline.
143 **
144 ** <p>
145 **
146 ** This another name for
147 ** <tt>AnnotationLocation.WEST</tt>. Its sole purpose is
148 ** to clarify/document the behavior of this location type
149 ** when used in conjunction with curves that employ the
150 ** <tt>HBAR_BASELINE_*</tt> symbol types.
151 **
152 ** @see Curve.Point#setAnnotationLocation setAnnotationLocation
153 ** @see SymbolType#HBAR_BASELINE_CENTER SymbolType.HBAR_BASELINE_CENTER
154 **
155 **/
156
157 public static final AnnotationLocation
158 CLOSEST_TO_VERTICAL_BASELINE = west;
159
160 /**
161 ** Specifies that a point's annotation (label) should
162 ** be positioned just to the right of, and vertically
163 ** centered on, the symbol used to represent the
164 ** point.
165 **
166 ** @see Curve.Point#setAnnotationLocation
167 **/
168 public static final AnnotationLocation EAST =
169 new AnnotationLocation(1, 0);
170
171 /**
172 ** Specifies that a point's annotation (label) should be
173 ** placed just below, and centered horizontally on,
174 ** vertical bars that grow down from a horizontal
175 ** baseline, and just above, and centered horizontally on,
176 ** vertical bars that grow up from a horizontal baseline.
177 **
178 ** <p>
179 **
180 ** This another name for
181 ** <tt>AnnotationLocation.SOUTH</tt>. Its sole purpose is
182 ** to clarify/document the behavior of this location type
183 ** when used in conjunction with curves that employ
184 ** <tt>VBAR_BASELINE_*</tt> symbol types.
185 **
186 ** @see Curve.Point#setAnnotationLocation setAnnotationLocation
187 ** @see SymbolType#VBAR_BASELINE_CENTER SymbolType.VBAR_BASELINE_CENTER
188 **
189 **/
190 public static final AnnotationLocation
191 FARTHEST_FROM_HORIZONTAL_BASELINE = south;
192
193 /**
194 ** Specifies that a point's annotation (label) should be
195 ** placed just to the left of, and centered vertically on,
196 ** horizontal bars that grow left from a vertical
197 ** baseline, and just to the right of, and centered
198 ** vertically on, horizontal bars that grow right from a
199 ** vertical baseline.
200 **
201 ** <p>
202 **
203 ** This another name for
204 ** <tt>AnnotationLocation.EAST</tt>. Its sole purpose is
205 ** to clarify/document the behavior of this location type
206 ** when used in conjunction with curves that employ the
207 ** <tt>HBAR_BASELINE_*</tt> family of symbol types.
208 **
209 ** @see Curve.Point#setAnnotationLocation setAnnotationLocation
210 ** @see SymbolType#HBAR_BASELINE_CENTER SymbolType.HBAR_BASELINE_CENTER
211 **
212 **/
213 public static final AnnotationLocation
214 FARTHEST_FROM_VERTICAL_BASELINE = EAST;
215
216
217 /**
218 ** Specifies that a point's annotation (label) should
219 ** be positioned just inside, and centered on, the
220 ** arc side of a pie slice.
221 ** <p>
222 **
223 ** You can move a pie slice's annotation a specific number
224 ** of pixels radially away from (or towards) the pie
225 ** center by passing a positive (or negative) argument to
226 ** the associated <tt>Point</tt>'s
227 ** <tt>setAnnotationXShift</tt> method.
228 **
229 ** <p> This is pie-friendly synonym for, and when used
230 ** with non-pie symbol types will behave exactly the same
231 ** as, <tt>AnnotationLocation.NORTH</tt>
232 **
233 ** @see #OUTSIDE_PIE_ARC OUTSIDE_PIE_ARC
234 ** @see #ON_PIE_ARC ON_PIE_ARC
235 ** @see Curve.Point#setAnnotationLocation setAnnotationLocation
236 ** @see AnnotationLocation#NORTH NORTH
237 **/
238 public static final AnnotationLocation INSIDE_PIE_ARC = north;
239
240 /**
241 ** Specifies that a point's annotation (label) should
242 ** be positioned just above, and horizontally centered on,
243 ** the symbol used to represent the point.
244 **
245 ** @see Curve.Point#setAnnotationLocation setAnnotationLocation
246 **/
247 public static final AnnotationLocation NORTH = north;
248
249
250 /**
251 ** Specifies that a point's annotation (label) should
252 ** be positioned just to the right of and above,
253 ** the symbol used to represent the
254 ** point.
255 **
256 ** @see Curve.Point#setAnnotationLocation
257 **/
258 public static final AnnotationLocation NORTHEAST =
259 new AnnotationLocation(1, -1);
260
261 /**
262 ** Specifies that a point's annotation (label) should
263 ** be positioned just to the left of and above,
264 ** the symbol used to represent the
265 ** point.
266 **
267 ** @see Curve.Point#setAnnotationLocation
268 **/
269 public static final AnnotationLocation NORTHWEST =
270 new AnnotationLocation(-1, -1);
271
272
273 /**
274 ** Specifies that a point's annotation (label) should
275 ** be centered on the center-point of the
276 ** arc side of a pie slice.
277 ** <p>
278 **
279 ** You can move a pie slice's annotation a specific number
280 ** of pixels radially away from (or towards) the pie
281 ** center by passing a positive (or negative) argument to
282 ** the associated <tt>Point</tt>'s
283 ** <tt>setAnnotationXShift</tt> method.
284 **
285 **
286 **
287 ** <p> This is pie-friendly synonym for, and when used
288 ** with non-pie symbol types will behave exactly the same
289 ** as, <tt>AnnotationLocation.CENTER</tt>
290 **
291 ** @see #OUTSIDE_PIE_ARC OUTSIDE_PIE_ARC
292 ** @see #INSIDE_PIE_ARC INSIDE_PIE_ARC
293 ** @see Curve.Point#setAnnotationLocation setAnnotationLocation
294 ** @see AnnotationLocation#CENTER CENTER
295 **
296 **/
297 public static final AnnotationLocation ON_PIE_ARC = CENTER;
298
299 /**
300 ** Specifies that a point's annotation (label) should
301 ** be positioned just outside, and centered on, the
302 ** arc side of a pie slice.
303 ** <p>
304 **
305 ** You can move a pie slice's annotation a specific number
306 ** of pixels radially away from (or towards) the pie
307 ** center by passing a positive (or negative) argument to
308 ** the associated <tt>Point</tt>'s
309 ** <tt>setAnnotationXShift</tt> method.
310 **
311 ** <p> This is pie-friendly synonym for, and when used
312 ** with non-pie symbol types will behave exactly the same
313 ** as, <tt>AnnotationLocation.SOUTH</tt>
314 **
315 ** @see #INSIDE_PIE_ARC INSIDE_PIE_ARC
316 ** @see #ON_PIE_ARC ON_PIE_ARC
317 ** @see Curve.Point#setAnnotationLocation setAnnotationLocation
318 ** @see Curve.Point#setAnnotationXShift setAnnotationXShift
319 ** @see AnnotationLocation#SOUTH SOUTH
320 **/
321 public static final AnnotationLocation OUTSIDE_PIE_ARC = south;
322
323 /**
324 ** Specifies that a point's annotation (label) should
325 ** be positioned just below, and horizontally centered on,
326 ** the symbol used to represent the point.
327 **
328 ** @see Curve.Point#setAnnotationLocation setAnnotationLocation
329 **/
330 public static final AnnotationLocation SOUTH = south;
331
332
333 /**
334 ** Specifies that a point's annotation (label) should
335 ** be positioned just to the right of and below,
336 ** the symbol used to represent the
337 ** point.
338 **
339 ** @see Curve.Point#setAnnotationLocation setAnnotationLocation
340 **/
341 public static final AnnotationLocation SOUTHEAST =
342 new AnnotationLocation(1, 1);
343 /**
344 ** Specifies that a point's annotation (label) should
345 ** be positioned just to the left of and below,
346 ** the symbol used to represent the
347 ** point.
348 **
349 ** @see Curve.Point#setAnnotationLocation setAnnotationLocation
350 **/
351 public static final AnnotationLocation SOUTHWEST =
352 new AnnotationLocation(-1, 1);
353
354 /**
355 ** Specifies that a point's annotation (label) should
356 ** be positioned just to the left of, and vertically
357 ** centered on, the symbol used to represent the
358 ** point.
359 **
360 ** @see Curve.Point#setAnnotationLocation setAnnotationLocation
361 **/
362 public static final AnnotationLocation WEST = west;
363
364
365
366 // these multiply the width and height of the annotation and
367 // the symbol it is attached to in order to define the
368 // center of the annotation (see equations in later code),
369 // and thus the upper left corner anchoring point.
370 private int heightMultiplier;
371 private int widthMultiplier;
372 private AnnotationLocation(int widthMultiplier,
373 int heightMultiplier) {
374 validateMultipliers(widthMultiplier, heightMultiplier);
375 this.widthMultiplier = widthMultiplier;
376 this.heightMultiplier = heightMultiplier;
377 }
378 // retrieves a static location given its multipliers
379 private static AnnotationLocation getAnnotationLocation(
380 int widthMultiplier, int heightMultiplier) {
381 final AnnotationLocation[][] locationMap = {
382 {NORTHWEST, NORTH, NORTHEAST},
383 {WEST, CENTER, EAST},
384 {SOUTHWEST, SOUTH, SOUTHEAST}};
385 // assumes both multiplier are -1, 0, or 1
386 AnnotationLocation result =
387 locationMap[heightMultiplier+1][widthMultiplier+1];
388 return result;
389 }
390
391 // Negative width or height "turn the symbol inside-out",
392 // requiring a corresponding "reflection" of annotation
393 // location (only needed for baseline-based bar symbols)
394 static AnnotationLocation transform(AnnotationLocation a,
395 int signWidth,
396 int signHeight) {
397 AnnotationLocation result = a;
398 if (signWidth < 0 || signHeight < 0)
399 result = getAnnotationLocation(
400 signWidth*a.widthMultiplier,
401 signHeight*a.heightMultiplier);
402
403 return result;
404 }
405 // These define the alignment of the label within it's
406 // containing 1 x 1 Grid. For example, if this
407 // containing grid is to the left of the labeled
408 // symbol (widthMultiplier==-1) the horizontal
409 // alignment will be ALIGN_RIGHT, so as to bring the
410 // contained label flush against the left edge of the
411 // labeled symbol.
412 HasHorizontalAlignment.HorizontalAlignmentConstant
413 getHorizontalAlignment() {
414 HasHorizontalAlignment.HorizontalAlignmentConstant result;
415 if (widthMultiplier == -1)
416 result = HasHorizontalAlignment.ALIGN_RIGHT;
417 else if (widthMultiplier == 0)
418 result = HasHorizontalAlignment.ALIGN_CENTER;
419 else if (widthMultiplier == 1)
420 result = HasHorizontalAlignment.ALIGN_LEFT;
421 else
422 throw new IllegalStateException(
423 "Invalid widthMultiplier: " + widthMultiplier +
424 " 1, 0, or -1 were expected.");
425 return result;
426 }
427
428 /* Given the x-coordinate at the center of the symbol
429 * that this annotation annotates, the annotation's
430 * width, and the symbol's width, this method returns
431 * the x-coordinate of the upper left corner of
432 * this annotation.
433 */
434 int getUpperLeftX(double x, double w, double symbolW) {
435 int result = (int) Math.round(x +
436 (widthMultiplier * (w + symbolW) - w)/2.);
437 return result;
438 }
439
440 /* analogous to getUpperLeftX, except for the y-coordinate */
441 int getUpperLeftY(double y, double h, double symbolH) {
442 int result = (int) Math.round(y +
443 (heightMultiplier * (h + symbolH) - h)/2.);
444 return result;
445 }
446 // analogous to getHorizontalAlignment
447 HasVerticalAlignment.VerticalAlignmentConstant
448 getVerticalAlignment() {
449 HasVerticalAlignment.VerticalAlignmentConstant result;
450 if (heightMultiplier == -1)
451 result = HasVerticalAlignment.ALIGN_BOTTOM;
452 else if (heightMultiplier == 0)
453 result = HasVerticalAlignment.ALIGN_MIDDLE;
454 else if (heightMultiplier == 1)
455 result = HasVerticalAlignment.ALIGN_TOP;
456 else
457 throw new IllegalStateException(
458 "Invalid heightMultiplier: " + heightMultiplier +
459 " -1, 0, or 1 were expected.");
460 return result;
461 }
462
463
464 /*
465 * This method returns the annotation location whose
466 * "attachment point" keeps the annotation either
467 * completely outside, centered on, or completely inside
468 * (depending on if the heightMultiplier of this annotation
469 * is 1, 0, or -1) the point on the pie's circumference
470 * associated with the given angle.
471 * <p>
472 *
473 * The use of heightMultiplier rather than widthMultiplier
474 * is somewhat arbitrary, but was chosen so that the
475 * NORTH, CENTER, and SOUTH annotation locations have the
476 * same interpretation for a pie slice whose bisecting
477 * radius points due south (due south is the default initial
478 * pie slice orientation) and for a 1px x 1px BOX_CENTER
479 * type symbol positioned at the due south position on the
480 * pie's circumference. As the pie-slice-arc-bisection
481 * point moves clockwise around the pie perimeter, the
482 * attachment point (except for vertically-centered
483 * annotations, which remain centered on the pie arc) also
484 * moves clockwise, but in discrete jumps (e.g. from
485 * NORTH, to NORTHEAST, to EAST, to SOUTHEAST, to SOUTH,
486 * etc. for annotations inside the pie) so the annotation
487 * remains appropriately attached to the center of the
488 * slice's arc as the angle changes.
489 *
490 */
491 AnnotationLocation decodePieLocation(double thetaMid) {
492 // a sin or cos that is small enough so that the
493 // associated angle is horizontal (for sines) or vertical
494 // (for cosines) enough to warrent use of a "centered"
495 // annotation location.
496 final double LOOKS_VERTICAL_OR_HORIZONTAL_DELTA = 0.1;
497 double sinTheta = Math.sin(thetaMid);
498 double cosTheta = Math.cos(thetaMid);
499 int pieTransformedWidthMultiplier = heightMultiplier *
500 ((cosTheta < -LOOKS_VERTICAL_OR_HORIZONTAL_DELTA)? -1 :
501 ((cosTheta > LOOKS_VERTICAL_OR_HORIZONTAL_DELTA)? 1 : 0));
502 int pieTransformedHeightMultiplier = heightMultiplier *
503 ((sinTheta < -LOOKS_VERTICAL_OR_HORIZONTAL_DELTA)? 1 :
504 ((sinTheta > LOOKS_VERTICAL_OR_HORIZONTAL_DELTA)? -1 : 0));
505
506 return getAnnotationLocation(pieTransformedWidthMultiplier,
507 pieTransformedHeightMultiplier);
508
509 }
510
511 } // end of class AnnotationLocation
512
513 /**
514 ** Represents an axis of the chart, for example, the x,
515 ** y, or y2 axis. An axis consists of the axis itself,
516 ** along with its tick marks, tick labels and gridlines.
517 **
518 ** @see XAxis XAxis
519 ** @see YAxis YAxis
520 ** @see Y2Axis Y2Axis
521 ** @see #getXAxis getXAxis
522 ** @see #getYAxis getYAxis
523 ** @see #getY2Axis getY2Axis
524 **
525 **
526 **/
527 public abstract class Axis {
528 // holds info needed to render a single axis tick
529 private class TickInfo {
530 double position; // along the tick axis in model units
531 String tickLabel;
532 Widget tickWidget;
533 int widthUpperBound; // upperbound on size of an enclosing
534 int heightUpperBound; // 1 x 1 grid (used for centering, etc.)
535 TickInfo(double position, String tickLabel, Widget tickWidget,
536 int widthUpperBound,
537 int heightUpperBound) {
538 this.position = position;
539 this.tickLabel = tickLabel;
540 this.tickWidget = tickWidget;
541 this.widthUpperBound = widthUpperBound;
542 this.heightUpperBound = heightUpperBound;
543 }
544 } // end of class TickInfo
545 protected class AxisLimits {
546 double min; double max; // in user-defined model units
547 AxisLimits(double min, double max) {
548 this.min = min;
549 this.max = max;
550 }
551 boolean equals(AxisLimits al) {
552 boolean result = (al.min == min && al.max == max);
553 return result;
554 }
555 }
556
557 // different initial curr, prev ==> "limits have changed" state
558 private AxisLimits currentLimits = new AxisLimits(
559 Double.MAX_VALUE, -Double.MAX_VALUE);
560 private AxisLimits previousLimits = new AxisLimits(
561 -Double.MAX_VALUE, Double.MAX_VALUE);
562
563 private Widget axisLabel;
564 protected int axisLabelThickness = GChart.NAI;
565 private boolean hasGridlines = false;
566 private int tickCount = DEFAULT_TICK_COUNT;
567 private ArrayList tickInfo = new ArrayList();
568 // axes auto-scale whenever min or max are NaN.
569 protected double axisMax = Double.NaN;
570 protected double axisMin = Double.NaN;
571 // this symbol facilitates rendering of gridlines & axes
572 protected Symbol gridSymbol;
573 protected String tickLabelFontColor = DEFAULT_TICK_LABEL_FONT_COLOR;
574 // In CSS font-size pixels. These define the height of each
575 // character; our code relies on the rule of thumb that
576 // character width is approximately 3/5th this height to
577 // obtain a reasonably tight upper bound on tick label widths.
578 protected int tickLabelFontSize = DEFAULT_TICK_LABEL_FONTSIZE;
579 protected String tickLabelFontStyle = DEFAULT_TICK_LABEL_FONT_STYLE;
580 protected String tickLabelFontWeight = DEFAULT_TICK_LABEL_FONT_WEIGHT;
581
582 protected String tickLabelFormat = DEFAULT_TICK_LABEL_FORMAT;
583 protected int tickLabelThickness = GChart.NAI;
584 protected int ticksPerLabel = 1;
585 protected int ticksPerGridline = 1;
586 protected int tickLength = DEFAULT_TICK_LENGTH;
587
588 // this symbol facilitates rendering of labeled tick-marks
589 protected Symbol tickSymbol;
590 protected int tickThickness = DEFAULT_TICK_THICKNESS;
591 protected WidgetCursor widgetCursor = new WidgetCursor();
592
593
594 // is axis itself visible (has no impact ticks or their labels)
595 boolean axisVisible = true;
596
597 WidgetCursor getWidgetCursor() { return widgetCursor;}
598 /**
599 * Adds a tick on this axis at the specified position.
600 * Note that explicitly adding a single tick via this method
601 * will eliminate any implicitly generated ticks associated with the
602 * <tt>setTickCount</tt> method.
603 * <p>
604 * The label associated with this tick will be generated by
605 * applying the format specified via <tt>setTickLabelFormat</tt>
606 * to the specified position.
607 * <p>
608 * This is a convenience method equivalent to
609 * <tt>addTick(tickPosition, null, GChart.NAI,
610 * GChart.NAI)</tt>. See {@link #addTick(double,String,int,int)
611 * addTick(tickPosition,tickLabel,widthUpperBound,heightUpperBound)}
612 * for details.
613 *
614 * @param tickPosition the position, in model units,
615 * along this axis at which this tick is displayed.
616 * For example, if the axis range goes from 0 to 100,
617 * a tick at position 50 would appear in the middle of
618 * the axis.
619 *
620 * @see #clearTicks clearTicks
621 * @see #addTick(double,String) addTick(double,String)
622 * @see #addTick(double,String,int,int) addTick(double,String,int,int)
623 * @see #addTick(double,Widget,int,int) addTick(double,Widget,int,int)
624 * @see #setTickCount setTickCount
625 * @see #setTickLabelFormat setTickLabelFormat
626 * @see #setTickLabelFontStyle setTickLabelFontStyle
627 * @see #setTickLabelFontColor setTickLabelFontColor
628 * @see #setTickLabelFontWeight setTickLabelFontWeight
629 * @see #setTickLabelFontSize setTickLabelFontSize
630 *
631 */
632 public void addTick(double tickPosition) {
633 addTick(tickPosition, (String) null);
634 }
635 /**
636 * Adds a tick at the specified position with the specified
637 * label on this axis, whose width and height are within
638 * the specified upper-bounds.
639 *
640 * <p>
641 * Note that explicitly adding a single tick via this method
642 * will eliminate any auto-generated ticks associated with the
643 * <tt>setTickCount</tt> method.
644 *
645 * <p>
646 * Use this method to specify unusually spaced
647 * tick marks with labels that do not directly
648 * reflect the position (for example, for a logarithmic axis,
649 * or for a bar chart with special keyword-type labels, or
650 * a time axis that places date and time on two separate lines).
651 *
652 * @param tickPosition the position, in model units, along
653 * this axis at which the tick is displayed.
654 * For example, if the axis range goes from 0 to 1,
655 * a tick at position 0.5 would appear in the middle of
656 * the axis.
657 *
658 * @param tickLabel the label for this tick. HTML is
659 * supported in tick labels, but it must be prefixed by
660 * <tt><html></tt>. See the {@link
661 * Curve.Point#setAnnotationText(String,int,int)
662 * setAnnotationText} method for more information.
663 *
664 * @param widthUpperBound an upper bound on the width of
665 * the text or HTML, in pixels. Use <tt>GChart.NAI</tt> to
666 * get GChart to estimate this width for you. See the
667 * <tt>setAnnotationText</tt> method for more information.
668 *
669 * @param heightUpperBound an upper bound on the height of
670 * the text or HTML, in pixels. Use <tt>GChart.NAI</tt> to
671 * get GChart to estimate this height for you. See the
672 * <tt>setAnnotationText</tt> method for more information.
673 *
674 * @see #clearTicks clearTicks
675 * @see #addTick(double) addTick(double)
676 * @see #addTick(double,String) addTick(double,String)
677 * @see #addTick(double,Widget,int,int) addTick(double,Widget,int,int)
678 * @see #setTickCount setTickCount
679 * @see #setTickLabelFormat setTickLabelFormat
680 * @see #setTickLabelFontSize setTickLabelFontSize
681 * @see #setTickLabelFontStyle setTickLabelFontStyle
682 * @see #setTickLabelFontColor setTickLabelFontColor
683 * @see #setTickLabelFontWeight setTickLabelFontWeight
684 * @see Curve.Point#setAnnotationText(String,int,int)
685 * setAnnotationText
686 * @see Curve.Point#setAnnotationWidget setAnnotationWidget
687 *
688 */
689 public void addTick(double tickPosition, String tickLabel,
690 int widthUpperBound,
691 int heightUpperBound) {
692 plotPanel.invalidateWidgetsAfterCursor(widgetCursor);
693 // position of plot area can depend on size of tick labels
694 plotPanel.plotAreaNeedsUpdate();
695 tickCount = 0; // eliminates any auto-generated ticks
696 tickInfo.add(new TickInfo(tickPosition, tickLabel, null,
697 widthUpperBound,
698 heightUpperBound));
699 }
700
701 /**
702 * Adds a tick at the specified position with the specified
703 * label on this axis.
704 * <p>
705 *
706 * This is a convenience method equivalent to
707 * <tt>addTick(tickPosition, tickLabel, GChart.NAI,
708 * GChart.NAI)</tt>. Most applications can usually just
709 * use this convenience method. See {@link #addTick(double,String,int,int)
710 * addTick(tickPosition,tickLabel,
711 * widthUpperBound,heightUpperBound)} for the fine print.
712 *
713 * @param tickPosition the position, in model units, along
714 * this axis at which the tick is displayed.
715 *
716 * @param tickLabel the plain text or
717 * (<tt><html></tt>-prefixed) HTML defining the tick's
718 * label.
719 *
720 * @see #addTick(double,String,int,int) addTick(double,String,int,int)
721 * @see #addTick(double,Widget) addTick(double,Widget)
722 *
723 */
724 public void addTick(double tickPosition,
725 String tickLabel) {
726 addTick(tickPosition, tickLabel, GChart.NAI, GChart.NAI);
727 }
728
729 /**
730 * Adds a widget-defined tick label at the specified
731 * position, whose width and height are within
732 * the specified upper-bounds.
733 *
734 *
735 * <p>
736 **
737 ** This method is similar to
738 ** <tt>addTick(double,String,int,int)</tt> except that it
739 ** uses a widget, rather than a string, to define the
740 ** tick's label. Although the string-based method is faster
741 ** on first chart rendering, and uses less memory, the
742 ** widget-based method allows you to change the label
743 ** independently of the chart--potentially bypassing (or
744 ** speeding up) expensive chart updates later on.
745 **
746 ** <p>
747 **
748 ** You might use a widget-based tick label to pop up a
749 ** dialog that allows the user to edit the parameters
750 ** defining the axis (min, max, etc.) whenever they click
751 ** on one of the tick labels on that axis, to define
752 ** hovertext that appears when the user mouses over
753 ** a tick label, to use images for your tick labels, etc.
754 **
755 * @param tickPosition the position, in model units, along
756 * this axis at which the tick is displayed.
757 * For example, if the axis range goes from 0 to 1,
758 * a tick at position 0.5 would appear in the middle of
759 * the axis.
760 *
761 * @param tickWidget the label for this tick, as defined
762 * by any GWT Widget.
763 *
764 * @param widthUpperBound an upper bound on the width of
765 * the widget, in pixels. If this and the next
766 * parameter are omitted, GChart will use
767 * <tt>DEFAULT_WIDGET_WIDTH_UPPERBOUND</tt>.
768 *
769 * @param heightUpperBound an upper bound on the height of
770 * the widget, in pixels. If this and the previous
771 * parameter are omitted, GChart will use <tt>
772 * DEFAULT_WIDGET_HEIGHT_UPPERBOUND</tt>
773 *
774 * @see #addTick(double,Widget) addTick(double,Widget)
775 * @see #addTick(double,String,int,int) addTick(double,String,int,int)
776 * @see Curve.Point#setAnnotationWidget setAnnotationWidget
777 * @see #DEFAULT_WIDGET_WIDTH_UPPERBOUND DEFAULT_WIDGET_WIDTH_UPPERBOUND
778 * @see #DEFAULT_WIDGET_HEIGHT_UPPERBOUND DEFAULT_WIDGET_HEIGHT_UPPERBOUND
779 **/
780 public void addTick(double tickPosition,
781 Widget tickWidget,
782 int widthUpperBound,
783 int heightUpperBound) {
784 plotPanel.invalidateWidgetsAfterCursor(widgetCursor);
785 plotPanel.plotAreaNeedsUpdate();
786 // accept "Not an Integer" (because text-based addTick does)
787 if (widthUpperBound == GChart.NAI)
788 widthUpperBound = DEFAULT_WIDGET_WIDTH_UPPERBOUND;
789 if (heightUpperBound == GChart.NAI)
790 heightUpperBound = DEFAULT_WIDGET_HEIGHT_UPPERBOUND;
791 tickCount = 0; // eliminates any auto-generated ticks
792 tickInfo.add(new TickInfo(tickPosition, null, tickWidget,
793 widthUpperBound,
794 heightUpperBound));
795 }
796
797 /**
798 * Adds a Widget-defined tick label at the specified
799 * position. Convenience method equivalent to
800 * <tt>addTick(tickPosition, tickWidget,
801 * DEFAULT_WIDGET_WIDTH_UPPERBOUND,
802 * DEFAULT_WIDGET_HEIGHT_UPPERBOUND)</tt>.
803 *
804 * @param tickPosition the position, in model units, along
805 * this axis at which the tick is displayed.
806 * For example, if the axis range goes from 0 to 1,
807 * a tick at position 0.5 would appear in the middle of
808 * the axis.
809 *
810 * @param tickWidget the label for this tick, as defined
811 * by any GWT Widget.
812 *
813 * @see #addTick(double,Widget,int,int)
814 * addTick(double,Widget,int,int)
815 *
816 */
817 public void addTick(double tickPosition,
818 Widget tickWidget) {
819 addTick(tickPosition, tickWidget,
820 DEFAULT_WIDGET_WIDTH_UPPERBOUND,
821 DEFAULT_WIDGET_HEIGHT_UPPERBOUND);
822 }
823 /**
824 *
825 * Removes all ticks from this axis. Specifically,
826 * erases any ticks that were explicitly specified via
827 * <tt>addTick</tt>, and also sets the tick count to 0.
828 * <p>
829 *
830 * @see #setTickCount setTickCount
831 * @see #addTick(double) addTick(double)
832 * @see #addTick(double,String) addTick(double,String)
833 * @see #addTick(double,String,int,int) addTick(double,String,int,int)
834 * @see #addTick(double,Widget) addTick(double,Widget)
835 * @see #addTick(double,Widget,int,int) addTick(double,Widget,int,int)
836 *
837 */
838 public void clearTicks() {
839 plotPanel.invalidateWidgetsAfterCursor(widgetCursor);
840 plotPanel.plotAreaNeedsUpdate();
841 tickCount = 0;
842 tickInfo.clear();
843 }
844 // these are used in formatting tick positions into tick labels:
845 private NumberFormat numberFormat =
846 NumberFormat.getFormat(DEFAULT_TICK_LABEL_FORMAT);
847 private DateTimeFormat dateFormat =
848 DateTimeFormat.getShortDateTimeFormat();
849 private final int NUMBER_FORMAT_TYPE = 0;
850 private final int DATE_FORMAT_TYPE = 1;
851 private final int LOG10INVERSE_FORMAT_TYPE = 2;
852 private final int LOG2INVERSE_FORMAT_TYPE = 3;
853 private int tickLabelFormatType = NUMBER_FORMAT_TYPE;
854 /**
855 *
856 * Applies this axis' tick label format to format a given value.
857 *
858 * @return the value formated as per this axis' currently specified
859 * tick label format.
860 *
861 * @see #setTickLabelFormat(String) setTickLabelFormat
862 *
863 */
864 public String formatNumberAsTickLabel(double value) {
865 String result = null;
866 switch (tickLabelFormatType) {
867 case DATE_FORMAT_TYPE:
868 Date transDate = new Date((long) value);
869 result = dateFormat.format(transDate);
870 break;
871 case LOG10INVERSE_FORMAT_TYPE:
872 value = Math.pow(10., value);
873 result = numberFormat.format(value);
874 break;
875 case LOG2INVERSE_FORMAT_TYPE:
876 value = Math.pow(2., value);
877 result = numberFormat.format(value);
878 break;
879 default:
880 result = numberFormat.format(value);
881 break;
882 }
883
884 return result;
885 }
886
887 /** Returns the previously specified label of this axis.
888 **
889 ** @return the Widget used as the label of this axis
890 **
891 ** @see #setAxisLabel setAxisLabel
892 **
893 */
894 public Widget getAxisLabel() {
895 return axisLabel;
896 }
897
898 /** Returns the thickness of the axis-label-holding region
899 ** adjacent to the region allocated for this axis' tick labels.
900 ** <p>
901 **
902 ** Note that if the axis label is <tt>null</tt> (the
903 ** default) then this method always returns 0, since
904 ** in that case no rectangular region will be allocated
905 ** for the axis label.
906 ** <p>
907 **
908 ** @return the thickness of the axis-label-holding
909 ** region, in pixels.
910 **
911 ** @see #setAxisLabelThickness setAxisLabelThickness
912 **
913 */
914 public int getAxisLabelThickness() {
915 int result = 0;
916 // Base class implementation is for y axes (x-axis will override).
917 final int EXTRA_CHARWIDTH = 2; // 1-char padding on each side
918 final int DEF_CHARWIDTH = 1; // when widget has no text
919 if (null == getAxisLabel())
920 result = 0;
921 else if (GChart.NAI != axisLabelThickness)
922 result = axisLabelThickness;
923 else if (getAxisLabel() instanceof HasHTML) {
924 int charWidth = htmlWidth(
925 ((HasHTML) (getAxisLabel())).getHTML());
926 result = (int) Math.round((charWidth + EXTRA_CHARWIDTH) *
927 getTickLabelFontSize() *
928 TICK_CHARWIDTH_TO_FONTSIZE_LOWERBOUND);
929 }
930 else if (getAxisLabel() instanceof HasText) {
931 String text = ((HasText) (getAxisLabel())).getText();
932 result = (int) Math.round((EXTRA_CHARWIDTH +
933 ((null==text)?0:text.length())) *
934 getTickLabelFontSize() *
935 TICK_CHARWIDTH_TO_FONTSIZE_LOWERBOUND);
936 }
937 else // non-text widget. Not a clue, just use def width
938 result = (int) Math.round(
939 (DEF_CHARWIDTH + EXTRA_CHARWIDTH) *
940 getTickLabelFontSize() *
941 TICK_CHARWIDTH_TO_FONTSIZE_LOWERBOUND);
942 return result;
943 }
944 /**
945 ** Returns the maximum value displayed on this axis.
946 ** If the explicitly specified maximum value is
947 ** undefined (<tt>Double.NaN</tt>) the maximum value returned
948 ** by this function is calculated as the maximum of
949 ** all of the values either displayed on this axis via
950 ** points on a curve, or explicitly specified via tick
951 ** positions.
952 **
953 ** @return maximum value visible on this axis, in
954 ** "model units" (arbitrary, application-specific,
955 ** units)
956 **
957 ** @see #setAxisMax setAxisMax
958 ** @see #getDataMin getDataMin
959 ** @see #getDataMax getDataMax
960 **/
961 public double getAxisMax() {
962
963 if (!(axisMax!=axisMax)) { // x!=x is a faster isNaN
964 return axisMax;
965 }
966 else if (tickCount > 0) {
967 return getDataMax();
968 }
969 else {
970 return Math.max(getDataMax(), getTickMax());
971 }
972 }
973 /**
974 **
975 ** Returns the minimum value displayed on this axis.
976 ** If the minimum value is undefined (<tt>Double.NaN</tt>) the
977 ** minimum value returned by this function is the
978 ** minimum of all of the values either displayed on
979 ** this axis via points on a curve, or explicitly specified
980 ** via tick positions.
981 **
982 ** @return minimum value visible on this axis, in
983 ** "model units" (arbitrary, application-specific,
984 ** units)
985 **
986 ** @see #setAxisMin setAxisMin
987 **/
988 public double getAxisMin() {
989 if (!(axisMin!=axisMin)) { // x!=x is a faster isNaN
990 return axisMin; // explicitly set
991 }
992 else if (tickCount > 0) {
993 return getDataMin();
994 }
995 else {
996 return Math.min(getDataMin(), getTickMin());
997 }
998 }
999
1000 /** Is axis line visible on the chart? Note that
1001 ** this property only determines the visibility of the axis line
1002 ** itself. It does not control the visibility of the
1003 ** tick marks or tick labels along this axis.
1004 ** <p>
1005 **
1006 ** @return true if the axis line is visible, false otherwise.
1007 **
1008 ** @see #setAxisVisible setAxisVisible
1009 **
1010 **/
1011 public boolean getAxisVisible() {
1012 return axisVisible;
1013 }
1014
1015
1016
1017 /** Returns the maximum data value associated with values
1018 ** represented on this axis. For example, for the left
1019 ** y-axis, this would be the largest y-value of all points
1020 ** contained in curves that are displayed on the left y-axis.
1021 **
1022 ** @return the maximum value associated with values
1023 ** mapped onto this axis.
1024 **
1025 ** @see #getDataMin getDataMin
1026 ** @see #getAxisMax getAxisMax
1027 ** @see #getAxisMin getAxisMin
1028 **
1029 */
1030 public abstract double getDataMax();
1031 /** Returns the minimum data value associated with values
1032 ** represented on this axis. For example, for the left
1033 ** y-axis, this would be the smallest y-value of all points
1034 ** contained in curves that are displayed on the left y-axis.
1035 **
1036 ** @return the minumum value associated with values
1037 ** mapped onto this axis.
1038 **
1039 ** @see #getDataMax getDataMax
1040 ** @see #getAxisMax getAxisMax
1041 ** @see #getAxisMin getAxisMax
1042 **
1043 */
1044 public abstract double getDataMin();
1045
1046 /** Returns the gridline setting previously made with
1047 ** <tt>setHasGridlines</tt>.
1048 **
1049 ** @return true if gridlines have been enabled, false if not.
1050 **
1051 ** @see #setHasGridlines setHasGridlines
1052 **
1053 **/
1054 public boolean getHasGridlines() {
1055 return hasGridlines;
1056 }
1057 /**
1058 ** Returns the number of ticks on this axis.
1059 **
1060 ** @return the number of ticks on this axis.
1061 **
1062 ** @see #setTickCount setTickCount
1063 ** @see #addTick(double) addTick(double)
1064 ** @see #addTick(double,String) addTick(double,String)
1065 ** @see #addTick(double,String,int,int) addTick(double,String,int,int)
1066 ** @see #addTick(double,Widget) addTick(double,Widget)
1067 ** @see #addTick(double,Widget,int,int) addTick(double,Widget,int,int)
1068 ** @see #clearTicks clearTicks
1069 **
1070 **/
1071 public int getTickCount() {
1072 if (tickCount == 0)
1073 return tickInfo.size();
1074 else
1075 return tickCount;
1076 }
1077 /**
1078 ** Returns the CSS font-weight specification to be used
1079 ** by this axis' tick labels.
1080 **
1081 ** @return font-weight of this axis' tick labels
1082 **
1083 ** @see #setTickLabelFontWeight setTickLabelFontWeight
1084 **/
1085 public String getTickLabelFontWeight() {
1086 return tickLabelFontWeight;
1087 }
1088 /**
1089 ** Returns the color of the font used to display the
1090 ** text of the tick labels on this axis.
1091 **
1092 **
1093 ** @return CSS color string defining the color of the text of
1094 ** the tick labels for this axis.
1095 **
1096 ** @see #setTickLabelFontColor setTickLabelFontColor
1097 **
1098 ** @see #DEFAULT_TICK_LABEL_FONT_COLOR DEFAULT_TICK_LABEL_FONT_COLOR
1099 **
1100 **
1101 **
1102 **/
1103 public String getTickLabelFontColor() {
1104 return tickLabelFontColor;
1105 }
1106
1107 /**
1108 ** Returns the font-style of the font used to render tick
1109 ** labels on this axis (typically either "italic" or
1110 ** "normal")
1111 **
1112 ** @return the CSS font-style in which tick labels of this axis
1113 ** are rendered.
1114 **
1115 ** @see #setTickLabelFontStyle setTickLabelFontStyle
1116 **/
1117 public String getTickLabelFontStyle() {
1118 return tickLabelFontStyle;
1119 }
1120 /** Returns the font size, in pixels, used for tick labels
1121 ** on this axis.
1122 **
1123 ** @return the tick label font size in pixels
1124 **
1125 ** @see #setTickLabelFontSize setTickLabelFontSize
1126 **/
1127 public int getTickLabelFontSize() {
1128 return tickLabelFontSize;
1129 }
1130
1131 /**
1132 ** Returns the tick label numeric format string for this
1133 ** axis.
1134 **
1135 ** @return numeric format used to generate tick labels.
1136 **
1137 ** @see #setTickLabelFormat setTickLabelFormat
1138 **
1139 **/
1140 public String getTickLabelFormat() {
1141 return tickLabelFormat;
1142 }
1143 /** Returns the thickness of the band adjacent to
1144 ** this axis that GChart will
1145 ** allocate to hold this axis' tick labels.
1146 ** <p>
1147 **
1148 ** @return width of band, in pixels, GChart will reserve
1149 ** for this axis' tick labels.
1150 **
1151 ** @see #setTickLabelThickness setTickLabelThickness
1152 **
1153 **/
1154 public int getTickLabelThickness() {
1155 int maxLength = 0;
1156 int result;
1157 if (tickLabelThickness != GChart.NAI)
1158 result = tickLabelThickness;
1159 else { // use an heuristic to estimate thickness
1160 maybePopulateTicks();
1161 for (int i=0; i < tickInfo.size(); i++) {
1162 String tt = getTickText(i);
1163 if (null != tt)
1164 maxLength = Math.max(maxLength,
1165 Annotation.getNumberOfCharsWide(tt));
1166 }
1167 result = (int) Math.round(maxLength * tickLabelFontSize *
1168 TICK_CHARWIDTH_TO_FONTSIZE_LOWERBOUND);
1169 }
1170 return result;
1171 }
1172
1173
1174 /**
1175 ** Returns the ratio of the number of ticks to the number of
1176 ** ticks that have an associated gridline.
1177 **
1178 ** @return number of ticks per gridline for this axis
1179 **
1180 ** @see #setTicksPerGridline setTicksPerGridline
1181 **
1182 **/
1183 public int getTicksPerGridline() {
1184 return ticksPerGridline;
1185 }
1186 /**
1187 ** Returns the ratio of the number of ticks to the number of
1188 ** labeled ticks.
1189 **
1190 ** @return number of ticks per label.
1191 **
1192 ** @see #setTicksPerLabel setTicksPerLabel
1193 **
1194 **/
1195 public int getTicksPerLabel() {
1196 return ticksPerLabel;
1197 }
1198
1199 /**
1200 * Returns the length of ticks for this axis.
1201 *
1202 * @return the length of this axis' ticks, in pixels.
1203 *
1204 * @see #setTickLength setTickLength
1205 */
1206 public int getTickLength() {
1207 return tickLength;
1208 }
1209
1210 /**
1211 * Returns the thickness of ticks for this axis.
1212 *
1213 * @return the thickness of this axis' ticks, in pixels.
1214 *
1215 * @see #setTickThickness setTickThickness
1216 * @see #getTickLength getTickLength
1217 */
1218 public int getTickThickness() {
1219 return tickThickness;
1220 }
1221
1222 /** Specifies the label of this axis.
1223 ** <p>
1224 **
1225 ** This label will be positioned just outside of, and
1226 ** centered lengthwise on, the region adjacent to
1227 ** this axis that GChart reserves for this axis' tick labels.
1228 **
1229 ** @param axisLabel a Widget to use as the label of this axis.
1230 **
1231 ** @see #getAxisLabel getAxisLabel
1232 ** @see #setTickLabelThickness setTickLabelThickness
1233 ** @see #setAxisLabelThickness setAxisLabelThickness
1234 **
1235 */
1236
1237 public void setAxisLabel(Widget axisLabel) {
1238 this.axisLabel = axisLabel;
1239 GChart.this.chartDecorationsChanged = true;
1240 }
1241
1242 /**
1243 * Convenience method equivalent to
1244 * <tt>setAxisLabel(new HTML(html))</tt>
1245 *
1246 * @param html HTML text used to define the axis label
1247 *
1248 * @see #setAxisLabel(Widget) setAxisLabel(Widget)
1249 */
1250 public void setAxisLabel(String html) {
1251 setAxisLabel(new HTML(html));
1252 }
1253
1254 /** Sets the thickness of the axis-label-holding region
1255 ** adjacent to the region allocated for tick labels.<p>
1256 **
1257 ** The axis label widget will be centered in this region.
1258 ** Choose a thickness large enough to hold the largest
1259 ** font size you want users to be able to zoom up to
1260 ** without the axis label spilling over into
1261 ** adjacent regions.
1262 ** <p>
1263 **
1264 ** If the axis label thickness is <tt>GChart.NAI</tt> (the
1265 ** default), and the widget defining the axis label
1266 ** implements <tt>HasHTML</tt> (or <tt>HasText</tt>) then
1267 ** GChart uses a thickness based on the estimated number of
1268 ** non-tag characters in the first <tt><br></tt> or
1269 ** <tt><li></tt>
1270 ** delimited line for y-axis labels, and based on the
1271 ** estimated number of (<tt><br></tt> or
1272 ** <tt><li></tt> delimited)
1273 ** text lines for x-axis labels.<p>
1274 **
1275 ** Note that if the axis label is <tt>null</tt> (its
1276 ** default setting) then no space is allocated for the axis
1277 ** label, regardless of this thickness setting.
1278 ** <p>
1279 **
1280 ** @param thickness the thickness of the axis-label-holding
1281 ** region, in pixels, or <tt>GChart.NAI</tt> to use
1282 ** GChart's character-based default thickness estimates.
1283 **
1284 ** @see #getAxisLabelThickness getAxisLabelThickness
1285 ** @see #setAxisLabel setAxisLabel
1286 */
1287 public void setAxisLabelThickness(int thickness) {
1288 axisLabelThickness = thickness;
1289 GChart.this.chartDecorationsChanged = true;
1290 }
1291
1292 /**
1293 ** Specifies the maximum value visible on this axis.
1294 ** <p>
1295 **
1296 ** Points with associated coordinates greater than this
1297 ** value will be clipped unless the chart's
1298 ** <tt>showOffChartPoints</tt> property is <tt>true</tt>.
1299 **
1300 ** <p>
1301 **
1302 ** If <tt>Double.NaN</tt> is specified, this maximum
1303 ** is auto-determined as described in <tt>getAxisMax</tt>.
1304 **
1305 ** <p> <i>Performance tip:</i> Using auto-determined axis
1306 ** limits (via <tt>Double.NaN</tt>) forces GChart to
1307 ** re-render the axis every time you call
1308 ** <tt>GChart.update</tt>. When your axis limits don't
1309 ** change between updates, these (often expensive)
1310 ** re-renderings can be avoided by using explicitly
1311 ** specified axis limits on every axis. <p>
1312 **
1313 ** @param max maximum value visible on this axis, in "model units"
1314 ** (arbitrary, application-specific, units) or <tt>Double.NaN</tt>
1315 ** (the default value) to use an auto-determined maximum.
1316 **
1317 ** @see #getAxisMax getAxisMax
1318 ** @see #getDataMin getDataMin
1319 ** @see #getDataMax getDataMax
1320 ** @see GChart#setShowOffChartPoints setShowOffChartPoints
1321 **
1322 **/
1323 public void setAxisMax(double max) {
1324 plotPanel.invalidateWidgetsAfterCursor(widgetCursor);
1325 // max can change axis label width ==> changes position of plot area
1326 plotPanel.plotAreaNeedsUpdate();
1327 this.axisMax = max;
1328 }
1329 /**
1330 ** Specifies the minimum value of this axis.
1331 ** <p>
1332 **
1333 ** Points with associated coordinates less than this
1334 ** value will be clipped unless the chart's
1335 ** <tt>showOffChartPoints</tt> property is <tt>true</tt>.
1336 ** <p>
1337 **
1338 ** If <tt>Double.NaN</tt> is specified, this minimum
1339 ** is auto-determined as described in <tt>getAxisMin</tt>.
1340 **
1341 ** <p> <i>Performance tip:</i> Using auto-de