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-2005, 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, 2005, by Object Refinery Limited.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   -;
  34:  *
  35:  * $Id: RectangleConstraint.java,v 1.5.2.1 2005/10/25 20:39:38 mungady Exp $
  36:  *
  37:  * Changes:
  38:  * --------
  39:  * 22-Oct-2004 : Version 1 (DG);
  40:  * 02-Feb-2005 : Added toString() method (DG);
  41:  * 08-Feb-2005 : Separated height and width constraints (DG);
  42:  * 13-May-2005 : Added convenience constructor and new methods for 
  43:  *               transforming constraints (DG);
  44:  * 
  45:  */
  46: 
  47: package org.jfree.chart.block;
  48: 
  49: import org.jfree.data.Range;
  50: import org.jfree.ui.Size2D;
  51: 
  52: /**
  53:  * A description of a constraint for resizing a rectangle.  Constraints are
  54:  * immutable.
  55:  */
  56: public class RectangleConstraint {
  57: 
  58:     /**
  59:      * An instance representing no constraint. 
  60:      */
  61:     public static final RectangleConstraint NONE = new RectangleConstraint(
  62:         0.0, null, LengthConstraintType.NONE, 
  63:         0.0, null, LengthConstraintType.NONE
  64:     );
  65:     
  66:     /** The width. */
  67:     private double width;
  68:     
  69:     /** The width range. */
  70:     private Range widthRange;
  71:     
  72:     /** The width constraint type. */
  73:     private LengthConstraintType widthConstraintType;
  74:     
  75:     /** The fixed or maximum height. */
  76:     private double height;
  77:     
  78:     private Range heightRange;
  79:     
  80:     /** The constraint type. */
  81:     private LengthConstraintType heightConstraintType;
  82:     
  83:     /**
  84:      * Creates a new "fixed width and height" instance.
  85:      * 
  86:      * @param w  the fixed width.
  87:      * @param h  the fixed height.
  88:      */
  89:     public RectangleConstraint(double w, double h) {
  90:         this(
  91:             w, null, LengthConstraintType.FIXED, 
  92:             h, null, LengthConstraintType.FIXED
  93:         );  
  94:     }
  95:     
  96:     /**
  97:      * Creates a new "range width and height" instance.
  98:      * 
  99:      * @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: }