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 STANDARD = new CategoryLabelPositions(
065: new CategoryLabelPosition(RectangleAnchor.BOTTOM,
066: TextBlockAnchor.BOTTOM_CENTER), // TOP
067: new CategoryLabelPosition(RectangleAnchor.TOP,
068: TextBlockAnchor.TOP_CENTER), // BOTTOM
069: new CategoryLabelPosition(RectangleAnchor.RIGHT,
070: TextBlockAnchor.CENTER_RIGHT,
071: CategoryLabelWidthType.RANGE, 0.30f), // LEFT
072: new CategoryLabelPosition(RectangleAnchor.LEFT,
073: TextBlockAnchor.CENTER_LEFT,
074: CategoryLabelWidthType.RANGE, 0.30f) // RIGHT
075: );
076:
077: /** UP_90 category label positions. */
078: public static final CategoryLabelPositions UP_90 = new CategoryLabelPositions(
079: new CategoryLabelPosition(RectangleAnchor.BOTTOM,
080: TextBlockAnchor.CENTER_LEFT,
081: TextAnchor.CENTER_LEFT, -Math.PI / 2.0,
082: CategoryLabelWidthType.RANGE, 0.30f), // TOP
083: new CategoryLabelPosition(RectangleAnchor.TOP,
084: TextBlockAnchor.CENTER_RIGHT,
085: TextAnchor.CENTER_RIGHT, -Math.PI / 2.0,
086: CategoryLabelWidthType.RANGE, 0.30f), // BOTTOM
087: new CategoryLabelPosition(RectangleAnchor.RIGHT,
088: TextBlockAnchor.BOTTOM_CENTER,
089: TextAnchor.BOTTOM_CENTER, -Math.PI / 2.0,
090: CategoryLabelWidthType.CATEGORY, 0.9f), // LEFT
091: new CategoryLabelPosition(RectangleAnchor.LEFT,
092: TextBlockAnchor.TOP_CENTER, TextAnchor.TOP_CENTER,
093: -Math.PI / 2.0, CategoryLabelWidthType.CATEGORY,
094: 0.90f) // RIGHT
095: );
096:
097: /** DOWN_90 category label positions. */
098: public static final CategoryLabelPositions DOWN_90 = new CategoryLabelPositions(
099: new CategoryLabelPosition(RectangleAnchor.BOTTOM,
100: TextBlockAnchor.CENTER_RIGHT,
101: TextAnchor.CENTER_RIGHT, Math.PI / 2.0,
102: CategoryLabelWidthType.RANGE, 0.30f), // TOP
103: new CategoryLabelPosition(RectangleAnchor.TOP,
104: TextBlockAnchor.CENTER_LEFT,
105: TextAnchor.CENTER_LEFT, Math.PI / 2.0,
106: CategoryLabelWidthType.RANGE, 0.30f), // BOTTOM
107: new CategoryLabelPosition(RectangleAnchor.RIGHT,
108: TextBlockAnchor.TOP_CENTER, TextAnchor.TOP_CENTER,
109: Math.PI / 2.0, CategoryLabelWidthType.CATEGORY,
110: 0.90f), // LEFT
111: new CategoryLabelPosition(RectangleAnchor.LEFT,
112: TextBlockAnchor.BOTTOM_CENTER,
113: TextAnchor.BOTTOM_CENTER, Math.PI / 2.0,
114: CategoryLabelWidthType.CATEGORY, 0.90f) // RIGHT
115: );
116:
117: /** UP_45 category label positions. */
118: public static final CategoryLabelPositions UP_45 = createUpRotationLabelPositions(Math.PI / 4.0);
119:
120: /** DOWN_45 category label positions. */
121: public static final CategoryLabelPositions DOWN_45 = createDownRotationLabelPositions(Math.PI / 4.0);
122:
123: /**
124: * Creates a new instance where the category labels angled upwards by the
125: * specified amount.
126: *
127: * @param angle the rotation angle (should be < Math.PI / 2.0).
128: *
129: * @return A category label position specification.
130: */
131: public static CategoryLabelPositions createUpRotationLabelPositions(
132: double angle) {
133: return new CategoryLabelPositions(new CategoryLabelPosition(
134: RectangleAnchor.BOTTOM, TextBlockAnchor.BOTTOM_LEFT,
135: TextAnchor.BOTTOM_LEFT, -angle,
136: CategoryLabelWidthType.RANGE, 0.50f), // TOP
137: new CategoryLabelPosition(RectangleAnchor.TOP,
138: TextBlockAnchor.TOP_RIGHT,
139: TextAnchor.TOP_RIGHT, -angle,
140: CategoryLabelWidthType.RANGE, 0.50f), // BOTTOM
141: new CategoryLabelPosition(RectangleAnchor.RIGHT,
142: TextBlockAnchor.BOTTOM_RIGHT,
143: TextAnchor.BOTTOM_RIGHT, -angle,
144: CategoryLabelWidthType.RANGE, 0.50f), // LEFT
145: new CategoryLabelPosition(RectangleAnchor.LEFT,
146: TextBlockAnchor.TOP_LEFT, TextAnchor.TOP_LEFT,
147: -angle, CategoryLabelWidthType.RANGE, 0.50f) // RIGHT
148: );
149: }
150:
151: /**
152: * Creates a new instance where the category labels angled downwards by the
153: * specified amount.
154: *
155: * @param angle the rotation angle (should be < Math.PI / 2.0).
156: *
157: * @return A category label position specification.
158: */
159: public static CategoryLabelPositions createDownRotationLabelPositions(
160: double angle) {
161: return new CategoryLabelPositions(new CategoryLabelPosition(
162: RectangleAnchor.BOTTOM, TextBlockAnchor.BOTTOM_RIGHT,
163: TextAnchor.BOTTOM_RIGHT, angle,
164: CategoryLabelWidthType.RANGE, 0.50f), // TOP
165: new CategoryLabelPosition(RectangleAnchor.TOP,
166: TextBlockAnchor.TOP_LEFT, TextAnchor.TOP_LEFT,
167: angle, CategoryLabelWidthType.RANGE, 0.50f), // BOTTOM
168: new CategoryLabelPosition(RectangleAnchor.RIGHT,
169: TextBlockAnchor.TOP_RIGHT,
170: TextAnchor.TOP_RIGHT, angle,
171: CategoryLabelWidthType.RANGE, 0.50f), // LEFT
172: new CategoryLabelPosition(RectangleAnchor.LEFT,
173: TextBlockAnchor.BOTTOM_LEFT,
174: TextAnchor.BOTTOM_LEFT, angle,
175: CategoryLabelWidthType.RANGE, 0.50f) // RIGHT
176: );
177: }
178:
179: /**
180: * The label positioning details used when an axis is at the top of a
181: * chart.
182: */
183: private CategoryLabelPosition positionForAxisAtTop;
184:
185: /**
186: * The label positioning details used when an axis is at the bottom of a
187: * chart.
188: */
189: private CategoryLabelPosition positionForAxisAtBottom;
190:
191: /**
192: * The label positioning details used when an axis is at the left of a
193: * chart.
194: */
195: private CategoryLabelPosition positionForAxisAtLeft;
196:
197: /**
198: * The label positioning details used when an axis is at the right of a
199: * chart.
200: */
201: private CategoryLabelPosition positionForAxisAtRight;
202:
203: /**
204: * Default constructor.
205: */
206: public CategoryLabelPositions() {
207: this .positionForAxisAtTop = new CategoryLabelPosition();
208: this .positionForAxisAtBottom = new CategoryLabelPosition();
209: this .positionForAxisAtLeft = new CategoryLabelPosition();
210: this .positionForAxisAtRight = new CategoryLabelPosition();
211: }
212:
213: /**
214: * Creates a new position specification.
215: *
216: * @param top the label position info used when an axis is at the top
217: * (<code>null</code> not permitted).
218: * @param bottom the label position info used when an axis is at the
219: * bottom (<code>null</code> not permitted).
220: * @param left the label position info used when an axis is at the left
221: * (<code>null</code> not permitted).
222: * @param right the label position info used when an axis is at the right
223: * (<code>null</code> not permitted).
224: */
225: public CategoryLabelPositions(CategoryLabelPosition top,
226: CategoryLabelPosition bottom, CategoryLabelPosition left,
227: CategoryLabelPosition right) {
228:
229: if (top == null) {
230: throw new IllegalArgumentException("Null 'top' argument.");
231: }
232: if (bottom == null) {
233: throw new IllegalArgumentException(
234: "Null 'bottom' argument.");
235: }
236: if (left == null) {
237: throw new IllegalArgumentException("Null 'left' argument.");
238: }
239: if (right == null) {
240: throw new IllegalArgumentException("Null 'right' argument.");
241: }
242:
243: this .positionForAxisAtTop = top;
244: this .positionForAxisAtBottom = bottom;
245: this .positionForAxisAtLeft = left;
246: this .positionForAxisAtRight = right;
247:
248: }
249:
250: /**
251: * Returns the category label position specification for an axis at the
252: * given location.
253: *
254: * @param edge the axis location.
255: *
256: * @return The category label position specification.
257: */
258: public CategoryLabelPosition getLabelPosition(RectangleEdge edge) {
259: CategoryLabelPosition result = null;
260: if (edge == RectangleEdge.TOP) {
261: result = this .positionForAxisAtTop;
262: } else if (edge == RectangleEdge.BOTTOM) {
263: result = this .positionForAxisAtBottom;
264: } else if (edge == RectangleEdge.LEFT) {
265: result = this .positionForAxisAtLeft;
266: } else if (edge == RectangleEdge.RIGHT) {
267: result = this .positionForAxisAtRight;
268: }
269: return result;
270: }
271:
272: /**
273: * Returns a new instance based on an existing instance but with the top
274: * position changed.
275: *
276: * @param base the base (<code>null</code> not permitted).
277: * @param top the top position (<code>null</code> not permitted).
278: *
279: * @return A new instance (never <code>null</code>).
280: */
281: public static CategoryLabelPositions replaceTopPosition(
282: CategoryLabelPositions base, CategoryLabelPosition top) {
283:
284: if (base == null) {
285: throw new IllegalArgumentException("Null 'base' argument.");
286: }
287: if (top == null) {
288: throw new IllegalArgumentException("Null 'top' argument.");
289: }
290:
291: return new CategoryLabelPositions(top, base
292: .getLabelPosition(RectangleEdge.BOTTOM), base
293: .getLabelPosition(RectangleEdge.LEFT), base
294: .getLabelPosition(RectangleEdge.RIGHT));
295: }
296:
297: /**
298: * Returns a new instance based on an existing instance but with the bottom
299: * position changed.
300: *
301: * @param base the base (<code>null</code> not permitted).
302: * @param bottom the bottom position (<code>null</code> not permitted).
303: *
304: * @return A new instance (never <code>null</code>).
305: */
306: public static CategoryLabelPositions replaceBottomPosition(
307: CategoryLabelPositions base, CategoryLabelPosition bottom) {
308:
309: if (base == null) {
310: throw new IllegalArgumentException("Null 'base' argument.");
311: }
312: if (bottom == null) {
313: throw new IllegalArgumentException(
314: "Null 'bottom' argument.");
315: }
316:
317: return new CategoryLabelPositions(base
318: .getLabelPosition(RectangleEdge.TOP), bottom, base
319: .getLabelPosition(RectangleEdge.LEFT), base
320: .getLabelPosition(RectangleEdge.RIGHT));
321: }
322:
323: /**
324: * Returns a new instance based on an existing instance but with the left
325: * position changed.
326: *
327: * @param base the base (<code>null</code> not permitted).
328: * @param left the left position (<code>null</code> not permitted).
329: *
330: * @return A new instance (never <code>null</code>).
331: */
332: public static CategoryLabelPositions replaceLeftPosition(
333: CategoryLabelPositions base, CategoryLabelPosition left) {
334:
335: if (base == null) {
336: throw new IllegalArgumentException("Null 'base' argument.");
337: }
338: if (left == null) {
339: throw new IllegalArgumentException("Null 'left' argument.");
340: }
341:
342: return new CategoryLabelPositions(base
343: .getLabelPosition(RectangleEdge.TOP), base
344: .getLabelPosition(RectangleEdge.BOTTOM), left, base
345: .getLabelPosition(RectangleEdge.RIGHT));
346: }
347:
348: /**
349: * Returns a new instance based on an existing instance but with the right
350: * position changed.
351: *
352: * @param base the base (<code>null</code> not permitted).
353: * @param right the right position (<code>null</code> not permitted).
354: *
355: * @return A new instance (never <code>null</code>).
356: */
357: public static CategoryLabelPositions replaceRightPosition(
358: CategoryLabelPositions base, CategoryLabelPosition right) {
359:
360: if (base == null) {
361: throw new IllegalArgumentException("Null 'base' argument.");
362: }
363: if (right == null) {
364: throw new IllegalArgumentException("Null 'right' argument.");
365: }
366:
367: return new CategoryLabelPositions(base
368: .getLabelPosition(RectangleEdge.TOP), base
369: .getLabelPosition(RectangleEdge.BOTTOM), base
370: .getLabelPosition(RectangleEdge.LEFT), right);
371: }
372:
373: /**
374: * Returns <code>true</code> if this object is equal to the specified
375: * object, and <code>false</code> otherwise.
376: *
377: * @param obj the other object.
378: *
379: * @return A boolean.
380: */
381: public boolean equals(Object obj) {
382:
383: if (this == obj) {
384: return true;
385: }
386: if (!(obj instanceof CategoryLabelPositions)) {
387: return false;
388: }
389:
390: CategoryLabelPositions that = (CategoryLabelPositions) obj;
391: if (!this .positionForAxisAtTop
392: .equals(that.positionForAxisAtTop)) {
393: return false;
394: }
395: if (!this .positionForAxisAtBottom
396: .equals(that.positionForAxisAtBottom)) {
397: return false;
398: }
399: if (!this .positionForAxisAtLeft
400: .equals(that.positionForAxisAtLeft)) {
401: return false;
402: }
403: if (!this .positionForAxisAtRight
404: .equals(that.positionForAxisAtRight)) {
405: return false;
406: }
407:
408: return true;
409:
410: }
411:
412: /**
413: * Returns a hash code for this object.
414: *
415: * @return A hash code.
416: */
417: public int hashCode() {
418: int result = 19;
419: result = 37 * result + this .positionForAxisAtTop.hashCode();
420: result = 37 * result + this .positionForAxisAtBottom.hashCode();
421: result = 37 * result + this .positionForAxisAtLeft.hashCode();
422: result = 37 * result + this.positionForAxisAtRight.hashCode();
423: return result;
424: }
425: }
|