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     * Marker.java
029     * -----------
030     * (C) Copyright 2002-2005, 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.3 2005/10/25 20:52:08 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     */
084    public abstract class Marker implements Cloneable, Serializable {
085    
086        /** For serialization. */
087        private static final long serialVersionUID = -734389651405327166L;
088    
089        /** The paint. */
090        private transient Paint paint;
091    
092        /** The stroke. */
093        private transient Stroke stroke;
094        
095        /** The outline paint. */
096        private transient Paint outlinePaint;
097    
098        /** The outline stroke. */
099        private transient Stroke outlineStroke;
100    
101        /** The alpha transparency. */
102        private float alpha;
103    
104        /** The label. */
105        private String label = null;
106    
107        /** The label font. */
108        private Font labelFont;
109    
110        /** The label paint. */
111        private transient Paint labelPaint;
112    
113        /** The label position. */
114        private RectangleAnchor labelAnchor;
115        
116        /** The text anchor for the label. */
117        private TextAnchor labelTextAnchor;
118    
119        /** The label offset from the marker rectangle. */
120        private RectangleInsets labelOffset;
121        
122        /** 
123         * The offset type for the domain or range axis (never <code>null</code>). 
124         */
125        private LengthAdjustmentType labelOffsetType;
126        
127        /**
128         * Creates a new marker with default attributes.
129         */
130        protected Marker() {
131            this(Color.gray);
132        }
133    
134        /**
135         * Constructs a new marker.
136         *
137         * @param paint  the paint (<code>null</code> not permitted).
138         */
139        protected Marker(Paint paint) {
140            this(
141                paint, new BasicStroke(0.5f), Color.gray, 
142                new BasicStroke(0.5f), 0.80f
143            );
144        }
145    
146        /**
147         * Constructs a new marker.
148         *
149         * @param paint  the paint (<code>null</code> not permitted).
150         * @param stroke  the stroke (<code>null</code> not permitted).
151         * @param outlinePaint  the outline paint (<code>null</code> permitted).
152         * @param outlineStroke  the outline stroke (<code>null</code> permitted).
153         * @param alpha  the alpha transparency.
154         */
155        protected Marker(Paint paint, Stroke stroke, 
156                         Paint outlinePaint, Stroke outlineStroke, 
157                         float alpha) {
158    
159            if (paint == null) {
160                throw new IllegalArgumentException("Null 'paint' argument.");
161            }
162            if (stroke == null) {
163                throw new IllegalArgumentException("Null 'stroke' argument.");
164            }
165            
166            this.paint = paint;
167            this.stroke = stroke;
168            this.outlinePaint = outlinePaint;
169            this.outlineStroke = outlineStroke;
170            this.alpha = alpha;
171            
172            this.labelFont = new Font("SansSerif", Font.PLAIN, 9);
173            this.labelPaint = Color.black;
174            this.labelAnchor = RectangleAnchor.TOP_LEFT;
175            this.labelOffset = new RectangleInsets(3.0, 3.0, 3.0, 3.0);
176            this.labelOffsetType = LengthAdjustmentType.CONTRACT;
177            this.labelTextAnchor = TextAnchor.CENTER;
178            
179        }
180    
181        /**
182         * Returns the paint.
183         *
184         * @return The paint (never <code>null</code>).
185         */
186        public Paint getPaint() {
187            return this.paint;
188        }
189        
190        /**
191         * Sets the paint.
192         * 
193         * @param paint  the paint (<code>null</code> not permitted).
194         */
195        public void setPaint(Paint paint) {
196            if (paint == null) {
197                throw new IllegalArgumentException("Null 'paint' argument.");
198            }
199            this.paint = paint;
200        }
201    
202        /**
203         * Returns the stroke.
204         *
205         * @return The stroke (never <code>null</code>).
206         */
207        public Stroke getStroke() {
208            return this.stroke;
209        }
210        
211        /**
212         * Sets the stroke.
213         * 
214         * @param stroke  the stroke (<code>null</code> not permitted).
215         */
216        public void setStroke(Stroke stroke) {
217            if (stroke == null) {
218                throw new IllegalArgumentException("Null 'stroke' argument.");
219            }
220            this.stroke = stroke;
221        }
222    
223        /**
224         * Returns the outline paint.
225         *
226         * @return The outline paint (possibly <code>null</code>).
227         */
228        public Paint getOutlinePaint() {
229            return this.outlinePaint;
230        }
231        
232        /**
233         * Sets the outline paint.
234         * 
235         * @param paint  the paint (<code>null</code> permitted).
236         */
237        public void setOutlinePaint(Paint paint) {
238            this.outlinePaint = paint;
239        }
240    
241        /**
242         * Returns the outline stroke.
243         *
244         * @return The outline stroke (possibly <code>null</code>).
245         */
246        public Stroke getOutlineStroke() {
247            return this.outlineStroke;
248        }
249        
250        /**
251         * Sets the outline stroke.
252         * 
253         * @param stroke  the stroke (<code>null</code> permitted).
254         */
255        public void setOutlineStroke(Stroke stroke) {
256            this.outlineStroke = stroke;
257        }
258    
259        /**
260         * Returns the alpha transparency.
261         *
262         * @return The alpha transparency.
263         */
264        public float getAlpha() {
265            return this.alpha;
266        }
267        
268        /**
269         * Sets the alpha transparency.
270         * 
271         * @param alpha  the alpha transparency.
272         */
273        public void setAlpha(float alpha) {
274            this.alpha = alpha;
275        }
276    
277        /**
278         * Returns the label (if <code>null</code> no label is displayed).
279         *
280         * @return The label (possibly <code>null</code>).
281         */
282        public String getLabel() {
283            return this.label;
284        }
285    
286        /**
287         * Sets the label (if <code>null</code> no label is displayed).
288         *
289         * @param label  the label (<code>null</code> permitted).
290         */
291        public void setLabel(String label) {
292            this.label = label;
293        }
294    
295        /**
296         * Returns the label font.
297         *
298         * @return The label font (never <code>null</code>).
299         */
300        public Font getLabelFont() {
301            return this.labelFont;
302        }
303    
304        /**
305         * Sets the label font.
306         *
307         * @param font  the font (<code>null</code> not permitted).
308         */
309        public void setLabelFont(Font font) {
310            if (font == null) {
311                throw new IllegalArgumentException("Null 'font' argument.");
312            }
313            this.labelFont = font;
314        }
315    
316        /**
317         * Returns the label paint.
318         *
319         * @return The label paint (never </code>null</code>).
320         */
321        public Paint getLabelPaint() {
322            return this.labelPaint;
323        }
324    
325        /**
326         * Sets the label paint.
327         *
328         * @param paint  the paint (<code>null</code> not permitted).
329         */
330        public void setLabelPaint(Paint paint) {
331            if (paint == null) {
332                throw new IllegalArgumentException("Null 'paint' argument.");
333            }
334            this.labelPaint = paint;
335        }
336    
337        /**
338         * Returns the label anchor.
339         *
340         * @return The label anchor (never <code>null</code>).
341         */
342        public RectangleAnchor getLabelAnchor() {
343            return this.labelAnchor;
344        }
345    
346        /**
347         * Sets the label anchor.
348         *
349         * @param anchor  the anchor (<code>null</code> not permitted).
350         */
351        public void setLabelAnchor(RectangleAnchor anchor) {
352            if (anchor == null) {
353                throw new IllegalArgumentException("Null 'anchor' argument.");
354            }
355            this.labelAnchor = anchor;
356        }
357    
358        /**
359         * Returns the label offset.
360         * 
361         * @return The label offset (never <code>null</code>).
362         */
363        public RectangleInsets getLabelOffset() {
364            return this.labelOffset;
365        }
366        
367        /**
368         * Sets the label offset.
369         * 
370         * @param offset  the label offset (<code>null</code> not permitted).
371         */
372        public void setLabelOffset(RectangleInsets offset) {
373            if (offset == null) {
374                throw new IllegalArgumentException("Null 'offset' argument.");
375            }
376            this.labelOffset = offset;
377        }
378        
379        /**
380         * Returns the label offset type.
381         * 
382         * @return The type (never <code>null</code>).
383         */
384        public LengthAdjustmentType getLabelOffsetType() {
385            return this.labelOffsetType;   
386        }
387        
388        /**
389         * Sets the label offset type.
390         * 
391         * @param adj  the type (<code>null</code> not permitted).
392         */
393        public void setLabelOffsetType(LengthAdjustmentType adj) {
394            if (adj == null) {
395                throw new IllegalArgumentException("Null 'adj' argument.");
396            }
397            this.labelOffsetType = adj;    
398        }
399            
400        /**
401         * Returns the label text anchor.
402         * 
403         * @return The label text anchor (never <code>null</code>).
404         */
405        public TextAnchor getLabelTextAnchor() {
406            return this.labelTextAnchor;
407        }
408        
409        /**
410         * Sets the label text anchor.
411         * 
412         * @param anchor  the label text anchor (<code>null</code> not permitted).
413         */
414        public void setLabelTextAnchor(TextAnchor anchor) {
415            if (anchor == null) { 
416                throw new IllegalArgumentException("Null 'anchor' argument.");
417            }
418            this.labelTextAnchor = anchor;
419        }
420        
421        /**
422         * Tests the marker for equality with an arbitrary object.
423         * 
424         * @param obj  the object (<code>null</code> permitted).
425         * 
426         * @return A boolean.
427         */
428        public boolean equals(Object obj) {
429            if (obj == this) {
430                return true;
431            }
432            if (!(obj instanceof Marker)) {
433                return false;
434            }
435            Marker that = (Marker) obj;
436            if (!PaintUtilities.equal(this.paint, that.paint)) {
437                return false;   
438            }
439            if (!ObjectUtilities.equal(this.stroke, that.stroke)) {
440                return false;
441            }
442            if (!PaintUtilities.equal(this.outlinePaint, that.outlinePaint)) {
443                return false;   
444            }
445            if (!ObjectUtilities.equal(this.outlineStroke, that.outlineStroke)) {
446                return false;
447            }
448            if (this.alpha != that.alpha) {
449                return false;
450            }
451            if (!ObjectUtilities.equal(this.label, that.label)) {
452                return false;
453            }
454            if (!ObjectUtilities.equal(this.labelFont, that.labelFont)) {
455                return false;
456            }
457            if (!PaintUtilities.equal(this.labelPaint, that.labelPaint)) {
458                return false;
459            }
460            if (this.labelAnchor != that.labelAnchor) {
461                return false;
462            }
463            if (this.labelTextAnchor != that.labelTextAnchor) {
464                return false;   
465            }
466            if (!ObjectUtilities.equal(this.labelOffset, that.labelOffset)) {
467                return false;
468            }
469            if (!this.labelOffsetType.equals(that.labelOffsetType)) {
470                return false;
471            }
472            return true;
473        }
474        
475        /**
476         * Creates a clone of the marker.
477         * 
478         * @return A clone.
479         * 
480         * @throws CloneNotSupportedException never.
481         */
482        public Object clone() throws CloneNotSupportedException {
483            return super.clone();
484        }
485        
486        /**
487         * Provides serialization support.
488         *
489         * @param stream  the output stream.
490         *
491         * @throws IOException  if there is an I/O error.
492         */
493        private void writeObject(ObjectOutputStream stream) throws IOException {
494            stream.defaultWriteObject();
495            SerialUtilities.writePaint(this.paint, stream);
496            SerialUtilities.writeStroke(this.stroke, stream);
497            SerialUtilities.writePaint(this.outlinePaint, stream);
498            SerialUtilities.writeStroke(this.outlineStroke, stream);
499            SerialUtilities.writePaint(this.labelPaint, stream);
500        }
501    
502        /**
503         * Provides serialization support.
504         *
505         * @param stream  the input stream.
506         *
507         * @throws IOException  if there is an I/O error.
508         * @throws ClassNotFoundException  if there is a classpath problem.
509         */
510        private void readObject(ObjectInputStream stream) 
511            throws IOException, ClassNotFoundException {
512            stream.defaultReadObject();
513            this.paint = SerialUtilities.readPaint(stream);
514            this.stroke = SerialUtilities.readStroke(stream);
515            this.outlinePaint = SerialUtilities.readPaint(stream);
516            this.outlineStroke = SerialUtilities.readStroke(stream);
517            this.labelPaint = SerialUtilities.readPaint(stream);
518        }
519    
520    }