001    /* ===========================================================
002     * JFreeChart : a free chart library for the Java(tm) platform
003     * ===========================================================
004     *
005     * (C) Copyright 2000-2007, 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     * BlockBorder.java
029     * ----------------
030     * (C) Copyright 2004-2007, by Object Refinery Limited.
031     *
032     * Original Author:  David Gilbert (for Object Refinery Limited);
033     * Contributor(s):   -;
034     *
035     * $Id: BlockBorder.java,v 1.7.2.2 2007/03/16 15:26:15 mungady Exp $
036     *
037     * Changes:
038     * --------
039     * 22-Oct-2004 : Version 1 (DG);
040     * 04-Feb-2005 : Added equals() and implemented Serializable (DG);
041     * 23-Feb-2005 : Added attribute for border color (DG);
042     * 06-May-2005 : Added new convenience constructors (DG);
043     * ------------- JFREECHART 1.0.x ---------------------------------------------
044     * 16-Mar-2007 : Implemented BlockFrame (DG);
045     * 
046     */
047    
048    package org.jfree.chart.block;
049    
050    import java.awt.Color;
051    import java.awt.Graphics2D;
052    import java.awt.Paint;
053    import java.awt.geom.Rectangle2D;
054    import java.io.IOException;
055    import java.io.ObjectInputStream;
056    import java.io.ObjectOutputStream;
057    import java.io.Serializable;
058    
059    import org.jfree.io.SerialUtilities;
060    import org.jfree.ui.RectangleInsets;
061    import org.jfree.util.PaintUtilities;
062    
063    /**
064     * A border for a block.  This class is immutable.
065     */
066    public class BlockBorder implements BlockFrame, Serializable {
067        
068        /** For serialization. */
069        private static final long serialVersionUID = 4961579220410228283L;
070        
071        /** An empty border. */
072        public static final BlockBorder NONE = new BlockBorder(
073                RectangleInsets.ZERO_INSETS, Color.white);
074        
075        /** The space reserved for the border. */
076        private RectangleInsets insets;
077        
078        /** The border color. */
079        private transient Paint paint;
080        
081        /**
082         * Creates a default border.
083         */
084        public BlockBorder() {
085            this(Color.black);    
086        }
087        
088        /**
089         * Creates a new border with the specified color.
090         * 
091         * @param paint  the color (<code>null</code> not permitted).
092         */
093        public BlockBorder(Paint paint) {
094            this(new RectangleInsets(1, 1, 1, 1), paint);   
095        }
096        
097        /**
098         * Creates a new border with the specified line widths (in black).
099         * 
100         * @param top  the width of the top border.
101         * @param left  the width of the left border.
102         * @param bottom  the width of the bottom border.
103         * @param right  the width of the right border.
104         */
105        public BlockBorder(double top, double left, double bottom, double right) {
106            this(new RectangleInsets(top, left, bottom, right), Color.black);    
107        }
108        
109        /**
110         * Creates a new border with the specified line widths (in black).
111         * 
112         * @param top  the width of the top border.
113         * @param left  the width of the left border.
114         * @param bottom  the width of the bottom border.
115         * @param right  the width of the right border.
116         * @param paint  the border paint (<code>null</code> not permitted).
117         */
118        public BlockBorder(double top, double left, double bottom, double right, 
119                           Paint paint) {
120            this(new RectangleInsets(top, left, bottom, right), paint);    
121        }
122        
123        /**
124         * Creates a new border.
125         * 
126         * @param insets  the border insets (<code>null</code> not permitted).
127         * @param paint  the paint (<code>null</code> not permitted).
128         */
129        public BlockBorder(RectangleInsets insets, Paint paint) {
130            if (insets == null) {
131                throw new IllegalArgumentException("Null 'insets' argument.");
132            }
133            if (paint == null) {
134                throw new IllegalArgumentException("Null 'paint' argument.");   
135            }
136            this.insets = insets;
137            this.paint = paint;
138        }
139    
140        /**
141         * Returns the space reserved for the border.
142         * 
143         * @return The space (never <code>null</code>).
144         */
145        public RectangleInsets getInsets() {
146            return this.insets;
147        }
148        
149        /**
150         * Returns the paint used to draw the border.
151         * 
152         * @return The paint (never <code>null</code>).
153         */
154        public Paint getPaint() {
155            return this.paint;   
156        }
157        
158        /**
159         * Draws the border by filling in the reserved space.
160         * 
161         * @param g2  the graphics device.
162         * @param area  the area.
163         */
164        public void draw(Graphics2D g2, Rectangle2D area) {
165            // this default implementation will just fill the available
166            // border space with a single color
167            double t = this.insets.calculateTopInset(area.getHeight());
168            double b = this.insets.calculateBottomInset(area.getHeight());
169            double l = this.insets.calculateLeftInset(area.getWidth());
170            double r = this.insets.calculateRightInset(area.getWidth());
171            double x = area.getX();
172            double y = area.getY();
173            double w = area.getWidth();
174            double h = area.getHeight();
175            g2.setPaint(this.paint);
176            Rectangle2D rect = new Rectangle2D.Double();
177            if (t > 0.0) {
178                rect.setRect(x, y, w, t);
179                g2.fill(rect);
180            }
181            if (b > 0.0) {
182                rect.setRect(x, y + h - b, w, b);
183                g2.fill(rect);
184            }
185            if (l > 0.0) {
186                rect.setRect(x, y, l, h);
187                g2.fill(rect);
188            }
189            if (r > 0.0) {
190                rect.setRect(x + w - r, y, r, h);
191                g2.fill(rect);
192            }
193        }
194        
195        /**
196         * Tests this border for equality with an arbitrary instance.
197         * 
198         * @param obj  the object (<code>null</code> permitted).
199         * 
200         * @return A boolean.
201         */
202        public boolean equals(Object obj) {
203            if (obj == this) {
204                return true;   
205            }
206            if (!(obj instanceof BlockBorder)) {
207                return false;   
208            }
209            BlockBorder that = (BlockBorder) obj;
210            if (!this.insets.equals(that.insets)) {
211                return false;   
212            }
213            if (!PaintUtilities.equal(this.paint, that.paint)) {
214                return false;
215            }
216            return true;
217        }
218        
219        /**
220         * Provides serialization support.
221         *
222         * @param stream  the output stream.
223         *
224         * @throws IOException  if there is an I/O error.
225         */
226        private void writeObject(ObjectOutputStream stream) throws IOException {
227            stream.defaultWriteObject();
228            SerialUtilities.writePaint(this.paint, stream);
229        }
230    
231        /**
232         * Provides serialization support.
233         *
234         * @param stream  the input stream.
235         *
236         * @throws IOException  if there is an I/O error.
237         * @throws ClassNotFoundException  if there is a classpath problem.
238         */
239        private void readObject(ObjectInputStream stream) 
240            throws IOException, ClassNotFoundException {
241            stream.defaultReadObject();
242            this.paint = SerialUtilities.readPaint(stream);
243        }
244     
245    }