    001/* ===========================================================
    002 * JFreeChart : a free chart library for the Java(tm) platform
    003 * ===========================================================
    004 *
    005 * (C) Copyright 2000-2011, 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 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    025 * Other names may be trademarks of their respective owners.]
    026 *
    027 * ------------------------
    028 * RectangleConstraint.java
    029 * ------------------------
    030 * (C) Copyright 2004-2008, 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
    045package org.jfree.chart.block;
    046
    047import org.jfree.data.Range;
    048import org.jfree.ui.Size2D;
    049
    050/**
    051 * A description of a constraint for resizing a rectangle.  Constraints are
    052 * immutable.
    053 */
    054public 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}