    001    /* ===========================================================
    002     * JFreeChart : a free chart library for the Java(tm) platform
    003     * ===========================================================
    004     *
    005     * (C) Copyright 2000-2008, 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     * AxisSpace.java
    029     * --------------
    030     * (C) Copyright 2003-2008, by Object Refinery Limited and Contributors.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   -;
    034     *
    035     * Changes
    036     * -------
    037     * 03-Jul-2003 : Version 1 (DG);
    038     * 14-Aug-2003 : Implemented Cloneable (DG);
    039     * 18-Aug-2003 : Implemented Serializable (DG);
    040     * 17-Mar-2004 : Added a toString() method for debugging (DG);
    041     * 07-Jan-2005 : Updated equals() method (DG);
    042     * 11-Jan-2005 : Removed deprecated methods in preparation for 1.0.0
    043     *               release (DG);
    044     *
    045     */
    046
    047    package org.jfree.chart.axis;
    048
    049    import java.awt.geom.Rectangle2D;
    050    import java.io.Serializable;
    051
    052    import org.jfree.ui.RectangleEdge;
    053    import org.jfree.util.PublicCloneable;
    054
    055    /**
    056     * A record that contains the space required at each edge of a plot.
    057     */
    058    public class AxisSpace implements Cloneable, PublicCloneable, Serializable {
    059
    060        /** For serialization. */
    061        private static final long serialVersionUID = -2490732595134766305L;
    062
    063        /** The top space. */
    064        private double top;
    065
    066        /** The bottom space. */
    067        private double bottom;
    068
    069        /** The left space. */
    070        private double left;
    071
    072        /** The right space. */
    073        private double right;
    074
    075        /**
    076         * Creates a new axis space record.
    077         */
    078        public AxisSpace() {
    079            this.top = 0.0;
    080            this.bottom = 0.0;
    081            this.left = 0.0;
    082            this.right = 0.0;
    083        }
    084
    085        /**
    086         * Returns the space reserved for axes at the top of the plot area.
    087         *
    088         * @return The space (in Java2D units).
    089         */
    090        public double getTop() {
    091            return this.top;
    092        }
    093
    094        /**
    095         * Sets the space reserved for axes at the top of the plot area.
    096         *
    097         * @param space  the space (in Java2D units).
    098         */
    099        public void setTop(double space) {
    100            this.top = space;
    101        }
    102
    103        /**
    104         * Returns the space reserved for axes at the bottom of the plot area.
    105         *
    106         * @return The space (in Java2D units).
    107         */
    108        public double getBottom() {
    109            return this.bottom;
    110        }
    111
    112        /**
    113         * Sets the space reserved for axes at the bottom of the plot area.
    114         *
    115         * @param space  the space (in Java2D units).
    116         */
    117        public void setBottom(double space) {
    118            this.bottom = space;
    119        }
    120
    121        /**
    122         * Returns the space reserved for axes at the left of the plot area.
    123         *
    124         * @return The space (in Java2D units).
    125         */
    126        public double getLeft() {
    127            return this.left;
    128        }
    129
    130        /**
    131         * Sets the space reserved for axes at the left of the plot area.
    132         *
    133         * @param space  the space (in Java2D units).
    134         */
    135        public void setLeft(double space) {
    136            this.left = space;
    137        }
    138
    139        /**
    140         * Returns the space reserved for axes at the right of the plot area.
    141         *
    142         * @return The space (in Java2D units).
    143         */
    144        public double getRight() {
    145            return this.right;
    146        }
    147
    148        /**
    149         * Sets the space reserved for axes at the right of the plot area.
    150         *
    151         * @param space  the space (in Java2D units).
    152         */
    153        public void setRight(double space) {
    154            this.right = space;
    155        }
    156
    157        /**
    158         * Adds space to the top, bottom, left or right edge of the plot area.
    159         *
    160         * @param space  the space (in Java2D units).
    161         * @param edge  the edge (<code>null</code> not permitted).
    162         */
    163        public void add(double space, RectangleEdge edge) {
    164            if (edge == null) {
    165                throw new IllegalArgumentException("Null 'edge' argument.");
    166            }
    167            if (edge == RectangleEdge.TOP) {
    168                this.top += space;
    169            }
    170            else if (edge == RectangleEdge.BOTTOM) {
    171                this.bottom += space;
    172            }
    173            else if (edge == RectangleEdge.LEFT) {
    174                this.left += space;
    175            }
    176            else if (edge == RectangleEdge.RIGHT) {
    177                this.right += space;
    178            }
    179            else {
    180                throw new IllegalStateException("Unrecognised 'edge' argument.");
    181            }
    182        }
    183
    184        /**
    185         * Ensures that this object reserves at least as much space as another.
    186         *
    187         * @param space  the other space.
    188         */
    189        public void ensureAtLeast(AxisSpace space) {
    190            this.top = Math.max(this.top, space.top);
    191            this.bottom = Math.max(this.bottom, space.bottom);
    192            this.left = Math.max(this.left, space.left);
    193            this.right = Math.max(this.right, space.right);
    194        }
    195
    196        /**
    197         * Ensures there is a minimum amount of space at the edge corresponding to
    198         * the specified axis location.
    199         *
    200         * @param space  the space.
    201         * @param edge  the location.
    202         */
    203        public void ensureAtLeast(double space, RectangleEdge edge) {
    204            if (edge == RectangleEdge.TOP) {
    205                if (this.top < space) {
    206                    this.top = space;
    207                }
    208            }
    209            else if (edge == RectangleEdge.BOTTOM) {
    210                if (this.bottom < space) {
    211                    this.bottom = space;
    212                }
    213            }
    214            else if (edge == RectangleEdge.LEFT) {
    215                if (this.left < space) {
    216                    this.left = space;
    217                }
    218            }
    219            else if (edge == RectangleEdge.RIGHT) {
    220                if (this.right < space) {
    221                    this.right = space;
    222                }
    223            }
    224            else {
    225                throw new IllegalStateException(
    226                    "AxisSpace.ensureAtLeast(): unrecognised AxisLocation."
    227                );
    228            }
    229        }
    230
    231        /**
    232         * Shrinks an area by the space attributes.
    233         *
    234         * @param area  the area to shrink.
    235         * @param result  an optional carrier for the result.
    236         *
    237         * @return The result.
    238         */
    239        public Rectangle2D shrink(Rectangle2D area, Rectangle2D result) {
    240            if (result == null) {
    241                result = new Rectangle2D.Double();
    242            }
    243            result.setRect(
    244                area.getX() + this.left,
    245                area.getY() + this.top,
    246                area.getWidth() - this.left - this.right,
    247                area.getHeight() - this.top - this.bottom
    248            );
    249            return result;
    250        }
    251
    252        /**
    253         * Expands an area by the amount of space represented by this object.
    254         *
    255         * @param area  the area to expand.
    256         * @param result  an optional carrier for the result.
    257         *
    258         * @return The result.
    259         */
    260        public Rectangle2D expand(Rectangle2D area, Rectangle2D result) {
    261            if (result == null) {
    262                result = new Rectangle2D.Double();
    263            }
    264            result.setRect(
    265                area.getX() - this.left,
    266                area.getY() - this.top,
    267                area.getWidth() + this.left + this.right,
    268                area.getHeight() + this.top + this.bottom
    269            );
    270            return result;
    271        }
    272
    273        /**
    274         * Calculates the reserved area.
    275         *
    276         * @param area  the area.
    277         * @param edge  the edge.
    278         *
    279         * @return The reserved area.
    280         */
    281        public Rectangle2D reserved(Rectangle2D area, RectangleEdge edge) {
    282            Rectangle2D result = null;
    283            if (edge == RectangleEdge.TOP) {
    284                result = new Rectangle2D.Double(
    285                    area.getX(), area.getY(), area.getWidth(), this.top
    286                );
    287            }
    288            else if (edge == RectangleEdge.BOTTOM) {
    289                result = new Rectangle2D.Double(
    290                    area.getX(), area.getMaxY() - this.top,
    291                    area.getWidth(), this.bottom
    292                );
    293            }
    294            else if (edge == RectangleEdge.LEFT) {
    295                result = new Rectangle2D.Double(
    296                    area.getX(), area.getY(), this.left, area.getHeight()
    297                );
    298            }
    299            else if (edge == RectangleEdge.RIGHT) {
    300                result = new Rectangle2D.Double(
    301                    area.getMaxX() - this.right, area.getY(),
    302                    this.right, area.getHeight()
    303                );
    304            }
    305            return result;
    306        }
    307
    308        /**
    309         * Returns a clone of the object.
    310         *
    311         * @return A clone.
    312         *
    313         * @throws CloneNotSupportedException This class won't throw this exception,
    314         *         but subclasses (if any) might.
    315         */
    316        public Object clone() throws CloneNotSupportedException {
    317            return super.clone();
    318        }
    319
    320        /**
    321         * Tests this object for equality with another object.
    322         *
    323         * @param obj  the object to compare against.
    324         *
    325         * @return <code>true</code> or <code>false</code>.
    326         */
    327        public boolean equals(Object obj) {
    328            if (obj == this) {
    329                return true;
    330            }
    331            if (!(obj instanceof AxisSpace)) {
    332                return false;
    333            }
    334            AxisSpace that = (AxisSpace) obj;
    335            if (this.top != that.top) {
    336                return false;
    337            }
    338            if (this.bottom != that.bottom) {
    339                return false;
    340            }
    341            if (this.left != that.left) {
    342                return false;
    343            }
    344            if (this.right != that.right) {
    345                return false;
    346            }
    347            return true;
    348        }
    349
    350        /**
    351         * Returns a hash code for this object.
    352         *
    353         * @return A hash code.
    354         */
    355        public int hashCode() {
    356            int result = 23;
    357            long l = Double.doubleToLongBits(this.top);
    358            result = 37 * result + (int) (l ^ (l >>> 32));
    359            l = Double.doubleToLongBits(this.bottom);
    360            result = 37 * result + (int) (l ^ (l >>> 32));
    361            l = Double.doubleToLongBits(this.left);
    362            result = 37 * result + (int) (l ^ (l >>> 32));
    363            l = Double.doubleToLongBits(this.right);
    364            result = 37 * result + (int) (l ^ (l >>> 32));
    365            return result;
    366        }
    367
    368        /**
    369         * Returns a string representing the object (for debugging purposes).
    370         *
    371         * @return A string.
    372         */
    373        public String toString() {
    374            return super.toString() + "[left=" + this.left + ",right=" + this.right
    375                        + ",top=" + this.top + ",bottom=" + this.bottom + "]";
    376        }
    377
    378    }