001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2006, 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 * Marker.java
029 * -----------
030 * (C) Copyright 2002-2006, by Object Refinery Limited.
031 *
032 * Original Author: David Gilbert (for Object Refinery Limited);
033 * Contributor(s): Nicolas Brodu;
034 *
035 * $Id: Marker.java,v 1.10.2.4 2006/07/03 15:55:15 mungady Exp $
036 *
037 * Changes (since 2-Jul-2002)
038 * --------------------------
039 * 02-Jul-2002 : Added extra constructor, standard header and Javadoc
040 * comments (DG);
041 * 20-Aug-2002 : Added the outline stroke attribute (DG);
042 * 02-Oct-2002 : Fixed errors reported by Checkstyle (DG);
043 * 16-Oct-2002 : Added new constructor (DG);
044 * 26-Mar-2003 : Implemented Serializable (DG);
045 * 21-May-2003 : Added labels (DG);
046 * 11-Sep-2003 : Implemented Cloneable (NB);
047 * 05-Nov-2003 : Added checks to ensure some attributes are never null (DG);
048 * 11-Feb-2003 : Moved to org.jfree.chart.plot package, plus significant API
049 * changes to support IntervalMarker in plots (DG);
050 * 14-Jun-2004 : Updated equals() method (DG);
051 * 21-Jan-2005 : Added settings to control direction of horizontal and
052 * vertical label offsets (DG);
053 * 01-Jun-2005 : Modified to use only one label offset type - this will be
054 * applied to the domain or range axis as appropriate (DG);
055 * 06-Jun-2005 : Fix equals() method to handle GradientPaint (DG);
056 * 19-Aug-2005 : Changed constructor from public --> protected (DG);
057 *
058 */
059
060 package org.jfree.chart.plot;
061
062 import java.awt.BasicStroke;
063 import java.awt.Color;
064 import java.awt.Font;
065 import java.awt.Paint;
066 import java.awt.Stroke;
067 import java.io.IOException;
068 import java.io.ObjectInputStream;
069 import java.io.ObjectOutputStream;
070 import java.io.Serializable;
071
072 import org.jfree.io.SerialUtilities;
073 import org.jfree.ui.LengthAdjustmentType;
074 import org.jfree.ui.RectangleAnchor;
075 import org.jfree.ui.RectangleInsets;
076 import org.jfree.ui.TextAnchor;
077 import org.jfree.util.ObjectUtilities;
078 import org.jfree.util.PaintUtilities;
079
080 /**
081 * The base class for markers that can be added to plots to highlight a value
082 * or range of values.
083 * <br><br>
084 * Note that there is no listener mechanism for markers, so changing the
085 * attributes for a marker will not lead to any automatic chart repainting.
086 */
087 public abstract class Marker implements Cloneable, Serializable {
088
089 /** For serialization. */
090 private static final long serialVersionUID = -734389651405327166L;
091
092 /** The paint. */
093 private transient Paint paint;
094
095 /** The stroke. */
096 private transient Stroke stroke;
097
098 /** The outline paint. */
099 private transient Paint outlinePaint;
100
101 /** The outline stroke. */
102 private transient Stroke outlineStroke;
103
104 /** The alpha transparency. */
105 private float alpha;
106
107 /** The label. */
108 private String label = null;
109
110 /** The label font. */
111 private Font labelFont;
112
113 /** The label paint. */
114 private transient Paint labelPaint;
115
116 /** The label position. */
117 private RectangleAnchor labelAnchor;
118
119 /** The text anchor for the label. */
120 private TextAnchor labelTextAnchor;
121
122 /** The label offset from the marker rectangle. */
123 private RectangleInsets labelOffset;
124
125 /**
126 * The offset type for the domain or range axis (never <code>null</code>).
127 */
128 private LengthAdjustmentType labelOffsetType;
129
130 /**
131 * Creates a new marker with default attributes.
132 */
133 protected Marker() {
134 this(Color.gray);
135 }
136
137 /**
138 * Constructs a new marker.
139 *
140 * @param paint the paint (<code>null</code> not permitted).
141 */
142 protected Marker(Paint paint) {
143 this(paint, new BasicStroke(0.5f), Color.gray, new BasicStroke(0.5f),
144 0.80f);
145 }
146
147 /**
148 * Constructs a new marker.
149 *
150 * @param paint the paint (<code>null</code> not permitted).
151 * @param stroke the stroke (<code>null</code> not permitted).
152 * @param outlinePaint the outline paint (<code>null</code> permitted).
153 * @param outlineStroke the outline stroke (<code>null</code> permitted).
154 * @param alpha the alpha transparency (must be in the range 0.0f to
155 * 1.0f).
156 *
157 * @throws IllegalArgumentException if <code>paint</code> or
158 * <code>stroke</code> is <code>null</code>, or <code>alpha</code> is
159 * not in the specified range.
160 */
161 protected Marker(Paint paint, Stroke stroke,
162 Paint outlinePaint, Stroke outlineStroke,
163 float alpha) {
164
165 if (paint == null) {
166 throw new IllegalArgumentException("Null 'paint' argument.");
167 }
168 if (stroke == null) {
169 throw new IllegalArgumentException("Null 'stroke' argument.");
170 }
171 if (alpha < 0.0f || alpha > 1.0f)
172 throw new IllegalArgumentException(
173 "The 'alpha' value must be in the range 0.0f to 1.0f");
174
175 this.paint = paint;
176 this.stroke = stroke;
177 this.outlinePaint = outlinePaint;
178 this.outlineStroke = outlineStroke;
179 this.alpha = alpha;
180
181 this.labelFont = new Font("SansSerif", Font.PLAIN, 9);
182 this.labelPaint = Color.black;
183 this.labelAnchor = RectangleAnchor.TOP_LEFT;
184 this.labelOffset = new RectangleInsets(3.0, 3.0, 3.0, 3.0);
185 this.labelOffsetType = LengthAdjustmentType.CONTRACT;
186 this.labelTextAnchor = TextAnchor.CENTER;
187
188 }
189
190 /**
191 * Returns the paint.
192 *
193 * @return The paint (never <code>null</code>).
194 *
195 * @see #setPaint(Paint)
196 */
197 public Paint getPaint() {
198 return this.paint;
199 }
200
201 /**
202 * Sets the paint.
203 *
204 * @param paint the paint (<code>null</code> not permitted).
205 *
206 * @see #getPaint()
207 */
208 public void setPaint(Paint paint) {
209 if (paint == null) {
210 throw new IllegalArgumentException("Null 'paint' argument.");
211 }
212 this.paint = paint;
213 }
214
215 /**
216 * Returns the stroke.
217 *
218 * @return The stroke (never <code>null</code>).
219 *
220 * @see #setStroke(Stroke)
221 */
222 public Stroke getStroke() {
223 return this.stroke;
224 }
225
226 /**
227 * Sets the stroke.
228 *
229 * @param stroke the stroke (<code>null</code> not permitted).
230 *
231 * @see #getStroke()
232 */
233 public void setStroke(Stroke stroke) {
234 if (stroke == null) {
235 throw new IllegalArgumentException("Null 'stroke' argument.");
236 }
237 this.stroke = stroke;
238 }
239
240 /**
241 * Returns the outline paint.
242 *
243 * @return The outline paint (possibly <code>null</code>).
244 *
245 * @see #setOutlinePaint(Paint)
246 */
247 public Paint getOutlinePaint() {
248 return this.outlinePaint;
249 }
250
251 /**
252 * Sets the outline paint.
253 *
254 * @param paint the paint (<code>null</code> permitted).
255 *
256 * @see #getOutlinePaint()
257 */
258 public void setOutlinePaint(Paint paint) {
259 this.outlinePaint = paint;
260 }
261
262 /**
263 * Returns the outline stroke.
264 *
265 * @return The outline stroke (possibly <code>null</code>).
266 *
267 * @see #setOutlineStroke(Stroke)
268 */
269 public Stroke getOutlineStroke() {
270 return this.outlineStroke;
271 }
272
273 /**
274 * Sets the outline stroke.
275 *
276 * @param stroke the stroke (<code>null</code> permitted).
277 *
278 * @see #getOutlineStroke()
279 */
280 public void setOutlineStroke(Stroke stroke) {
281 this.outlineStroke = stroke;
282 }
283
284 /**
285 * Returns the alpha transparency.
286 *
287 * @return The alpha transparency.
288 *
289 * @see #setAlpha(float)
290 */
291 public float getAlpha() {
292 return this.alpha;
293 }
294
295 /**
296 * Sets the alpha transparency that should be used when drawing the
297 * marker. This is a value in the range 0.0f (completely transparent) to
298 * 1.0f (completely opaque).
299 *
300 * @param alpha the alpha transparency (must be in the range 0.0f to
301 * 1.0f).
302 *
303 * @throws IllegalArgumentException if <code>alpha</code> is not in the
304 * specified range.
305 *
306 * @see #getAlpha()
307 */
308 public void setAlpha(float alpha) {
309 if (alpha < 0.0f || alpha > 1.0f)
310 throw new IllegalArgumentException(
311 "The 'alpha' value must be in the range 0.0f to 1.0f");
312 this.alpha = alpha;
313 }
314
315 /**
316 * Returns the label (if <code>null</code> no label is displayed).
317 *
318 * @return The label (possibly <code>null</code>).
319 *
320 * @see #setLabel(String)
321 */
322 public String getLabel() {
323 return this.label;
324 }
325
326 /**
327 * Sets the label (if <code>null</code> no label is displayed).
328 *
329 * @param label the label (<code>null</code> permitted).
330 *
331 * @see #getLabel()
332 */
333 public void setLabel(String label) {
334 this.label = label;
335 }
336
337 /**
338 * Returns the label font.
339 *
340 * @return The label font (never <code>null</code>).
341 *
342 * @see #setLabelFont(Font)
343 */
344 public Font getLabelFont() {
345 return this.labelFont;
346 }
347
348 /**
349 * Sets the label font.
350 *
351 * @param font the font (<code>null</code> not permitted).
352 *
353 * @see #getLabelFont()
354 */
355 public void setLabelFont(Font font) {
356 if (font == null) {
357 throw new IllegalArgumentException("Null 'font' argument.");
358 }
359 this.labelFont = font;
360 }
361
362 /**
363 * Returns the label paint.
364 *
365 * @return The label paint (never </code>null</code>).
366 *
367 * @see #setLabelPaint(Paint)
368 */
369 public Paint getLabelPaint() {
370 return this.labelPaint;
371 }
372
373 /**
374 * Sets the label paint.
375 *
376 * @param paint the paint (<code>null</code> not permitted).
377 *
378 * @see #getLabelPaint()
379 */
380 public void setLabelPaint(Paint paint) {
381 if (paint == null) {
382 throw new IllegalArgumentException("Null 'paint' argument.");
383 }
384 this.labelPaint = paint;
385 }
386
387 /**
388 * Returns the label anchor. This defines the position of the label
389 * anchor, relative to the bounds of the marker.
390 *
391 * @return The label anchor (never <code>null</code>).
392 *
393 * @see #setLabelAnchor(RectangleAnchor)
394 */
395 public RectangleAnchor getLabelAnchor() {
396 return this.labelAnchor;
397 }
398
399 /**
400 * Sets the label anchor. This defines the position of the label
401 * anchor, relative to the bounds of the marker.
402 *
403 * @param anchor the anchor (<code>null</code> not permitted).
404 *
405 * @see #getLabelAnchor()
406 */
407 public void setLabelAnchor(RectangleAnchor anchor) {
408 if (anchor == null) {
409 throw new IllegalArgumentException("Null 'anchor' argument.");
410 }
411 this.labelAnchor = anchor;
412 }
413
414 /**
415 * Returns the label offset.
416 *
417 * @return The label offset (never <code>null</code>).
418 *
419 * @see #setLabelOffset(RectangleInsets)
420 */
421 public RectangleInsets getLabelOffset() {
422 return this.labelOffset;
423 }
424
425 /**
426 * Sets the label offset.
427 *
428 * @param offset the label offset (<code>null</code> not permitted).
429 *
430 * @see #getLabelOffset()
431 */
432 public void setLabelOffset(RectangleInsets offset) {
433 if (offset == null) {
434 throw new IllegalArgumentException("Null 'offset' argument.");
435 }
436 this.labelOffset = offset;
437 }
438
439 /**
440 * Returns the label offset type.
441 *
442 * @return The type (never <code>null</code>).
443 *
444 * @see #setLabelOffsetType(LengthAdjustmentType)
445 */
446 public LengthAdjustmentType getLabelOffsetType() {
447 return this.labelOffsetType;
448 }
449
450 /**
451 * Sets the label offset type.
452 *
453 * @param adj the type (<code>null</code> not permitted).
454 *
455 * @see #getLabelOffsetType()
456 */
457 public void setLabelOffsetType(LengthAdjustmentType adj) {
458 if (adj == null) {
459 throw new IllegalArgumentException("Null 'adj' argument.");
460 }
461 this.labelOffsetType = adj;
462 }
463
464 /**
465 * Returns the label text anchor.
466 *
467 * @return The label text anchor (never <code>null</code>).
468 *
469 * @see #setLabelTextAnchor(TextAnchor)
470 */
471 public TextAnchor getLabelTextAnchor() {
472 return this.labelTextAnchor;
473 }
474
475 /**
476 * Sets the label text anchor.
477 *
478 * @param anchor the label text anchor (<code>null</code> not permitted).
479 *
480 * @see #getLabelTextAnchor()
481 */
482 public void setLabelTextAnchor(TextAnchor anchor) {
483 if (anchor == null) {
484 throw new IllegalArgumentException("Null 'anchor' argument.");
485 }
486 this.labelTextAnchor = anchor;
487 }
488
489 /**
490 * Tests the marker for equality with an arbitrary object.
491 *
492 * @param obj the object (<code>null</code> permitted).
493 *
494 * @return A boolean.
495 */
496 public boolean equals(Object obj) {
497 if (obj == this) {
498 return true;
499 }
500 if (!(obj instanceof Marker)) {
501 return false;
502 }
503 Marker that = (Marker) obj;
504 if (!PaintUtilities.equal(this.paint, that.paint)) {
505 return false;
506 }
507 if (!ObjectUtilities.equal(this.stroke, that.stroke)) {
508 return false;
509 }
510 if (!PaintUtilities.equal(this.outlinePaint, that.outlinePaint)) {
511 return false;
512 }
513 if (!ObjectUtilities.equal(this.outlineStroke, that.outlineStroke)) {
514 return false;
515 }
516 if (this.alpha != that.alpha) {
517 return false;
518 }
519 if (!ObjectUtilities.equal(this.label, that.label)) {
520 return false;
521 }
522 if (!ObjectUtilities.equal(this.labelFont, that.labelFont)) {
523 return false;
524 }
525 if (!PaintUtilities.equal(this.labelPaint, that.labelPaint)) {
526 return false;
527 }
528 if (this.labelAnchor != that.labelAnchor) {
529 return false;
530 }
531 if (this.labelTextAnchor != that.labelTextAnchor) {
532 return false;
533 }
534 if (!ObjectUtilities.equal(this.labelOffset, that.labelOffset)) {
535 return false;
536 }
537 if (!this.labelOffsetType.equals(that.labelOffsetType)) {
538 return false;
539 }
540 return true;
541 }
542
543 /**
544 * Creates a clone of the marker.
545 *
546 * @return A clone.
547 *
548 * @throws CloneNotSupportedException never.
549 */
550 public Object clone() throws CloneNotSupportedException {
551 return super.clone();
552 }
553
554 /**
555 * Provides serialization support.
556 *
557 * @param stream the output stream.
558 *
559 * @throws IOException if there is an I/O error.
560 */
561 private void writeObject(ObjectOutputStream stream) throws IOException {
562 stream.defaultWriteObject();
563 SerialUtilities.writePaint(this.paint, stream);
564 SerialUtilities.writeStroke(this.stroke, stream);
565 SerialUtilities.writePaint(this.outlinePaint, stream);
566 SerialUtilities.writeStroke(this.outlineStroke, stream);
567 SerialUtilities.writePaint(this.labelPaint, stream);
568 }
569
570 /**
571 * Provides serialization support.
572 *
573 * @param stream the input stream.
574 *
575 * @throws IOException if there is an I/O error.
576 * @throws ClassNotFoundException if there is a classpath problem.
577 */
578 private void readObject(ObjectInputStream stream)
579 throws IOException, ClassNotFoundException {
580 stream.defaultReadObject();
581 this.paint = SerialUtilities.readPaint(stream);
582 this.stroke = SerialUtilities.readStroke(stream);
583 this.outlinePaint = SerialUtilities.readPaint(stream);
584 this.outlineStroke = SerialUtilities.readStroke(stream);
585 this.labelPaint = SerialUtilities.readPaint(stream);
586 }
587
588 }