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 * $Id: BlockContainer.java,v 1.11.2.3 2007/03/16 14:10:12 mungady Exp $ 036 * 037 * Changes: 038 * -------- 039 * 22-Oct-2004 : Version 1 (DG); 040 * 02-Feb-2005 : Added isEmpty() method (DG); 041 * 04-Feb-2005 : Added equals(), clone() and implemented Serializable (DG); 042 * 08-Feb-2005 : Updated for changes in RectangleConstraint (DG); 043 * 20-Apr-2005 : Added new draw() method (DG); 044 * ------------- JFREECHART 1.0.0 --------------------------------------------- 045 * 20-Jul-2006 : Perform translation directly on drawing area, not via 046 * Graphics2D (DG); 047 * 048 */ 049 050 package org.jfree.chart.block; 051 052 import java.awt.Graphics2D; 053 import java.awt.geom.Rectangle2D; 054 import java.io.Serializable; 055 import java.util.ArrayList; 056 import java.util.Collections; 057 import java.util.Iterator; 058 import java.util.List; 059 060 import org.jfree.chart.entity.EntityCollection; 061 import org.jfree.chart.entity.StandardEntityCollection; 062 import org.jfree.ui.Size2D; 063 import org.jfree.util.PublicCloneable; 064 065 /** 066 * A container for a collection of {@link Block} objects. The container uses 067 * an {@link Arrangement} object to handle the position of each block. 068 */ 069 public class BlockContainer extends AbstractBlock 070 implements Block, 071 Cloneable, PublicCloneable, 072 Serializable { 073 074 /** For serialization. */ 075 private static final long serialVersionUID = 8199508075695195293L; 076 077 /** The blocks within the container. */ 078 private List blocks; 079 080 /** The object responsible for laying out the blocks. */ 081 private Arrangement arrangement; 082 083 /** 084 * Creates a new instance with default settings. 085 */ 086 public BlockContainer() { 087 this(new BorderArrangement()); 088 } 089 090 /** 091 * Creates a new instance with the specified arrangement. 092 * 093 * @param arrangement the arrangement manager (<code>null</code> not 094 * permitted). 095 */ 096 public BlockContainer(Arrangement arrangement) { 097 if (arrangement == null) { 098 throw new IllegalArgumentException("Null 'arrangement' argument."); 099 } 100 this.arrangement = arrangement; 101 this.blocks = new ArrayList(); 102 } 103 104 /** 105 * Returns the arrangement (layout) manager for the container. 106 * 107 * @return The arrangement manager (never <code>null</code>). 108 */ 109 public Arrangement getArrangement() { 110 return this.arrangement; 111 } 112 113 /** 114 * Sets the arrangement (layout) manager. 115 * 116 * @param arrangement the arrangement (<code>null</code> not permitted). 117 */ 118 public void setArrangement(Arrangement arrangement) { 119 if (arrangement == null) { 120 throw new IllegalArgumentException("Null 'arrangement' argument."); 121 } 122 this.arrangement = arrangement; 123 } 124 125 /** 126 * Returns <code>true</code> if there are no blocks in the container, and 127 * <code>false</code> otherwise. 128 * 129 * @return A boolean. 130 */ 131 public boolean isEmpty() { 132 return this.blocks.isEmpty(); 133 } 134 135 /** 136 * Returns an unmodifiable list of the {@link Block} objects managed by 137 * this arrangement. 138 * 139 * @return A list of blocks. 140 */ 141 public List getBlocks() { 142 return Collections.unmodifiableList(this.blocks); 143 } 144 145 /** 146 * Adds a block to the container. 147 * 148 * @param block the block (<code>null</code> permitted). 149 */ 150 public void add(Block block) { 151 add(block, null); 152 } 153 154 /** 155 * Adds a block to the container. 156 * 157 * @param block the block (<code>null</code> permitted). 158 * @param key the key (<code>null</code> permitted). 159 */ 160 public void add(Block block, Object key) { 161 this.blocks.add(block); 162 this.arrangement.add(block, key); 163 } 164 165 /** 166 * Clears all the blocks from the container. 167 */ 168 public void clear() { 169 this.blocks.clear(); 170 this.arrangement.clear(); 171 } 172 173 /** 174 * Arranges the contents of the block, within the given constraints, and 175 * returns the block size. 176 * 177 * @param g2 the graphics device. 178 * @param constraint the constraint (<code>null</code> not permitted). 179 * 180 * @return The block size (in Java2D units, never <code>null</code>). 181 */ 182 public Size2D arrange(Graphics2D g2, RectangleConstraint constraint) { 183 return this.arrangement.arrange(this, g2, constraint); 184 } 185 186 /** 187 * Draws the container and all the blocks within it. 188 * 189 * @param g2 the graphics device. 190 * @param area the area. 191 */ 192 public void draw(Graphics2D g2, Rectangle2D area) { 193 draw(g2, area, null); 194 } 195 196 /** 197 * Draws the block within the specified area. 198 * 199 * @param g2 the graphics device. 200 * @param area the area. 201 * @param params passed on to blocks within the container 202 * (<code>null</code> permitted). 203 * 204 * @return An instance of {@link EntityBlockResult}, or <code>null</code>. 205 */ 206 public Object draw(Graphics2D g2, Rectangle2D area, Object params) { 207 // check if we need to collect chart entities from the container 208 EntityBlockParams ebp = null; 209 StandardEntityCollection sec = null; 210 if (params instanceof EntityBlockParams) { 211 ebp = (EntityBlockParams) params; 212 if (ebp.getGenerateEntities()) { 213 sec = new StandardEntityCollection(); 214 } 215 } 216 Rectangle2D contentArea = (Rectangle2D) area.clone(); 217 contentArea = trimMargin(contentArea); 218 drawBorder(g2, contentArea); 219 contentArea = trimBorder(contentArea); 220 contentArea = trimPadding(contentArea); 221 Iterator iterator = this.blocks.iterator(); 222 while (iterator.hasNext()) { 223 Block block = (Block) iterator.next(); 224 Rectangle2D bounds = block.getBounds(); 225 Rectangle2D drawArea = new Rectangle2D.Double(bounds.getX() 226 + area.getX(), bounds.getY() + area.getY(), 227 bounds.getWidth(), bounds.getHeight()); 228 Object r = block.draw(g2, drawArea, params); 229 if (sec != null) { 230 if (r instanceof EntityBlockResult) { 231 EntityBlockResult ebr = (EntityBlockResult) r; 232 EntityCollection ec = ebr.getEntityCollection(); 233 sec.addAll(ec); 234 } 235 } 236 } 237 BlockResult result = null; 238 if (sec != null) { 239 result = new BlockResult(); 240 result.setEntityCollection(sec); 241 } 242 return result; 243 } 244 245 /** 246 * Tests this container for equality with an arbitrary object. 247 * 248 * @param obj the object (<code>null</code> permitted). 249 * 250 * @return A boolean. 251 */ 252 public boolean equals(Object obj) { 253 if (obj == this) { 254 return true; 255 } 256 if (!(obj instanceof BlockContainer)) { 257 return false; 258 } 259 if (!super.equals(obj)) { 260 return false; 261 } 262 BlockContainer that = (BlockContainer) obj; 263 if (!this.arrangement.equals(that.arrangement)) { 264 return false; 265 } 266 if (!this.blocks.equals(that.blocks)) { 267 return false; 268 } 269 return true; 270 } 271 272 /** 273 * Returns a clone of the container. 274 * 275 * @return A clone. 276 * 277 * @throws CloneNotSupportedException if there is a problem cloning. 278 */ 279 public Object clone() throws CloneNotSupportedException { 280 BlockContainer clone = (BlockContainer) super.clone(); 281 // TODO : complete this 282 return clone; 283 } 284 285 }