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