001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2007, 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 * BlockContainer.java
029 * -------------------
030 * (C) Copyright 2004-2007, 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 isEmpty() method (DG);
039 * 04-Feb-2005 : Added equals(), clone() and implemented Serializable (DG);
040 * 08-Feb-2005 : Updated for changes in RectangleConstraint (DG);
041 * 20-Apr-2005 : Added new draw() method (DG);
042 * ------------- JFREECHART 1.0.x ---------------------------------------------
043 * 20-Jul-2006 : Perform translation directly on drawing area, not via
044 * Graphics2D (DG);
045 *
046 */
047
048 package org.jfree.chart.block;
049
050 import java.awt.Graphics2D;
051 import java.awt.geom.Rectangle2D;
052 import java.io.Serializable;
053 import java.util.ArrayList;
054 import java.util.Collections;
055 import java.util.Iterator;
056 import java.util.List;
057
058 import org.jfree.chart.entity.EntityCollection;
059 import org.jfree.chart.entity.StandardEntityCollection;
060 import org.jfree.ui.Size2D;
061 import org.jfree.util.PublicCloneable;
062
063 /**
064 * A container for a collection of {@link Block} objects. The container uses
065 * an {@link Arrangement} object to handle the position of each block.
066 */
067 public class BlockContainer extends AbstractBlock
068 implements Block,
069 Cloneable, PublicCloneable,
070 Serializable {
071
072 /** For serialization. */
073 private static final long serialVersionUID = 8199508075695195293L;
074
075 /** The blocks within the container. */
076 private List blocks;
077
078 /** The object responsible for laying out the blocks. */
079 private Arrangement arrangement;
080
081 /**
082 * Creates a new instance with default settings.
083 */
084 public BlockContainer() {
085 this(new BorderArrangement());
086 }
087
088 /**
089 * Creates a new instance with the specified arrangement.
090 *
091 * @param arrangement the arrangement manager (<code>null</code> not
092 * permitted).
093 */
094 public BlockContainer(Arrangement arrangement) {
095 if (arrangement == null) {
096 throw new IllegalArgumentException("Null 'arrangement' argument.");
097 }
098 this.arrangement = arrangement;
099 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 }