001    /* ========================================================================
002     * JCommon : a free general purpose class 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/jcommon/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     * RectangleAnchor.java
029     * --------------------
030     * (C) Copyright 2003-2005, by Object Refinery Limited.
031     *
032     * Original Author:  David Gilbert (for Object Refinery Limited);
033     * Contributor(s):   -;
034     *
035     * $Id: RectangleAnchor.java,v 1.6 2005/10/18 13:18:34 mungady Exp $
036     *
037     * Changes:
038     * --------
039     * 31-Oct-2003 (DG);
040     * 01-Apr-2004 : Changed java.awt.geom.Dimension2D to org.jfree.ui.Size2D 
041     *               because of JDK bug 4976448 which persists on JDK 1.3.1 (DG);
042     * 21-Jan-2005 : Changed return type of coordinates() method (DG);
043     * 
044     */
045    
046    package org.jfree.ui;
047    
048    import java.awt.geom.Point2D;
049    import java.awt.geom.Rectangle2D;
050    import java.io.ObjectStreamException;
051    import java.io.Serializable;
052    
053    /**
054     * Used to indicate an anchor point for a rectangle.
055     *
056     * @author David Gilbert
057     */
058    public final class RectangleAnchor implements Serializable {
059    
060        /** For serialization. */
061        private static final long serialVersionUID = -2457494205644416327L;
062        
063        /** Center. */
064        public static final RectangleAnchor CENTER 
065            = new RectangleAnchor("RectangleAnchor.CENTER");
066    
067        /** Top. */
068        public static final RectangleAnchor TOP 
069            = new RectangleAnchor("RectangleAnchor.TOP");
070    
071        /** Top-Left. */
072        public static final RectangleAnchor TOP_LEFT 
073            = new RectangleAnchor("RectangleAnchor.TOP_LEFT");
074    
075        /** Top-Right. */
076        public static final RectangleAnchor TOP_RIGHT 
077            = new RectangleAnchor("RectangleAnchor.TOP_RIGHT");
078    
079        /** Bottom. */
080        public static final RectangleAnchor BOTTOM 
081            = new RectangleAnchor("RectangleAnchor.BOTTOM");
082    
083        /** Bottom-Left. */
084        public static final RectangleAnchor BOTTOM_LEFT 
085            = new RectangleAnchor("RectangleAnchor.BOTTOM_LEFT");
086    
087        /** Bottom-Right. */
088        public static final RectangleAnchor BOTTOM_RIGHT 
089            = new RectangleAnchor("RectangleAnchor.BOTTOM_RIGHT");
090    
091        /** Left. */
092        public static final RectangleAnchor LEFT 
093            = new RectangleAnchor("RectangleAnchor.LEFT");
094    
095        /** Right. */
096        public static final RectangleAnchor RIGHT 
097            = new RectangleAnchor("RectangleAnchor.RIGHT");
098    
099        /** The name. */
100        private String name;
101    
102        /**
103         * Private constructor.
104         *
105         * @param name  the name.
106         */
107        private RectangleAnchor(final String name) {
108            this.name = name;
109        }
110    
111        /**
112         * Returns a string representing the object.
113         *
114         * @return The string.
115         */
116        public String toString() {
117            return this.name;
118        }
119    
120        /**
121         * Returns <code>true</code> if this object is equal to the specified 
122         * object, and <code>false</code> otherwise.
123         *
124         * @param obj  the other object (<code>null</code> permitted).
125         *
126         * @return A boolean.
127         */
128        public boolean equals(final Object obj) {
129    
130            if (this == obj) {
131                return true;
132            }
133            if (!(obj instanceof RectangleAnchor)) {
134                return false;
135            }
136    
137            final RectangleAnchor order = (RectangleAnchor) obj;
138            if (!this.name.equals(order.name)) {
139                return false;
140            }
141    
142            return true;
143        }
144    
145        /**
146         * Returns a hash code value for the object.
147         *
148         * @return The hashcode
149         */
150        public int hashCode() {
151            return this.name.hashCode();
152        }
153    
154        /**
155         * Returns the (x, y) coordinates of the specified anchor.
156         * 
157         * @param rectangle  the rectangle.
158         * @param anchor  the anchor.
159         * 
160         * @return The (x, y) coordinates.
161         */
162        public static Point2D coordinates(final Rectangle2D rectangle, 
163                                          final RectangleAnchor anchor) {
164            Point2D result = new Point2D.Double();
165            if (anchor == RectangleAnchor.CENTER) {
166                result.setLocation(rectangle.getCenterX(), rectangle.getCenterY());
167            }
168            else if (anchor == RectangleAnchor.TOP) {
169                result.setLocation(rectangle.getCenterX(), rectangle.getMinY());
170            }
171            else if (anchor == RectangleAnchor.BOTTOM) {
172                result.setLocation(rectangle.getCenterX(), rectangle.getMaxY());
173            }
174            else if (anchor == RectangleAnchor.LEFT) {
175                result.setLocation(rectangle.getMinX(), rectangle.getCenterY());
176            }
177            else if (anchor == RectangleAnchor.RIGHT) {
178                result.setLocation(rectangle.getMaxX(), rectangle.getCenterY());
179            }
180            else if (anchor == RectangleAnchor.TOP_LEFT) {
181                result.setLocation(rectangle.getMinX(), rectangle.getMinY());
182            }
183            else if (anchor == RectangleAnchor.TOP_RIGHT) {
184                result.setLocation(rectangle.getMaxX(), rectangle.getMinY());
185            }
186            else if (anchor == RectangleAnchor.BOTTOM_LEFT) {
187                result.setLocation(rectangle.getMinX(), rectangle.getMaxY());
188            }
189            else if (anchor == RectangleAnchor.BOTTOM_RIGHT) {
190                result.setLocation(rectangle.getMaxX(), rectangle.getMaxY());
191            }
192            return result;
193        }
194        
195        /**
196         * Creates a new rectangle with the specified dimensions that is aligned to
197         * the given anchor point <code>(anchorX, anchorY)</code>.
198         * 
199         * @param dimensions  the dimensions (<code>null</code> not permitted).
200         * @param anchorX  the x-anchor.
201         * @param anchorY  the y-anchor.
202         * @param anchor  the anchor (<code>null</code> not permitted).
203         * 
204         * @return A rectangle.
205         */
206        public static Rectangle2D createRectangle(final Size2D dimensions,
207                                                  final double anchorX,
208                                                  final double anchorY,
209                                                  final RectangleAnchor anchor) {
210            Rectangle2D result = null;
211            final double w = dimensions.getWidth();
212            final double h = dimensions.getHeight();
213            if (anchor == RectangleAnchor.CENTER) {
214                result = new Rectangle2D.Double(
215                    anchorX - w / 2.0, anchorY - h / 2.0, w, h
216                );
217            }
218            else if (anchor == RectangleAnchor.TOP) {
219                result = new Rectangle2D.Double(
220                    anchorX - w / 2.0, anchorY - h / 2.0, w, h
221                );
222            }
223            else if (anchor == RectangleAnchor.BOTTOM) {
224                result = new Rectangle2D.Double(
225                    anchorX - w / 2.0, anchorY - h / 2.0, w, h
226                );
227            }
228            else if (anchor == RectangleAnchor.LEFT) {
229                result = new Rectangle2D.Double(
230                    anchorX, anchorY - h / 2.0, w, h
231                );
232            }
233            else if (anchor == RectangleAnchor.RIGHT) {
234                result = new Rectangle2D.Double(
235                    anchorX - w, anchorY - h / 2.0, w, h
236                );
237            }
238            else if (anchor == RectangleAnchor.TOP_LEFT) {
239                result = new Rectangle2D.Double(
240                    anchorX - w / 2.0, anchorY - h / 2.0, w, h
241                );
242            }
243            else if (anchor == RectangleAnchor.TOP_RIGHT) {
244                result = new Rectangle2D.Double(
245                    anchorX - w / 2.0, anchorY - h / 2.0, w, h
246                );
247            }
248            else if (anchor == RectangleAnchor.BOTTOM_LEFT) {
249                result = new Rectangle2D.Double(
250                    anchorX - w / 2.0, anchorY - h / 2.0, w, h
251                );
252            }
253            else if (anchor == RectangleAnchor.BOTTOM_RIGHT) {
254                result = new Rectangle2D.Double(
255                    anchorX - w / 2.0, anchorY - h / 2.0, w, h
256                );
257            }
258            return result;
259        }
260        
261        /**
262         * Ensures that serialization returns the unique instances.
263         * 
264         * @return The object.
265         * 
266         * @throws ObjectStreamException if there is a problem.
267         */
268        private Object readResolve() throws ObjectStreamException {
269            RectangleAnchor result = null;
270            if (this.equals(RectangleAnchor.CENTER)) {
271                result = RectangleAnchor.CENTER;
272            }
273            else if (this.equals(RectangleAnchor.TOP)) {
274                result = RectangleAnchor.TOP;
275            }
276            else if (this.equals(RectangleAnchor.BOTTOM)) {
277                result = RectangleAnchor.BOTTOM;
278            }
279            else if (this.equals(RectangleAnchor.LEFT)) {
280                result = RectangleAnchor.LEFT;
281            }
282            else if (this.equals(RectangleAnchor.RIGHT)) {
283                result = RectangleAnchor.RIGHT;
284            }
285            else if (this.equals(RectangleAnchor.TOP_LEFT)) {
286                result = RectangleAnchor.TOP_LEFT;
287            }
288            else if (this.equals(RectangleAnchor.TOP_RIGHT)) {
289                result = RectangleAnchor.TOP_RIGHT;
290            }
291            else if (this.equals(RectangleAnchor.BOTTOM_LEFT)) {
292                result = RectangleAnchor.BOTTOM_LEFT;
293            }
294            else if (this.equals(RectangleAnchor.BOTTOM_RIGHT)) {
295                result = RectangleAnchor.BOTTOM_RIGHT;
296            }
297            return result;
298        }
299        
300    }