Source for org.jfree.chart.block.RectangleConstraint

   1: /* ===========================================================
   2:  * JFreeChart : a free chart library for the Java(tm) platform
   3:  * ===========================================================
   4:  *
   5:  * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
   6:  *
   7:  * Project Info:  http://www.jfree.org/jfreechart/index.html
   8:  *
   9:  * This library is free software; you can redistribute it and/or modify it 
  10:  * under the terms of the GNU Lesser General Public License as published by 
  11:  * the Free Software Foundation; either version 2.1 of the License, or 
  12:  * (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but 
  15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  16:  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
  17:  * License for more details.
  18:  *
  19:  * You should have received a copy of the GNU Lesser General Public
  20:  * License along with this library; if not, write to the Free Software
  21:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
  22:  * USA.  
  23:  *
  24:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
  25:  * in the United States and other countries.]
  26:  *
  27:  * ------------------------
  28:  * RectangleConstraint.java
  29:  * ------------------------
  30:  * (C) Copyright 2004-2007, by Object Refinery Limited.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   -;
  34:  *
  35:  * Changes:
  36:  * --------
  37:  * 22-Oct-2004 : Version 1 (DG);
  38:  * 02-Feb-2005 : Added toString() method (DG);
  39:  * 08-Feb-2005 : Separated height and width constraints (DG);
  40:  * 13-May-2005 : Added convenience constructor and new methods for 
  41:  *               transforming constraints (DG);
  42:  * 
  43:  */
  44: 
  45: package org.jfree.chart.block;
  46: 
  47: import org.jfree.data.Range;
  48: import org.jfree.ui.Size2D;
  49: 
  50: /**
  51:  * A description of a constraint for resizing a rectangle.  Constraints are
  52:  * immutable.
  53:  */
  54: public class RectangleConstraint {
  55: 
  56:     /**
  57:      * An instance representing no constraint. 
  58:      */
  59:     public static final RectangleConstraint NONE = new RectangleConstraint(
  60:             0.0, null, LengthConstraintType.NONE, 
  61:             0.0, null, LengthConstraintType.NONE);
  62:     
  63:     /** The width. */
  64:     private double width;
  65:     
  66:     /** The width range. */
  67:     private Range widthRange;
  68:     
  69:     /** The width constraint type. */
  70:     private LengthConstraintType widthConstraintType;
  71:     
  72:     /** The fixed or maximum height. */
  73:     private double height;
  74:     
  75:     private Range heightRange;
  76:     
  77:     /** The constraint type. */
  78:     private LengthConstraintType heightConstraintType;
  79:     
  80:     /**
  81:      * Creates a new "fixed width and height" instance.
  82:      * 
  83:      * @param w  the fixed width.
  84:      * @param h  the fixed height.
  85:      */
  86:     public RectangleConstraint(double w, double h) {
  87:         this(w, null, LengthConstraintType.FIXED, 
  88:                 h, null, LengthConstraintType.FIXED);  
  89:     }
  90:     
  91:     /**
  92:      * Creates a new "range width and height" instance.
  93:      * 
  94:      * @param w  the width range.
  95:      * @param h  the height range.
  96:      */
  97:     public RectangleConstraint(Range w, Range h) {
  98:         this(0.0, w, LengthConstraintType.RANGE, 
  99:                 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: }