KickJava   Java API By Example, From Geeks To Geeks.

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


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  * BorderArrangement.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: BorderArrangement.java,v 1.14.2.1 2005/10/25 20:39:38 mungady Exp $
36  *
37  * Changes:
38  * --------
39  * 22-Oct-2004 : Version 1 (DG);
40  * 08-Feb-2005 : Updated for changes in RectangleConstraint (DG);
41  * 24-Feb-2005 : Improved arrangeRR() method (DG);
42  * 03-May-2005 : Implemented Serializable and added equals() method (DG);
43  * 13-May-2005 : Fixed bugs in the arrange() method (DG);
44  *
45  */

46
47 package org.jfree.chart.block;
48
49 import java.awt.Graphics2D JavaDoc;
50 import java.awt.geom.Rectangle2D JavaDoc;
51 import java.io.Serializable JavaDoc;
52
53 import org.jfree.data.Range;
54 import org.jfree.ui.RectangleEdge;
55 import org.jfree.ui.Size2D;
56 import org.jfree.util.ObjectUtilities;
57
58 /**
59  * An arrangement manager that lays out blocks in a similar way to
60  * Swing's BorderLayout class.
61  */

62 public class BorderArrangement implements Arrangement, Serializable JavaDoc {
63     
64     /** For serialization. */
65     private static final long serialVersionUID = 506071142274883745L;
66     
67     /** The block (if any) at the center of the layout. */
68     private Block centerBlock;
69
70     /** The block (if any) at the top of the layout. */
71     private Block topBlock;
72     
73     /** The block (if any) at the bottom of the layout. */
74     private Block bottomBlock;
75     
76     /** The block (if any) at the left of the layout. */
77     private Block leftBlock;
78     
79     /** The block (if any) at the right of the layout. */
80     private Block rightBlock;
81     
82     /**
83      * Creates a new instance.
84      */

85     public BorderArrangement() {
86     }
87     
88     /**
89      * Adds a block to the arrangement manager at the specified edge.
90      *
91      * @param block the block (<code>null</code> permitted).
92      * @param key the edge (an instance of {@link RectangleEdge}) or
93      * <code>null</code> for the center block.
94      */

95     public void add(Block block, Object JavaDoc key) {
96         
97         if (key == null) {
98             this.centerBlock = block;
99         }
100         else {
101             RectangleEdge edge = (RectangleEdge) key;
102             if (edge == RectangleEdge.TOP) {
103                 this.topBlock = block;
104             }
105             else if (edge == RectangleEdge.BOTTOM) {
106                 this.bottomBlock = block;
107             }
108             else if (edge == RectangleEdge.LEFT) {
109                 this.leftBlock = block;
110             }
111             else if (edge == RectangleEdge.RIGHT) {
112                 this.rightBlock = block;
113             }
114         }
115     }
116     
117     /**
118      * Arranges the items in the specified container, subject to the given
119      * constraint.
120      *
121      * @param container the container.
122      * @param g2 the graphics device.
123      * @param constraint the constraint.
124      *
125      * @return The block size.
126      */

127     public Size2D arrange(BlockContainer container,
128                           Graphics2D JavaDoc g2,
129                           RectangleConstraint constraint) {
130         RectangleConstraint contentConstraint
131             = container.toContentConstraint(constraint);
132         Size2D contentSize = null;
133         LengthConstraintType w = contentConstraint.getWidthConstraintType();
134         LengthConstraintType h = contentConstraint.getHeightConstraintType();
135         if (w == LengthConstraintType.NONE) {
136             if (h == LengthConstraintType.NONE) {
137                 contentSize = arrangeNN(container, g2);
138             }
139             else if (h == LengthConstraintType.FIXED) {
140                 throw new RuntimeException JavaDoc("Not implemented.");
141             }
142             else if (h == LengthConstraintType.RANGE) {
143                 throw new RuntimeException JavaDoc("Not implemented.");
144             }
145         }
146         else if (w == LengthConstraintType.FIXED) {
147             if (h == LengthConstraintType.NONE) {
148                 contentSize = arrangeFN(container, g2, constraint.getWidth());
149             }
150             else if (h == LengthConstraintType.FIXED) {
151                 contentSize = arrangeFF(container, g2, constraint);
152             }
153             else if (h == LengthConstraintType.RANGE) {
154                 contentSize = arrangeFR(container, g2, constraint);
155             }
156         }
157         else if (w == LengthConstraintType.RANGE) {
158             if (h == LengthConstraintType.NONE) {
159                 throw new RuntimeException JavaDoc("Not implemented.");
160             }
161             else if (h == LengthConstraintType.FIXED) {
162                 throw new RuntimeException JavaDoc("Not implemented.");
163             }
164             else if (h == LengthConstraintType.RANGE) {
165                 contentSize = arrangeRR(
166                     container, constraint.getWidthRange(),
167                     constraint.getHeightRange(), g2
168                 );
169             }
170         }
171         return new Size2D(
172             container.calculateTotalWidth(contentSize.getWidth()),
173             container.calculateTotalHeight(contentSize.getHeight())
174         );
175     }
176     
177     /**
178      * Performs an arrangement without constraints.
179      *
180      * @param container the container.
181      * @param g2 the graphics device.
182      *
183      * @return The container size after the arrangement.
184      */

185     protected Size2D arrangeNN(BlockContainer container, Graphics2D JavaDoc g2) {
186         double[] w = new double[5];
187         double[] h = new double[5];
188         if (this.topBlock != null) {
189             Size2D size = this.topBlock.arrange(
190                 g2, RectangleConstraint.NONE
191             );
192             w[0] = size.width;
193             h[0] = size.height;
194         }
195         if (this.bottomBlock != null) {
196             Size2D size = this.bottomBlock.arrange(
197                 g2, RectangleConstraint.NONE
198             );
199             w[1] = size.width;
200             h[1] = size.height;
201         }
202         if (this.leftBlock != null) {
203             Size2D size = this.leftBlock.arrange(
204                 g2, RectangleConstraint.NONE
205             );
206             w[2] = size.width;
207             h[2] = size.height;
208        }
209         if (this.rightBlock != null) {
210             Size2D size = this.rightBlock.arrange(
211                 g2, RectangleConstraint.NONE
212             );
213             w[3] = size.width;
214             h[3] = size.height;
215         }
216         
217         h[2] = Math.max(h[2], h[3]);
218         h[3] = h[2];
219         
220         if (this.centerBlock != null) {
221             Size2D size = this.centerBlock.arrange(
222                 g2, RectangleConstraint.NONE
223             );
224             w[4] = size.width;
225             h[4] = size.height;
226         }
227         double width = Math.max(w[0], Math.max(w[1], w[2] + w[4] + w[3]));
228         double centerHeight = Math.max(h[2], Math.max(h[3], h[4]));
229         double height = h[0] + h[1] + centerHeight;
230         if (this.topBlock != null) {
231             this.topBlock.setBounds(
232                 new Rectangle2D.Double JavaDoc(0.0, 0.0, width, h[0])
233             );
234         }
235         if (this.bottomBlock != null) {
236             this.bottomBlock.setBounds(
237                 new Rectangle2D.Double JavaDoc(0.0, height - h[1], width, h[1])
238             );
239         }
240         if (this.leftBlock != null) {
241             this.leftBlock.setBounds(
242                 new Rectangle2D.Double JavaDoc(0.0, h[0], w[2], centerHeight)
243             );
244         }
245         if (this.rightBlock != null) {
246             this.rightBlock.setBounds(
247                 new Rectangle2D.Double JavaDoc(width - w[3], h[0], w[3], centerHeight)
248             );
249         }
250         
251         if (this.centerBlock != null) {
252             this.centerBlock.setBounds(
253                 new Rectangle2D.Double JavaDoc(
254                     w[2], h[0], width - w[2] - w[3], centerHeight
255                 )
256             );
257         }
258         return new Size2D(width, height);
259     }
260
261     /**
262      * Performs an arrangement with a fixed width and a range for the height.
263      *
264      * @param container the container.
265      * @param g2 the graphics device.
266      * @param constraint the constraint.
267      *
268      * @return The container size after the arrangement.
269      */

270     protected Size2D arrangeFR(BlockContainer container, Graphics2D JavaDoc g2,
271                                RectangleConstraint constraint) {
272         Size2D size1 = arrangeFN(container, g2, constraint.getWidth());
273         if (constraint.getHeightRange().contains(size1.getHeight())) {
274             return size1;
275         }
276         else {
277             double h = constraint.getHeightRange().constrain(size1.getHeight());
278             RectangleConstraint c2 = constraint.toFixedHeight(h);
279             return arrange(container, g2, c2);
280         }
281     }
282     
283     /**
284      * Arranges the container width a fixed width and no constraint on the
285      * height.
286      *
287      * @param container the container.
288      * @param g2 the graphics device.
289      * @param width the fixed width.
290      *
291      * @return The container size after arranging the contents.
292      */

293     protected Size2D arrangeFN(BlockContainer container, Graphics2D JavaDoc g2,
294                                double width) {
295         double[] w = new double[5];
296         double[] h = new double[5];
297         RectangleConstraint c1 = new RectangleConstraint(
298             width, null, LengthConstraintType.FIXED,
299             0.0, null, LengthConstraintType.NONE
300         );
301         if (this.topBlock != null) {
302             Size2D size = this.topBlock.arrange(g2, c1);
303             w[0] = size.width;
304             h[0] = size.height;
305         }
306         if (this.bottomBlock != null) {
307             Size2D size = this.bottomBlock.arrange(g2, c1);
308             w[1] = size.width;
309             h[1] = size.height;
310         }
311         RectangleConstraint c2 = new RectangleConstraint(
312             0.0, new Range(0.0, width), LengthConstraintType.RANGE,
313             0.0, null, LengthConstraintType.NONE
314         );
315         if (this.leftBlock != null) {
316             Size2D size = this.leftBlock.arrange(g2, c2);
317             w[2] = size.width;
318             h[2] = size.height;
319         }
320         if (this.rightBlock != null) {
321             double maxW = Math.max(width - w[2], 0.0);
322             RectangleConstraint c3 = new RectangleConstraint(
323                 0.0, new Range(Math.min(w[2], maxW), maxW),
324                 LengthConstraintType.RANGE,
325                 0.0, null, LengthConstraintType.NONE
326             );
327             Size2D size = this.rightBlock.arrange(g2, c3);
328             w[3] = size.width;
329             h[3] = size.height;
330         }
331         
332         h[2] = Math.max(h[2], h[3]);
333         h[3] = h[2];
334         
335         if (this.centerBlock != null) {
336             RectangleConstraint c4 = new RectangleConstraint(
337                 width - w[2] - w[3], null, LengthConstraintType.FIXED,
338                 0.0, null, LengthConstraintType.NONE
339             );
340             Size2D size = this.centerBlock.arrange(g2, c4);
341             w[4] = size.width;
342             h[4] = size.height;
343         }
344         double height = h[0] + h[1] + Math.max(h[2], Math.max(h[3], h[4]));
345         return arrange(container, g2, new RectangleConstraint(width, height));
346     }
347
348     /**
349      * Performs an arrangement with range constraints on both the vertical
350      * and horizontal sides.
351      *
352      * @param container the container.
353      * @param widthRange the allowable range for the container width.
354      * @param heightRange the allowable range for the container height.
355      * @param g2 the graphics device.
356      *
357      * @return The container size.
358      */

359     protected Size2D arrangeRR(BlockContainer container,
360                                Range widthRange, Range heightRange,
361                                Graphics2D JavaDoc g2) {
362         double[] w = new double[5];
363         double[] h = new double[5];
364         if (this.topBlock != null) {
365             RectangleConstraint c1 = new RectangleConstraint(
366                 widthRange, heightRange
367             );
368             Size2D size = this.topBlock.arrange(g2, c1);
369             w[0] = size.width;
370             h[0] = size.height;
371         }
372         if (this.bottomBlock != null) {
373             Range heightRange2 = Range.shift(heightRange, -h[0], false);
374             RectangleConstraint c2 = new RectangleConstraint(
375                 widthRange, heightRange2
376             );
377             Size2D size = this.bottomBlock.arrange(g2, c2);
378             w[1] = size.width;
379             h[1] = size.height;
380         }
381         Range heightRange3 = Range.shift(heightRange, -(h[0] + h[1]));
382         if (this.leftBlock != null) {
383             RectangleConstraint c3 = new RectangleConstraint(
384                 widthRange, heightRange3
385             );
386             Size2D size = this.leftBlock.arrange(g2, c3);
387             w[2] = size.width;
388             h[2] = size.height;
389         }
390         Range widthRange2 = Range.shift(widthRange, -w[2], false);
391         if (this.rightBlock != null) {
392             RectangleConstraint c4 = new RectangleConstraint(
393                 widthRange2, heightRange3
394             );
395             Size2D size = this.rightBlock.arrange(g2, c4);
396             w[3] = size.width;
397             h[3] = size.height;
398         }
399         
400         h[2] = Math.max(h[2], h[3]);
401         h[3] = h[2];
402         Range widthRange3 = Range.shift(widthRange, -(w[2] + w[3]), false);
403         if (this.centerBlock != null) {
404             RectangleConstraint c5 = new RectangleConstraint(
405                 widthRange3, heightRange3
406             );
407             // TODO: the width and height ranges should be reduced by the
408
// height required for the top and bottom, and the width required
409
// by the left and right
410
Size2D size = this.centerBlock.arrange(g2, c5);
411             w[4] = size.width;
412             h[4] = size.height;
413         }
414         double width = Math.max(w[0], Math.max(w[1], w[2] + w[4] + w[3]));
415         double height = h[0] + h[1] + Math.max(h[2], Math.max(h[3], h[4]));
416         if (this.topBlock != null) {
417             this.topBlock.setBounds(
418                 new Rectangle2D.Double JavaDoc(0.0, 0.0, width, h[0])
419             );
420         }
421         if (this.bottomBlock != null) {
422             this.bottomBlock.setBounds(
423                 new Rectangle2D.Double JavaDoc(0.0, height - h[1], width, h[1])
424             );
425         }
426         if (this.leftBlock != null) {
427             this.leftBlock.setBounds(
428                 new Rectangle2D.Double JavaDoc(0.0, h[0], w[2], h[2])
429             );
430         }
431         if (this.rightBlock != null) {
432             this.rightBlock.setBounds(
433                 new Rectangle2D.Double JavaDoc(width - w[3], h[0], w[3], h[3])
434             );
435         }
436         
437         if (this.centerBlock != null) {
438             this.centerBlock.setBounds(
439                 new Rectangle2D.Double JavaDoc(
440                     w[2], h[0], width - w[2] - w[3], height - h[0] - h[1]
441                 )
442             );
443         }
444         return new Size2D(width, height);
445     }
446
447     /**
448      * Arranges the items within a container.
449      *
450      * @param container the container.
451      * @param constraint the constraint.
452      * @param g2 the graphics device.
453      *
454      * @return The container size after the arrangement.
455      */

456     protected Size2D arrangeFF(BlockContainer container, Graphics2D JavaDoc g2,
457                                RectangleConstraint constraint) {
458         double[] w = new double[5];
459         double[] h = new double[5];
460         w[0] = constraint.getWidth();
461         if (this.topBlock != null) {
462             RectangleConstraint c1 = new RectangleConstraint(
463                 w[0], null, LengthConstraintType.FIXED,
464                 0.0, new Range(0.0, constraint.getHeight()),
465                 LengthConstraintType.RANGE
466             );
467             Size2D size = this.topBlock.arrange(g2, c1);
468             h[0] = size.height;
469         }
470         w[1] = w[0];
471         if (this.bottomBlock != null) {
472             RectangleConstraint c2 = new RectangleConstraint(
473                 w[0], null, LengthConstraintType.FIXED,
474                 0.0, new Range(0.0, constraint.getHeight() - h[0]),
475                 LengthConstraintType.RANGE
476             );
477             Size2D size = this.bottomBlock.arrange(g2, c2);
478             h[1] = size.height;
479         }
480         h[2] = constraint.getHeight() - h[1] - h[0];
481         if (this.leftBlock != null) {
482             RectangleConstraint c3 = new RectangleConstraint(
483                 0.0, new Range(0.0, constraint.getWidth()),
484                 LengthConstraintType.RANGE,
485                 h[2], null, LengthConstraintType.FIXED
486             );
487             Size2D size = this.leftBlock.arrange(g2, c3);
488             w[2] = size.width;
489         }
490         h[3] = h[2];
491         if (this.rightBlock != null) {
492             RectangleConstraint c4 = new RectangleConstraint(
493                 0.0, new Range(0.0, constraint.getWidth() - w[2]),
494                 LengthConstraintType.RANGE,
495                 h[2], null, LengthConstraintType.FIXED
496             );
497             Size2D size = this.rightBlock.arrange(g2, c4);
498             w[3] = size.width;
499         }
500         h[4] = h[2];
501         w[4] = constraint.getWidth() - w[3] - w[2];
502         RectangleConstraint c5 = new RectangleConstraint(w[4], h[4]);
503         if (this.centerBlock != null) {
504             this.centerBlock.arrange(g2, c5);
505         }
506        
507         if (this.topBlock != null) {
508             this.topBlock.setBounds(
509                 new Rectangle2D.Double JavaDoc(0.0, 0.0, w[0], h[0])
510             );
511         }
512         if (this.bottomBlock != null) {
513             this.bottomBlock.setBounds(
514                 new Rectangle2D.Double JavaDoc(0.0, h[0] + h[2], w[1], h[1])
515             );
516         }
517         if (this.leftBlock != null) {
518             this.leftBlock.setBounds(
519                 new Rectangle2D.Double JavaDoc(0.0, h[0], w[2], h[2])
520             );
521         }
522         if (this.rightBlock != null) {
523             this.rightBlock.setBounds(
524                 new Rectangle2D.Double JavaDoc(w[2] + w[4], h[0], w[3], h[3])
525             );
526         }
527         if (this.centerBlock != null) {
528             this.centerBlock.setBounds(
529                 new Rectangle2D.Double JavaDoc(w[2], h[0], w[4], h[4])
530             );
531         }
532         return new Size2D(constraint.getWidth(), constraint.getHeight());
533     }
534     
535     /**
536      * Clears the layout.
537      */

538     public void clear() {
539         this.centerBlock = null;
540         this.topBlock = null;
541         this.bottomBlock = null;
542         this.leftBlock = null;
543         this.rightBlock = null;
544     }
545     
546     /**
547      * Tests this arrangement for equality with an arbitrary object.
548      *
549      * @param obj the object (<code>null</code> permitted).
550      *
551      * @return A boolean.
552      */

553     public boolean equals(Object JavaDoc obj) {
554         if (obj == this) {
555             return true;
556         }
557         if (!(obj instanceof BorderArrangement)) {
558             return false;
559         }
560         BorderArrangement that = (BorderArrangement) obj;
561         if (!ObjectUtilities.equal(this.topBlock, that.topBlock)) {
562             return false;
563         }
564         if (!ObjectUtilities.equal(this.bottomBlock, that.bottomBlock)) {
565             return false;
566         }
567         if (!ObjectUtilities.equal(this.leftBlock, that.leftBlock)) {
568             return false;
569         }
570         if (!ObjectUtilities.equal(this.rightBlock, that.rightBlock)) {
571             return false;
572         }
573         if (!ObjectUtilities.equal(this.centerBlock, that.centerBlock)) {
574             return false;
575         }
576         return true;
577     }
578 }
579
Popular Tags