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