001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2008, 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-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
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 }