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