    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     * RectangleConstraint.java
    029     * ------------------------
    030     * (C) Copyright 2004, 2005, by Object Refinery Limited.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   -;
    034     *
    035     * $Id: RectangleConstraint.java,v 1.5.2.1 2005/10/25 20:39:38 mungady Exp $
    036     *
    037     * Changes:
    038     * --------
    039     * 22-Oct-2004 : Version 1 (DG);
    040     * 02-Feb-2005 : Added toString() method (DG);
    041     * 08-Feb-2005 : Separated height and width constraints (DG);
    042     * 13-May-2005 : Added convenience constructor and new methods for
    043     *               transforming constraints (DG);
    044     *
    045     */
    046
    047    package org.jfree.chart.block;
    048
    049    import org.jfree.data.Range;
    050    import org.jfree.ui.Size2D;
    051
    052    /**
    053     * A description of a constraint for resizing a rectangle.  Constraints are
    054     * immutable.
    055     */
    056    public class RectangleConstraint {
    057
    058        /**
    059         * An instance representing no constraint.
    060         */
    061        public static final RectangleConstraint NONE = new RectangleConstraint(
    062            0.0, null, LengthConstraintType.NONE,
    063            0.0, null, LengthConstraintType.NONE
    064        );
    065
    066        /** The width. */
    067        private double width;
    068
    069        /** The width range. */
    070        private Range widthRange;
    071
    072        /** The width constraint type. */
    073        private LengthConstraintType widthConstraintType;
    074
    075        /** The fixed or maximum height. */
    076        private double height;
    077
    078        private Range heightRange;
    079
    080        /** The constraint type. */
    081        private LengthConstraintType heightConstraintType;
    082
    083        /**
    084         * Creates a new "fixed width and height" instance.
    085         *
    086         * @param w  the fixed width.
    087         * @param h  the fixed height.
    088         */
    089        public RectangleConstraint(double w, double h) {
    090            this(
    091                w, null, LengthConstraintType.FIXED,
    092                h, null, LengthConstraintType.FIXED
    093            );
    094        }
    095
    096        /**
    097         * Creates a new "range width and height" instance.
    098         *
    099         * @param w  the width range.
    100         * @param h  the height range.
    101         */
    102        public RectangleConstraint(Range w, Range h) {
    103            this(
    104                0.0, w, LengthConstraintType.RANGE,
    105                0.0, h, LengthConstraintType.RANGE
    106            );
    107        }
    108
    109        /**
    110         * Creates a new constraint with a range for the width and a
    111         * fixed height.
    112         *
    113         * @param w  the width range.
    114         * @param h  the fixed height.
    115         */
    116        public RectangleConstraint(Range w, double h) {
    117            this(
    118                0.0, w, LengthConstraintType.RANGE,
    119                h, null, LengthConstraintType.FIXED
    120            );
    121        }
    122
    123        /**
    124         * Creates a new constraint with a fixed width and a range for
    125         * the height.
    126         *
    127         * @param w  the fixed width.
    128         * @param h  the height range.
    129         */
    130        public RectangleConstraint(double w, Range h) {
    131            this(
    132                w, null, LengthConstraintType.FIXED,
    133                0.0, h, LengthConstraintType.RANGE
    134            );
    135        }
    136
    137        /**
    138         * Creates a new constraint.
    139         *
    140         * @param w  the fixed or maximum width.
    141         * @param widthRange  the width range.
    142         * @param widthConstraintType  the width type.
    143         * @param h  the fixed or maximum height.
    144         * @param heightRange  the height range.
    145         * @param heightConstraintType  the height type.
    146         */
    147        public RectangleConstraint(double w, Range widthRange,
    148                                   LengthConstraintType widthConstraintType,
    149                                   double h, Range heightRange,
    150                                   LengthConstraintType heightConstraintType) {
    151            if (widthConstraintType == null) {
    152                throw new IllegalArgumentException("Null 'widthType' argument.");
    153            }
    154            if (heightConstraintType == null) {
    155                throw new IllegalArgumentException("Null 'heightType' argument.");
    156            }
    157            this.width = w;
    158            this.widthRange = widthRange;
    159            this.widthConstraintType = widthConstraintType;
    160            this.height = h;
    161            this.heightRange = heightRange;
    162            this.heightConstraintType = heightConstraintType;
    163        }
    164
    165        /**
    166         * Returns the fixed width.
    167         *
    168         * @return The width.
    169         */
    170        public double getWidth() {
    171            return this.width;
    172        }
    173
    174        /**
    175         * Returns the width range.
    176         *
    177         * @return The range (possibly <code>null</code>).
    178         */
    179        public Range getWidthRange() {
    180            return this.widthRange;
    181        }
    182
    183        /**
    184         * Returns the constraint type.
    185         *
    186         * @return The constraint type (never <code>null</code>).
    187         */
    188        public LengthConstraintType getWidthConstraintType() {
    189            return this.widthConstraintType;
    190        }
    191
    192        /**
    193         * Returns the fixed height.
    194         *
    195         * @return The height.
    196         */
    197        public double getHeight() {
    198            return this.height;
    199        }
    200
    201        /**
    202         * Returns the width range.
    203         *
    204         * @return The range (possibly <code>null</code>).
    205         */
    206        public Range getHeightRange() {
    207            return this.heightRange;
    208        }
    209
    210        /**
    211         * Returns the constraint type.
    212         *
    213         * @return The constraint type (never <code>null</code>).
    214         */
    215        public LengthConstraintType getHeightConstraintType() {
    216            return this.heightConstraintType;
    217        }
    218
    219        /**
    220         * Returns a constraint that matches this one on the height attributes,
    221         * but has no width constraint.
    222         *
    223         * @return A new constraint.
    224         */
    225        public RectangleConstraint toUnconstrainedWidth() {
    226            if (this.widthConstraintType == LengthConstraintType.NONE) {
    227                return this;
    228            }
    229            else {
    230                return new RectangleConstraint(
    231                    this.width, this.widthRange, LengthConstraintType.NONE,
    232                    this.height, this.heightRange, this.heightConstraintType
    233                );
    234            }
    235        }
    236
    237        /**
    238         * Returns a constraint that matches this one on the width attributes,
    239         * but has no height constraint.
    240         *
    241         * @return A new constraint.
    242         */
    243        public RectangleConstraint toUnconstrainedHeight() {
    244            if (this.heightConstraintType == LengthConstraintType.NONE) {
    245                return this;
    246            }
    247            else {
    248                return new RectangleConstraint(
    249                    this.width, this.widthRange, this.widthConstraintType,
    250                    0.0, this.heightRange, LengthConstraintType.NONE
    251                );
    252            }
    253        }
    254
    255        /**
    256         * Returns a constraint that matches this one on the height attributes,
    257         * but has a fixed width constraint.
    258         *
    259         * @param width  the fixed width.
    260         *
    261         * @return A new constraint.
    262         */
    263        public RectangleConstraint toFixedWidth(double width) {
    264            return new RectangleConstraint(
    265                width, this.widthRange, LengthConstraintType.FIXED,
    266                this.height, this.heightRange, this.heightConstraintType
    267            );
    268        }
    269
    270        /**
    271         * Returns a constraint that matches this one on the width attributes,
    272         * but has a fixed height constraint.
    273         *
    274         * @param height  the fixed height.
    275         *
    276         * @return A new constraint.
    277         */
    278        public RectangleConstraint toFixedHeight(double height) {
    279            return new RectangleConstraint(
    280                this.width, this.widthRange, this.widthConstraintType,
    281                height, this.heightRange, LengthConstraintType.FIXED
    282            );
    283        }
    284
    285        /**
    286         * Returns a constraint that matches this one on the height attributes,
    287         * but has a range width constraint.
    288         *
    289         * @param range  the width range (<code>null</code> not permitted).
    290         *
    291         * @return A new constraint.
    292         */
    293        public RectangleConstraint toRangeWidth(Range range) {
    294            if (range == null) {
    295                throw new IllegalArgumentException("Null 'range' argument.");
    296            }
    297            return new RectangleConstraint(
    298                range.getUpperBound(), range, LengthConstraintType.RANGE,
    299                this.height, this.heightRange, this.heightConstraintType
    300            );
    301        }
    302
    303        /**
    304         * Returns a constraint that matches this one on the width attributes,
    305         * but has a range height constraint.
    306         *
    307         * @param range  the height range (<code>null</code> not permitted).
    308         *
    309         * @return A new constraint.
    310         */
    311        public RectangleConstraint toRangeHeight(Range range) {
    312            if (range == null) {
    313                throw new IllegalArgumentException("Null 'range' argument.");
    314            }
    315            return new RectangleConstraint(
    316                this.width, this.widthRange, this.widthConstraintType,
    317                range.getUpperBound(), range, LengthConstraintType.RANGE
    318            );
    319        }
    320
    321        /**
    322         * Returns a string representation of this instance, mostly used for
    323         * debugging purposes.
    324         *
    325         * @return A string.
    326         */
    327        public String toString() {
    328            return "RectangleConstraint["
    329                + this.widthConstraintType.toString() + ": width="
    330                + this.width + ", height=" + this.height + "]";
    331        }
    332
    333        /**
    334         * Returns the new size that reflects the constraints defined by this
    335         * instance.
    336         *
    337         * @param base  the base size.
    338         *
    339         * @return The constrained size.
    340         */
    341        public Size2D calculateConstrainedSize(Size2D base) {
    342            Size2D result = new Size2D();
    343            if (this.widthConstraintType == LengthConstraintType.NONE) {
    344                result.width = base.width;
    345                if (this.heightConstraintType == LengthConstraintType.NONE) {
    346                   result.height = base.height;
    347                }
    348                else if (this.heightConstraintType == LengthConstraintType.RANGE) {
    349                   result.height = this.heightRange.constrain(base.height);
    350                }
    351                else if (this.heightConstraintType == LengthConstraintType.FIXED) {
    352                   result.height = this.height;
    353                }
    354            }
    355            else if (this.widthConstraintType == LengthConstraintType.RANGE) {
    356                result.width = this.widthRange.constrain(base.width);
    357                if (this.heightConstraintType == LengthConstraintType.NONE) {
    358                    result.height = base.height;
    359                }
    360                else if (this.heightConstraintType == LengthConstraintType.RANGE) {
    361                    result.height = this.heightRange.constrain(base.height);
    362                }
    363                else if (this.heightConstraintType == LengthConstraintType.FIXED) {
    364                    result.height = this.height;
    365                }
    366            }
    367            else if (this.widthConstraintType == LengthConstraintType.FIXED) {
    368                result.width = this.width;
    369                if (this.heightConstraintType == LengthConstraintType.NONE) {
    370                    result.height = base.height;
    371                }
    372                else if (this.heightConstraintType == LengthConstraintType.RANGE) {
    373                    result.height = this.heightRange.constrain(base.height);
    374                }
    375                else if (this.heightConstraintType == LengthConstraintType.FIXED) {
    376                    result.height = this.height;
    377                }
    378            }
    379            return result;
    380        }
    381
    382    }