KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > chart > block > FlowArrangement


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  * FlowArrangement.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: FlowArrangement.java,v 1.13.2.2 2006/08/04 11:48:41 mungady Exp $
36  *
37  * Changes:
38  * --------
39  * 22-Oct-2004 : Version 1 (DG);
40  * 04-Feb-2005 : Implemented equals() and made serializable (DG);
41  * 08-Feb-2005 : Updated for changes in RectangleConstraint (DG);
42  *
43  */

44
45 package org.jfree.chart.block;
46
47 import java.awt.Graphics2D JavaDoc;
48 import java.awt.geom.Rectangle2D JavaDoc;
49 import java.io.Serializable JavaDoc;
50 import java.util.ArrayList JavaDoc;
51 import java.util.List JavaDoc;
52
53 import org.jfree.ui.HorizontalAlignment;
54 import org.jfree.ui.Size2D;
55 import org.jfree.ui.VerticalAlignment;
56
57 /**
58  * Arranges blocks in a flow layout. This class is immutable.
59  */

60 public class FlowArrangement implements Arrangement, Serializable JavaDoc {
61
62     /** For serialization. */
63     private static final long serialVersionUID = 4543632485478613800L;
64     
65     /** The horizontal alignment of blocks. */
66     private HorizontalAlignment horizontalAlignment;
67     
68     /** The vertical alignment of blocks within each row. */
69     private VerticalAlignment verticalAlignment;
70     
71     /** The horizontal gap between items within rows. */
72     private double horizontalGap;
73     
74     /** The vertical gap between rows. */
75     private double verticalGap;
76     
77     /**
78      * Creates a new instance.
79      */

80     public FlowArrangement() {
81         this(HorizontalAlignment.CENTER, VerticalAlignment.CENTER, 2.0, 2.0);
82     }
83      
84     /**
85      * Creates a new instance.
86      *
87      * @param hAlign the horizontal alignment (currently ignored).
88      * @param vAlign the vertical alignment (currently ignored).
89      * @param hGap the horizontal gap.
90      * @param vGap the vertical gap.
91      */

92     public FlowArrangement(HorizontalAlignment hAlign, VerticalAlignment vAlign,
93                            double hGap, double vGap) {
94         this.horizontalAlignment = hAlign;
95         this.verticalAlignment = vAlign;
96         this.horizontalGap = hGap;
97         this.verticalGap = vGap;
98     }
99     
100     /**
101      * Adds a block to be managed by this instance. This method is usually
102      * called by the {@link BlockContainer}, you shouldn't need to call it
103      * directly.
104      *
105      * @param block the block.
106      * @param key a key that controls the position of the block.
107      */

108     public void add(Block block, Object JavaDoc key) {
109         // since the flow layout is relatively straightforward,
110
// no information needs to be recorded here
111
}
112     
113     /**
114      * Calculates and sets the bounds of all the items in the specified
115      * container, subject to the given constraint. The <code>Graphics2D</code>
116      * can be used by some items (particularly items containing text) to
117      * calculate sizing parameters.
118      *
119      * @param container the container whose items are being arranged.
120      * @param constraint the size constraint.
121      * @param g2 the graphics device.
122      *
123      * @return The size of the container after arrangement of the contents.
124      */

125     public Size2D arrange(BlockContainer container, Graphics2D JavaDoc g2,
126                           RectangleConstraint constraint) {
127         
128         LengthConstraintType w = constraint.getWidthConstraintType();
129         LengthConstraintType h = constraint.getHeightConstraintType();
130         if (w == LengthConstraintType.NONE) {
131             if (h == LengthConstraintType.NONE) {
132                 return arrangeNN(container, g2);
133             }
134             else if (h == LengthConstraintType.FIXED) {
135                 return arrangeNF(container, g2, constraint);
136             }
137             else if (h == LengthConstraintType.RANGE) {
138                 throw new RuntimeException JavaDoc("Not implemented.");
139             }
140         }
141         else if (w == LengthConstraintType.FIXED) {
142             if (h == LengthConstraintType.NONE) {
143                 return arrangeFN(container, g2, constraint);
144             }
145             else if (h == LengthConstraintType.FIXED) {
146                 return arrangeFF(container, g2, constraint);
147             }
148             else if (h == LengthConstraintType.RANGE) {
149                 return arrangeFR(container, g2, constraint);
150             }
151         }
152         else if (w == LengthConstraintType.RANGE) {
153             if (h == LengthConstraintType.NONE) {
154                 return arrangeRN(container, g2, constraint);
155             }
156             else if (h == LengthConstraintType.FIXED) {
157                 return arrangeRF(container, g2, constraint);
158             }
159             else if (h == LengthConstraintType.RANGE) {
160                 return arrangeRR(container, g2, constraint);
161             }
162         }
163         throw new RuntimeException JavaDoc("Unrecognised constraint type.");
164         
165     }
166
167     /**
168      * Arranges the blocks in the container with a fixed width and no height
169      * constraint.
170      *
171      * @param container the container.
172      * @param constraint the constraint.
173      * @param g2 the graphics device.
174      *
175      * @return The size.
176      */

177     protected Size2D arrangeFN(BlockContainer container, Graphics2D JavaDoc g2,
178                                RectangleConstraint constraint) {
179         
180         List JavaDoc blocks = container.getBlocks();
181         double width = constraint.getWidth();
182         
183         double x = 0.0;
184         double y = 0.0;
185         double maxHeight = 0.0;
186         List JavaDoc itemsInRow = new ArrayList JavaDoc();
187         for (int i = 0; i < blocks.size(); i++) {
188             Block block = (Block) blocks.get(i);
189             Size2D size = block.arrange(g2, RectangleConstraint.NONE);
190             if (x + size.width <= width) {
191                 itemsInRow.add(block);
192                 block.setBounds(
193                     new Rectangle2D.Double JavaDoc(x, y, size.width, size.height)
194                 );
195                 x = x + size.width + this.horizontalGap;
196                 maxHeight = Math.max(maxHeight, size.height);
197             }
198             else {
199                 if (itemsInRow.isEmpty()) {
200                     // place in this row (truncated) anyway
201
block.setBounds(
202                         new Rectangle2D.Double JavaDoc(
203                             x, y, Math.min(size.width, width - x), size.height
204                         )
205                     );
206                     x = 0.0;
207                     y = y + size.height + this.verticalGap;
208                 }
209                 else {
210                     // start new row
211
itemsInRow.clear();
212                     x = 0.0;
213                     y = y + maxHeight + this.verticalGap;
214                     maxHeight = size.height;
215                     block.setBounds(
216                         new Rectangle2D.Double JavaDoc(
217                             x, y, Math.min(size.width, width), size.height
218                         )
219                     );
220                     x = size.width + this.horizontalGap;
221                     itemsInRow.add(block);
222                 }
223             }
224         }
225         return new Size2D(constraint.getWidth(), y + maxHeight);
226     }
227     
228     /**
229      * Arranges the blocks in the container with a fixed width and a range
230      * constraint on the height.
231      *
232      * @param container the container.
233      * @param constraint the constraint.
234      * @param g2 the graphics device.
235      *
236      * @return The size following the arrangement.
237      */

238     protected Size2D arrangeFR(BlockContainer container, Graphics2D JavaDoc g2,
239                                RectangleConstraint constraint) {
240
241         Size2D s = arrangeFN(container, g2, constraint);
242         if (constraint.getHeightRange().contains(s.height)) {
243             return s;
244         }
245         else {
246             RectangleConstraint c = constraint.toFixedHeight(
247                 constraint.getHeightRange().constrain(s.getHeight())
248             );
249             return arrangeFF(container, g2, c);
250         }
251     }
252
253     /**
254      * Arranges the blocks in the container with the overall height and width
255      * specified as fixed constraints.
256      *
257      * @param container the container.
258      * @param constraint the constraint.
259      * @param g2 the graphics device.
260      *
261      * @return The size following the arrangement.
262      */

263     protected Size2D arrangeFF(BlockContainer container, Graphics2D JavaDoc g2,
264                                RectangleConstraint constraint) {
265
266         // TODO: implement this properly
267
return arrangeFN(container, g2, constraint);
268     }
269
270     /**
271      * Arranges the blocks with the overall width and height to fit within
272      * specified ranges.
273      *
274      * @param container the container.
275      * @param constraint the constraint.
276      * @param g2 the graphics device.
277      *
278      * @return The size after the arrangement.
279      */

280     protected Size2D arrangeRR(BlockContainer container, Graphics2D JavaDoc g2,
281                                RectangleConstraint constraint) {
282
283         // first arrange without constraints, and see if this fits within
284
// the required ranges...
285
Size2D s1 = arrangeNN(container, g2);
286         if (constraint.getWidthRange().contains(s1.width)) {
287             return s1; // TODO: we didn't check the height yet
288
}
289         else {
290             RectangleConstraint c = constraint.toFixedWidth(
291                 constraint.getWidthRange().getUpperBound()
292             );
293             return arrangeFR(container, g2, c);
294         }
295     }
296     
297     /**
298      * Arranges the blocks in the container with a range constraint on the
299      * width and a fixed height.
300      *
301      * @param container the container.
302      * @param constraint the constraint.
303      * @param g2 the graphics device.
304      *
305      * @return The size following the arrangement.
306      */

307     protected Size2D arrangeRF(BlockContainer container, Graphics2D JavaDoc g2,
308                                RectangleConstraint constraint) {
309
310         Size2D s = arrangeNF(container, g2, constraint);
311         if (constraint.getWidthRange().contains(s.width)) {
312             return s;
313         }
314         else {
315             RectangleConstraint c = constraint.toFixedWidth(
316                 constraint.getWidthRange().constrain(s.getWidth())
317             );
318             return arrangeFF(container, g2, c);
319         }
320     }
321
322     /**
323      * Arranges the block with a range constraint on the width, and no
324      * constraint on the height.
325      *
326      * @param container the container.
327      * @param constraint the constraint.
328      * @param g2 the graphics device.
329      *
330      * @return The size following the arrangement.
331      */

332     protected Size2D arrangeRN(BlockContainer container, Graphics2D JavaDoc g2,
333                                RectangleConstraint constraint) {
334         // first arrange without constraints, then see if the width fits
335
// within the required range...if not, call arrangeFN() at max width
336
Size2D s1 = arrangeNN(container, g2);
337         if (constraint.getWidthRange().contains(s1.width)) {
338             return s1;
339         }
340         else {
341             RectangleConstraint c = constraint.toFixedWidth(
342                 constraint.getWidthRange().getUpperBound()
343             );
344             return arrangeFN(container, g2, c);
345         }
346     }
347     
348     /**
349      * Arranges the blocks without any constraints. This puts all blocks
350      * into a single row.
351      *
352      * @param container the container.
353      * @param g2 the graphics device.
354      *
355      * @return The size after the arrangement.
356      */

357     protected Size2D arrangeNN(BlockContainer container, Graphics2D JavaDoc g2) {
358         double x = 0.0;
359         double width = 0.0;
360         double maxHeight = 0.0;
361         List JavaDoc blocks = container.getBlocks();
362         int blockCount = blocks.size();
363         if (blockCount > 0) {
364             Size2D[] sizes = new Size2D[blocks.size()];
365             for (int i = 0; i < blocks.size(); i++) {
366                 Block block = (Block) blocks.get(i);
367                 sizes[i] = block.arrange(g2, RectangleConstraint.NONE);
368                 width = width + sizes[i].getWidth();
369                 maxHeight = Math.max(sizes[i].height, maxHeight);
370                 block.setBounds(
371                     new Rectangle2D.Double JavaDoc(
372                         x, 0.0, sizes[i].width, sizes[i].height
373                     )
374                 );
375                 x = x + sizes[i].width + this.horizontalGap;
376             }
377             if (blockCount > 1) {
378                 width = width + this.horizontalGap * (blockCount - 1);
379             }
380             if (this.verticalAlignment != VerticalAlignment.TOP) {
381                 for (int i = 0; i < blocks.size(); i++) {
382                     //Block b = (Block) blocks.get(i);
383
if (this.verticalAlignment == VerticalAlignment.CENTER) {
384                         //TODO: shift block down by half
385
}
386                     else if (this.verticalAlignment
387                             == VerticalAlignment.BOTTOM) {
388                         //TODO: shift block down to bottom
389
}
390                 }
391             }
392         }
393         return new Size2D(width, maxHeight);
394     }
395     
396     /**
397      * Arranges the blocks with no width constraint and a fixed height
398      * constraint. This puts all blocks into a single row.
399      *
400      * @param container the container.
401      * @param constraint the constraint.
402      * @param g2 the graphics device.
403      *
404      * @return The size after the arrangement.
405      */

406     protected Size2D arrangeNF(BlockContainer container, Graphics2D JavaDoc g2,
407                                RectangleConstraint constraint) {
408         // TODO: for now we are ignoring the height constraint
409
return arrangeNN(container, g2);
410     }
411     
412     /**
413      * Clears any cached information.
414      */

415     public void clear() {
416         // no action required.
417
}
418     
419     /**
420      * Tests this instance for equality with an arbitrary object.
421      *
422      * @param obj the object (<code>null</code> permitted).
423      *
424      * @return A boolean.
425      */

426     public boolean equals(Object JavaDoc obj) {
427         if (obj == this) {
428             return true;
429         }
430         if (!(obj instanceof FlowArrangement)) {
431             return false;
432         }
433         FlowArrangement that = (FlowArrangement) obj;
434         if (this.horizontalAlignment != that.horizontalAlignment) {
435             return false;
436         }
437         if (this.verticalAlignment != that.verticalAlignment) {
438             return false;
439         }
440         if (this.horizontalGap != that.horizontalGap) {
441             return false;
442         }
443         if (this.verticalGap != that.verticalGap) {
444             return false;
445         }
446         return true;
447     }
448     
449 }
450
Popular Tags