1 /* ===========================================================
2 * JFreeChart : a free chart library for the Java(tm) platform
3 * ===========================================================
4 *
5 * (C) Copyright 2000-2007, 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 * BlockContainer.java
29 * -------------------
30 * (C) Copyright 2004-2007, by Object Refinery Limited.
31 *
32 * Original Author: David Gilbert (for Object Refinery Limited);
33 * Contributor(s): -;
34 *
35 * Changes:
36 * --------
37 * 22-Oct-2004 : Version 1 (DG);
38 * 02-Feb-2005 : Added isEmpty() method (DG);
39 * 04-Feb-2005 : Added equals(), clone() and implemented Serializable (DG);
40 * 08-Feb-2005 : Updated for changes in RectangleConstraint (DG);
41 * 20-Apr-2005 : Added new draw() method (DG);
42 * ------------- JFREECHART 1.0.x ---------------------------------------------
43 * 20-Jul-2006 : Perform translation directly on drawing area, not via
44 * Graphics2D (DG);
45 *
46 */
47
48 package org.jfree.chart.block;
49
50 import java.awt.Graphics2D;
51 import java.awt.geom.Rectangle2D;
52 import java.io.Serializable;
53 import java.util.ArrayList;
54 import java.util.Collections;
55 import java.util.Iterator;
56 import java.util.List;
57
58 import org.jfree.chart.entity.EntityCollection;
59 import org.jfree.chart.entity.StandardEntityCollection;
60 import org.jfree.ui.Size2D;
61 import org.jfree.util.PublicCloneable;
62
63 /**
64 * A container for a collection of {@link Block} objects. The container uses
65 * an {@link Arrangement} object to handle the position of each block.
66 */
67 public class BlockContainer extends AbstractBlock
68 implements Block,
69 Cloneable, PublicCloneable,
70 Serializable {
71
72 /** For serialization. */
73 private static final long serialVersionUID = 8199508075695195293L;
74
75 /** The blocks within the container. */
76 private List blocks;
77
78 /** The object responsible for laying out the blocks. */
79 private Arrangement arrangement;
80
81 /**
82 * Creates a new instance with default settings.
83 */
84 public BlockContainer() {
85 this(new BorderArrangement());
86 }
87
88 /**
89 * Creates a new instance with the specified arrangement.
90 *
91 * @param arrangement the arrangement manager (<code>null</code> not
92 * permitted).
93 */
94 public BlockContainer(Arrangement arrangement) {
95 if (arrangement == null) {
96 throw new IllegalArgumentException("Null 'arrangement' argument.");
97 }
98 this.arrangement = arrangement;
99 this.blocks = new ArrayList();
100 }
101
102 /**
103 * Returns the arrangement (layout) manager for the container.
104 *
105 * @return The arrangement manager (never <code>null</code>).
106 */
107 public Arrangement getArrangement() {
108 return this.arrangement;
109 }
110
111 /**
112 * Sets the arrangement (layout) manager.
113 *
114 * @param arrangement the arrangement (<code>null</code> not permitted).
115 */
116 public void setArrangement(Arrangement arrangement) {
117 if (arrangement == null) {
118 throw new IllegalArgumentException("Null 'arrangement' argument.");
119 }
120 this.arrangement = arrangement;
121 }
122
123 /**
124 * Returns <code>true</code> if there are no blocks in the container, and
125 * <code>false</code> otherwise.
126 *
127 * @return A boolean.
128 */
129 public boolean isEmpty() {
130 return this.blocks.isEmpty();
131 }
132
133 /**
134 * Returns an unmodifiable list of the {@link Block} objects managed by
135 * this arrangement.
136 *
137 * @return A list of blocks.
138 */
139 public List getBlocks() {
140 return Collections.unmodifiableList(this.blocks);
141 }
142
143 /**
144 * Adds a block to the container.
145 *
146 * @param block the block (<code>null</code> permitted).
147 */
148 public void add(Block block) {
149 add(block, null);
150 }
151
152 /**
153 * Adds a block to the container.
154 *
155 * @param block the block (<code>null</code> permitted).
156 * @param key the key (<code>null</code> permitted).
157 */
158 public void add(Block block, Object key) {
159 this.blocks.add(block);
160 this.arrangement.add(block, key);
161 }
162
163 /**
164 * Clears all the blocks from the container.
165 */
166 public void clear() {
167 this.blocks.clear();
168 this.arrangement.clear();
169 }
170
171 /**
172 * Arranges the contents of the block, within the given constraints, and
173 * returns the block size.
174 *
175 * @param g2 the graphics device.
176 * @param constraint the constraint (<code>null</code> not permitted).
177 *
178 * @return The block size (in Java2D units, never <code>null</code>).
179 */
180 public Size2D arrange(Graphics2D g2, RectangleConstraint constraint) {
181 return this.arrangement.arrange(this, g2, constraint);
182 }
183
184 /**
185 * Draws the container and all the blocks within it.
186 *
187 * @param g2 the graphics device.
188 * @param area the area.
189 */
190 public void draw(Graphics2D g2, Rectangle2D area) {
191 draw(g2, area, null);
192 }
193
194 /**
195 * Draws the block within the specified area.
196 *
197 * @param g2 the graphics device.
198 * @param area the area.
199 * @param params passed on to blocks within the container
200 * (<code>null</code> permitted).
201 *
202 * @return An instance of {@link EntityBlockResult}, or <code>null</code>.
203 */
204 public Object draw(Graphics2D g2, Rectangle2D area, Object params) {
205 // check if we need to collect chart entities from the container
206 EntityBlockParams ebp = null;
207 StandardEntityCollection sec = null;
208 if (params instanceof EntityBlockParams) {
209 ebp = (EntityBlockParams) params;
210 if (ebp.getGenerateEntities()) {
211 sec = new StandardEntityCollection();
212 }
213 }
214 Rectangle2D contentArea = (Rectangle2D) area.clone();
215 contentArea = trimMargin(contentArea);
216 drawBorder(g2, contentArea);
217 contentArea = trimBorder(contentArea);
218 contentArea = trimPadding(contentArea);
219 Iterator iterator = this.blocks.iterator();
220 while (iterator.hasNext()) {
221 Block block = (Block) iterator.next();
222 Rectangle2D bounds = block.getBounds();
223 Rectangle2D drawArea = new Rectangle2D.Double(bounds.getX()
224 + area.getX(), bounds.getY() + area.getY(),
225 bounds.getWidth(), bounds.getHeight());
226 Object r = block.draw(g2, drawArea, params);
227 if (sec != null) {
228 if (r instanceof EntityBlockResult) {
229 EntityBlockResult ebr = (EntityBlockResult) r;
230 EntityCollection ec = ebr.getEntityCollection();
231 sec.addAll(ec);
232 }
233 }
234 }
235 BlockResult result = null;
236 if (sec != null) {
237 result = new BlockResult();
238 result.setEntityCollection(sec);
239 }
240 return result;
241 }
242
243 /**
244 * Tests this container for equality with an arbitrary object.
245 *
246 * @param obj the object (<code>null</code> permitted).
247 *
248 * @return A boolean.
249 */
250 public boolean equals(Object obj) {
251 if (obj == this) {
252 return true;
253 }
254 if (!(obj instanceof BlockContainer)) {
255 return false;
256 }
257 if (!super.equals(obj)) {
258 return false;
259 }
260 BlockContainer that = (BlockContainer) obj;
261 if (!this.arrangement.equals(that.arrangement)) {
262 return false;
263 }
264 if (!this.blocks.equals(that.blocks)) {
265 return false;
266 }
267 return true;
268 }
269
270 /**
271 * Returns a clone of the container.
272 *
273 * @return A clone.
274 *
275 * @throws CloneNotSupportedException if there is a problem cloning.
276 */
277 public Object clone() throws CloneNotSupportedException {
278 BlockContainer clone = (BlockContainer) super.clone();
279 // TODO : complete this
280 return clone;
281 }
282
283 }