001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2005, 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, 2005, by Object Refinery Limited.
031 *
032 * Original Author: David Gilbert (for Object Refinery Limited);
033 * Contributor(s): -;
034 *
035 * $Id: RectangleConstraint.java,v 1.5.2.1 2005/10/25 20:39:38 mungady Exp $
036 *
037 * Changes:
038 * --------
039 * 22-Oct-2004 : Version 1 (DG);
040 * 02-Feb-2005 : Added toString() method (DG);
041 * 08-Feb-2005 : Separated height and width constraints (DG);
042 * 13-May-2005 : Added convenience constructor and new methods for
043 * transforming constraints (DG);
044 *
045 */
046
047 package org.jfree.chart.block;
048
049 import org.jfree.data.Range;
050 import org.jfree.ui.Size2D;
051
052 /**
053 * A description of a constraint for resizing a rectangle. Constraints are
054 * immutable.
055 */
056 public class RectangleConstraint {
057
058 /**
059 * An instance representing no constraint.
060 */
061 public static final RectangleConstraint NONE = new RectangleConstraint(
062 0.0, null, LengthConstraintType.NONE,
063 0.0, null, LengthConstraintType.NONE
064 );
065
066 /** The width. */
067 private double width;
068
069 /** The width range. */
070 private Range widthRange;
071
072 /** The width constraint type. */
073 private LengthConstraintType widthConstraintType;
074
075 /** The fixed or maximum height. */
076 private double height;
077
078 private Range heightRange;
079
080 /** The constraint type. */
081 private LengthConstraintType heightConstraintType;
082
083 /**
084 * Creates a new "fixed width and height" instance.
085 *
086 * @param w the fixed width.
087 * @param h the fixed height.
088 */
089 public RectangleConstraint(double w, double h) {
090 this(
091 w, null, LengthConstraintType.FIXED,
092 h, null, LengthConstraintType.FIXED
093 );
094 }
095
096 /**
097 * Creates a new "range width and height" instance.
098 *
099 * @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 }