Source for org.jfree.chart.axis.CategoryLabelPositions

   1: /* ===========================================================
   2:  * JFreeChart : a free chart library for the Java(tm) platform
   3:  * ===========================================================
   4:  *
   5:  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
   6:  *
   7:  * Project Info:  http://www.jfree.org/jfreechart/index.html
   8:  *
   9:  * This library is free software; you can redistribute it and/or modify it 
  10:  * under the terms of the GNU Lesser General Public License as published by 
  11:  * the Free Software Foundation; either version 2.1 of the License, or 
  12:  * (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but 
  15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  16:  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
  17:  * License for more details.
  18:  *
  19:  * You should have received a copy of the GNU Lesser General Public
  20:  * License along with this library; if not, write to the Free Software
  21:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
  22:  * USA.  
  23:  *
  24:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
  25:  * in the United States and other countries.]
  26:  *
  27:  * ---------------------------
  28:  * CategoryLabelPositions.java
  29:  * ---------------------------
  30:  * (C) Copyright 2004, 2005, by Object Refinery Limited and Contributors.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   -;
  34:  *
  35:  * $Id: CategoryLabelPositions.java,v 1.5.2.1 2005/10/25 20:37:34 mungady Exp $
  36:  *
  37:  * Changes
  38:  * -------
  39:  * 06-Jan-2004 : Version 1 (DG);
  40:  * 17-Feb-2004 : Added equals() method (DG);
  41:  * 05-Nov-2004 : Adjusted settings for UP_90 and DOWN_90 (DG);
  42:  *
  43:  */
  44: 
  45: package org.jfree.chart.axis;
  46: 
  47: import java.io.Serializable;
  48: 
  49: import org.jfree.text.TextBlockAnchor;
  50: import org.jfree.ui.RectangleAnchor;
  51: import org.jfree.ui.RectangleEdge;
  52: import org.jfree.ui.TextAnchor;
  53: 
  54: /**
  55:  * Records the label positions for a category axis.  Instances of this class 
  56:  * are immutable.
  57:  */
  58: public class CategoryLabelPositions implements Serializable {
  59: 
  60:     /** For serialization. */
  61:     private static final long serialVersionUID = -8999557901920364580L;
  62:     
  63:     /** STANDARD category label positions. */
  64:     public static final CategoryLabelPositions 
  65:         STANDARD = new CategoryLabelPositions(
  66:             new CategoryLabelPosition(
  67:                 RectangleAnchor.BOTTOM, TextBlockAnchor.BOTTOM_CENTER
  68:             ), // TOP
  69:             new CategoryLabelPosition(
  70:                 RectangleAnchor.TOP, TextBlockAnchor.TOP_CENTER
  71:             ), // BOTTOM
  72:             new CategoryLabelPosition(
  73:                 RectangleAnchor.RIGHT, TextBlockAnchor.CENTER_RIGHT, 
  74:                 CategoryLabelWidthType.RANGE, 0.30f
  75:             ), // LEFT
  76:             new CategoryLabelPosition(
  77:                 RectangleAnchor.LEFT, TextBlockAnchor.CENTER_LEFT, 
  78:                 CategoryLabelWidthType.RANGE, 0.30f
  79:             ) // RIGHT
  80:         );
  81:     
  82:     /** UP_90 category label positions. */
  83:     public static final CategoryLabelPositions 
  84:         UP_90 = new CategoryLabelPositions(
  85:             new CategoryLabelPosition(
  86:                 RectangleAnchor.BOTTOM, TextBlockAnchor.CENTER_LEFT, 
  87:                 TextAnchor.CENTER_LEFT, -Math.PI / 2.0,
  88:                 CategoryLabelWidthType.RANGE, 0.30f
  89:             ), // TOP
  90:             new CategoryLabelPosition(
  91:                 RectangleAnchor.TOP, TextBlockAnchor.CENTER_RIGHT, 
  92:                 TextAnchor.CENTER_RIGHT, -Math.PI / 2.0,
  93:                 CategoryLabelWidthType.RANGE, 0.30f
  94:             ), // BOTTOM
  95:             new CategoryLabelPosition(
  96:                 RectangleAnchor.RIGHT, TextBlockAnchor.BOTTOM_CENTER, 
  97:                 TextAnchor.BOTTOM_CENTER, -Math.PI / 2.0,
  98:                 CategoryLabelWidthType.CATEGORY, 0.9f
  99:             ), // LEFT
 100:             new CategoryLabelPosition(
 101:                 RectangleAnchor.LEFT, TextBlockAnchor.TOP_CENTER, 
 102:                 TextAnchor.TOP_CENTER, -Math.PI / 2.0,
 103:                 CategoryLabelWidthType.CATEGORY, 0.90f
 104:             ) // RIGHT
 105:         );
 106:     
 107:     /** DOWN_90 category label positions. */
 108:     public static final CategoryLabelPositions 
 109:         DOWN_90 = new CategoryLabelPositions(
 110:             new CategoryLabelPosition(
 111:                 RectangleAnchor.BOTTOM, TextBlockAnchor.CENTER_RIGHT, 
 112:                 TextAnchor.CENTER_RIGHT, Math.PI / 2.0,
 113:                 CategoryLabelWidthType.RANGE, 0.30f
 114:             ), // TOP
 115:             new CategoryLabelPosition(
 116:                 RectangleAnchor.TOP, TextBlockAnchor.CENTER_LEFT, 
 117:                 TextAnchor.CENTER_LEFT, Math.PI / 2.0,
 118:                 CategoryLabelWidthType.RANGE, 0.30f
 119:             ), // BOTTOM
 120:             new CategoryLabelPosition(
 121:                 RectangleAnchor.RIGHT, TextBlockAnchor.TOP_CENTER, 
 122:                 TextAnchor.TOP_CENTER, Math.PI / 2.0,
 123:                 CategoryLabelWidthType.CATEGORY, 0.90f
 124:             ), // LEFT
 125:             new CategoryLabelPosition(
 126:                 RectangleAnchor.LEFT, TextBlockAnchor.BOTTOM_CENTER, 
 127:                 TextAnchor.BOTTOM_CENTER, Math.PI / 2.0,
 128:                 CategoryLabelWidthType.CATEGORY, 0.90f
 129:             ) // RIGHT
 130:         );
 131:     
 132:     /** UP_45 category label positions. */
 133:     public static final CategoryLabelPositions UP_45 
 134:         = createUpRotationLabelPositions(Math.PI / 4.0);
 135:     
 136:     /** DOWN_45 category label positions. */
 137:     public static final CategoryLabelPositions DOWN_45 
 138:         = createDownRotationLabelPositions(Math.PI / 4.0);
 139:     
 140:     /**
 141:      * Creates a new instance where the category labels angled upwards by the 
 142:      * specified amount.
 143:      * 
 144:      * @param angle  the rotation angle (should be < Math.PI / 2.0).
 145:      * 
 146:      * @return A category label position specification.
 147:      */
 148:     public static CategoryLabelPositions createUpRotationLabelPositions(
 149:             double angle) {
 150:         return new CategoryLabelPositions(
 151:             new CategoryLabelPosition(
 152:                 RectangleAnchor.BOTTOM, TextBlockAnchor.BOTTOM_LEFT, 
 153:                 TextAnchor.BOTTOM_LEFT, -angle,
 154:                 CategoryLabelWidthType.RANGE, 0.50f
 155:             ), // TOP
 156:             new CategoryLabelPosition(
 157:                 RectangleAnchor.TOP, TextBlockAnchor.TOP_RIGHT, 
 158:                 TextAnchor.TOP_RIGHT, -angle,
 159:                 CategoryLabelWidthType.RANGE, 0.50f
 160:             ), // BOTTOM
 161:             new CategoryLabelPosition(
 162:                 RectangleAnchor.RIGHT, TextBlockAnchor.BOTTOM_RIGHT, 
 163:                 TextAnchor.BOTTOM_RIGHT, -angle,
 164:                 CategoryLabelWidthType.RANGE, 0.50f
 165:             ), // LEFT
 166:             new CategoryLabelPosition(
 167:                 RectangleAnchor.LEFT, TextBlockAnchor.TOP_LEFT, 
 168:                 TextAnchor.TOP_LEFT, -angle,
 169:                 CategoryLabelWidthType.RANGE, 0.50f
 170:             ) // RIGHT
 171:         );
 172:     }
 173:     
 174:     /**
 175:      * Creates a new instance where the category labels angled downwards by the
 176:      * specified amount.
 177:      * 
 178:      * @param angle  the rotation angle (should be < Math.PI / 2.0).
 179:      * 
 180:      * @return A category label position specification.
 181:      */
 182:     public static CategoryLabelPositions createDownRotationLabelPositions(
 183:             double angle) {
 184:         return new CategoryLabelPositions(
 185:             new CategoryLabelPosition(
 186:                 RectangleAnchor.BOTTOM, TextBlockAnchor.BOTTOM_RIGHT, 
 187:                 TextAnchor.BOTTOM_RIGHT, angle,
 188:                 CategoryLabelWidthType.RANGE, 0.50f
 189:             ), // TOP
 190:             new CategoryLabelPosition(
 191:                 RectangleAnchor.TOP, TextBlockAnchor.TOP_LEFT, 
 192:                 TextAnchor.TOP_LEFT, angle,
 193:                 CategoryLabelWidthType.RANGE, 0.50f
 194:             ), // BOTTOM
 195:             new CategoryLabelPosition(
 196:                 RectangleAnchor.RIGHT, TextBlockAnchor.TOP_RIGHT, 
 197:                 TextAnchor.TOP_RIGHT, angle,
 198:                 CategoryLabelWidthType.RANGE, 0.50f
 199:             ), // LEFT
 200:             new CategoryLabelPosition(
 201:                 RectangleAnchor.LEFT, TextBlockAnchor.BOTTOM_LEFT, 
 202:                 TextAnchor.BOTTOM_LEFT, angle,
 203:                 CategoryLabelWidthType.RANGE, 0.50f
 204:             ) // RIGHT
 205:         );
 206:     }
 207:     
 208:     /** 
 209:      * The label positioning details used when an axis is at the top of a 
 210:      * chart. 
 211:      */
 212:     private CategoryLabelPosition positionForAxisAtTop;
 213:     
 214:     /** 
 215:      * The label positioning details used when an axis is at the bottom of a 
 216:      * chart. 
 217:      */
 218:     private CategoryLabelPosition positionForAxisAtBottom;
 219:     
 220:     /** 
 221:      * The label positioning details used when an axis is at the left of a 
 222:      * chart. 
 223:      */
 224:     private CategoryLabelPosition positionForAxisAtLeft;
 225:     
 226:     /** 
 227:      * The label positioning details used when an axis is at the right of a 
 228:      * chart. 
 229:      */
 230:     private CategoryLabelPosition positionForAxisAtRight;
 231:  
 232:     /**
 233:      * Default constructor.
 234:      */
 235:     public CategoryLabelPositions() {
 236:         this.positionForAxisAtTop = new CategoryLabelPosition();
 237:         this.positionForAxisAtBottom = new CategoryLabelPosition();
 238:         this.positionForAxisAtLeft = new CategoryLabelPosition();
 239:         this.positionForAxisAtRight = new CategoryLabelPosition();
 240:     }
 241:     
 242:     /**
 243:      * Creates a new position specification.
 244:      * 
 245:      * @param top  the label position info used when an axis is at the top 
 246:      *             (<code>null</code> not permitted).
 247:      * @param bottom  the label position info used when an axis is at the 
 248:      *                bottom (<code>null</code> not permitted).
 249:      * @param left  the label position info used when an axis is at the left 
 250:      *              (<code>null</code> not permitted).
 251:      * @param right  the label position info used when an axis is at the right 
 252:      *               (<code>null</code> not permitted).
 253:      */
 254:     public CategoryLabelPositions(CategoryLabelPosition top,
 255:                                   CategoryLabelPosition bottom,
 256:                                   CategoryLabelPosition left,
 257:                                   CategoryLabelPosition right) {
 258:         
 259:         if (top == null) {
 260:             throw new IllegalArgumentException("Null 'top' argument.");
 261:         }
 262:         if (bottom == null) {
 263:             throw new IllegalArgumentException("Null 'bottom' argument.");
 264:         }
 265:         if (left == null) {
 266:             throw new IllegalArgumentException("Null 'left' argument.");
 267:         }
 268:         if (right == null) {
 269:             throw new IllegalArgumentException("Null 'right' argument.");
 270:         }
 271:         
 272:         this.positionForAxisAtTop = top;
 273:         this.positionForAxisAtBottom = bottom;
 274:         this.positionForAxisAtLeft = left;
 275:         this.positionForAxisAtRight = right;
 276:     
 277:     }
 278:     
 279:     /**
 280:      * Returns the category label position specification for an axis at the 
 281:      * given location.
 282:      * 
 283:      * @param edge  the axis location.
 284:      * 
 285:      * @return The category label position specification.
 286:      */
 287:     public CategoryLabelPosition getLabelPosition(RectangleEdge edge) {
 288:         CategoryLabelPosition result = null;
 289:         if (edge == RectangleEdge.TOP) {
 290:             result = this.positionForAxisAtTop;
 291:         }
 292:         else if (edge == RectangleEdge.BOTTOM) {
 293:             result = this.positionForAxisAtBottom;
 294:         }
 295:         else if (edge == RectangleEdge.LEFT) {
 296:             result = this.positionForAxisAtLeft;
 297:         }
 298:         else if (edge == RectangleEdge.RIGHT) {
 299:             result = this.positionForAxisAtRight;
 300:         }
 301:         return result;
 302:     }
 303:     
 304:     /**
 305:      * Returns a new instance based on an existing instance but with the top 
 306:      * position changed.
 307:      * 
 308:      * @param base  the base (<code>null</code> not permitted).
 309:      * @param top  the top position (<code>null</code> not permitted).
 310:      * 
 311:      * @return A new instance (never <code>null</code>).
 312:      */
 313:     public static CategoryLabelPositions replaceTopPosition(
 314:             CategoryLabelPositions base, CategoryLabelPosition top) {
 315:         
 316:         if (base == null) {
 317:             throw new IllegalArgumentException("Null 'base' argument.");
 318:         }
 319:         if (top == null) {
 320:             throw new IllegalArgumentException("Null 'top' argument.");
 321:         }
 322:         
 323:         return new CategoryLabelPositions(
 324:             top, 
 325:             base.getLabelPosition(RectangleEdge.BOTTOM),
 326:             base.getLabelPosition(RectangleEdge.LEFT),
 327:             base.getLabelPosition(RectangleEdge.RIGHT)
 328:         );
 329:     }
 330:     
 331:     /**
 332:      * Returns a new instance based on an existing instance but with the bottom
 333:      * position changed.
 334:      * 
 335:      * @param base  the base (<code>null</code> not permitted).
 336:      * @param bottom  the bottom position (<code>null</code> not permitted).
 337:      * 
 338:      * @return A new instance (never <code>null</code>).
 339:      */
 340:     public static CategoryLabelPositions replaceBottomPosition(
 341:             CategoryLabelPositions base, CategoryLabelPosition bottom) {
 342:         
 343:         if (base == null) {
 344:             throw new IllegalArgumentException("Null 'base' argument.");
 345:         }
 346:         if (bottom == null) {
 347:             throw new IllegalArgumentException("Null 'bottom' argument.");
 348:         }
 349:         
 350:         return new CategoryLabelPositions(
 351:             base.getLabelPosition(RectangleEdge.TOP),
 352:             bottom,
 353:             base.getLabelPosition(RectangleEdge.LEFT),
 354:             base.getLabelPosition(RectangleEdge.RIGHT)
 355:         );
 356:     }
 357:     
 358:     /**
 359:      * Returns a new instance based on an existing instance but with the left 
 360:      * position changed.
 361:      * 
 362:      * @param base  the base (<code>null</code> not permitted).
 363:      * @param left  the left position (<code>null</code> not permitted).
 364:      * 
 365:      * @return A new instance (never <code>null</code>).
 366:      */
 367:     public static CategoryLabelPositions replaceLeftPosition(
 368:             CategoryLabelPositions base, CategoryLabelPosition left) {
 369:         
 370:         if (base == null) {
 371:             throw new IllegalArgumentException("Null 'base' argument.");
 372:         }
 373:         if (left == null) {
 374:             throw new IllegalArgumentException("Null 'left' argument.");
 375:         }
 376:         
 377:         return new CategoryLabelPositions(
 378:             base.getLabelPosition(RectangleEdge.TOP),
 379:             base.getLabelPosition(RectangleEdge.BOTTOM),
 380:             left,
 381:             base.getLabelPosition(RectangleEdge.RIGHT)
 382:         );
 383:     }
 384:     
 385:     /**
 386:      * Returns a new instance based on an existing instance but with the right 
 387:      * position changed.
 388:      * 
 389:      * @param base  the base (<code>null</code> not permitted).
 390:      * @param right  the right position (<code>null</code> not permitted).
 391:      * 
 392:      * @return A new instance (never <code>null</code>).
 393:      */
 394:     public static CategoryLabelPositions replaceRightPosition(
 395:             CategoryLabelPositions base, CategoryLabelPosition right) {
 396:         
 397:         if (base == null) {
 398:             throw new IllegalArgumentException("Null 'base' argument.");
 399:         }
 400:         if (right == null) {
 401:             throw new IllegalArgumentException("Null 'right' argument.");
 402:         }
 403:         
 404:         return new CategoryLabelPositions(
 405:             base.getLabelPosition(RectangleEdge.TOP),
 406:             base.getLabelPosition(RectangleEdge.BOTTOM),
 407:             base.getLabelPosition(RectangleEdge.LEFT),
 408:             right
 409:         );
 410:     }
 411:     
 412:     /**
 413:      * Returns <code>true</code> if this object is equal to the specified 
 414:      * object, and <code>false</code> otherwise.
 415:      *
 416:      * @param obj  the other object.
 417:      *
 418:      * @return A boolean.
 419:      */
 420:     public boolean equals(Object obj) {
 421: 
 422:         if (this == obj) {
 423:             return true;
 424:         }
 425:         if (!(obj instanceof CategoryLabelPositions)) {
 426:             return false;
 427:         }
 428: 
 429:         CategoryLabelPositions that = (CategoryLabelPositions) obj;
 430:         if (!this.positionForAxisAtTop.equals(that.positionForAxisAtTop)) {
 431:             return false;
 432:         }
 433:         if (!this.positionForAxisAtBottom.equals(
 434:                 that.positionForAxisAtBottom)) {
 435:             return false;
 436:         }
 437:         if (!this.positionForAxisAtLeft.equals(that.positionForAxisAtLeft)) {
 438:             return false;
 439:         }
 440:         if (!this.positionForAxisAtRight.equals(that.positionForAxisAtRight)) {
 441:             return false;
 442:         }
 443:   
 444:         return true;
 445: 
 446:     }
 447:     
 448:     /**
 449:      * Returns a hash code for this object.
 450:      * 
 451:      * @return A hash code.
 452:      */
 453:     public int hashCode() {
 454:         int result = 19;
 455:         result = 37 * result + this.positionForAxisAtTop.hashCode();
 456:         result = 37 * result + this.positionForAxisAtBottom.hashCode();
 457:         result = 37 * result + this.positionForAxisAtLeft.hashCode();
 458:         result = 37 * result + this.positionForAxisAtRight.hashCode();
 459:         return result;
 460:     }
 461: }