001 /* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. 006 * 007 * Project Info: http://www.jfree.org/jfreechart/index.html 008 * 009 * This library is free software; you can redistribute it and/or modify it 010 * under the terms of the GNU Lesser General Public License as published by 011 * the Free Software Foundation; either version 2.1 of the License, or 012 * (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but 015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 017 * License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public 020 * License along with this library; if not, write to the Free Software 021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 022 * USA. 023 * 024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 025 * in the United States and other countries.] 026 * 027 * --------------------------- 028 * CategoryLabelPositions.java 029 * --------------------------- 030 * (C) Copyright 2004, 2005, by Object Refinery Limited and Contributors. 031 * 032 * Original Author: David Gilbert (for Object Refinery Limited); 033 * Contributor(s): -; 034 * 035 * $Id: CategoryLabelPositions.java,v 1.5.2.1 2005/10/25 20:37:34 mungady Exp $ 036 * 037 * Changes 038 * ------- 039 * 06-Jan-2004 : Version 1 (DG); 040 * 17-Feb-2004 : Added equals() method (DG); 041 * 05-Nov-2004 : Adjusted settings for UP_90 and DOWN_90 (DG); 042 * 043 */ 044 045 package org.jfree.chart.axis; 046 047 import java.io.Serializable; 048 049 import org.jfree.text.TextBlockAnchor; 050 import org.jfree.ui.RectangleAnchor; 051 import org.jfree.ui.RectangleEdge; 052 import org.jfree.ui.TextAnchor; 053 054 /** 055 * Records the label positions for a category axis. Instances of this class 056 * are immutable. 057 */ 058 public class CategoryLabelPositions implements Serializable { 059 060 /** For serialization. */ 061 private static final long serialVersionUID = -8999557901920364580L; 062 063 /** STANDARD category label positions. */ 064 public static final CategoryLabelPositions 065 STANDARD = new CategoryLabelPositions( 066 new CategoryLabelPosition( 067 RectangleAnchor.BOTTOM, TextBlockAnchor.BOTTOM_CENTER 068 ), // TOP 069 new CategoryLabelPosition( 070 RectangleAnchor.TOP, TextBlockAnchor.TOP_CENTER 071 ), // BOTTOM 072 new CategoryLabelPosition( 073 RectangleAnchor.RIGHT, TextBlockAnchor.CENTER_RIGHT, 074 CategoryLabelWidthType.RANGE, 0.30f 075 ), // LEFT 076 new CategoryLabelPosition( 077 RectangleAnchor.LEFT, TextBlockAnchor.CENTER_LEFT, 078 CategoryLabelWidthType.RANGE, 0.30f 079 ) // RIGHT 080 ); 081 082 /** UP_90 category label positions. */ 083 public static final CategoryLabelPositions 084 UP_90 = new CategoryLabelPositions( 085 new CategoryLabelPosition( 086 RectangleAnchor.BOTTOM, TextBlockAnchor.CENTER_LEFT, 087 TextAnchor.CENTER_LEFT, -Math.PI / 2.0, 088 CategoryLabelWidthType.RANGE, 0.30f 089 ), // TOP 090 new CategoryLabelPosition( 091 RectangleAnchor.TOP, TextBlockAnchor.CENTER_RIGHT, 092 TextAnchor.CENTER_RIGHT, -Math.PI / 2.0, 093 CategoryLabelWidthType.RANGE, 0.30f 094 ), // BOTTOM 095 new CategoryLabelPosition( 096 RectangleAnchor.RIGHT, TextBlockAnchor.BOTTOM_CENTER, 097 TextAnchor.BOTTOM_CENTER, -Math.PI / 2.0, 098 CategoryLabelWidthType.CATEGORY, 0.9f 099 ), // 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 }