001 /* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2006, 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 * CenterArrangement.java 029 * ---------------------- 030 * (C) Copyright 2005, 2006, by Object Refinery Limited. 031 * 032 * Original Author: David Gilbert (for Object Refinery Limited); 033 * Contributor(s): -; 034 * 035 * $Id: CenterArrangement.java,v 1.3.2.2 2006/07/20 16:21:58 mungady Exp $ 036 * 037 * Changes: 038 * -------- 039 * 08-Mar-2005 : Version 1 (DG); 040 * ------------- JFREECHART 1.0.0 --------------------------------------------- 041 * 20-Jul-2006 : Set bounds of contained block when arranging (DG); 042 * 043 */ 044 045 package org.jfree.chart.block; 046 047 import java.awt.Graphics2D; 048 import java.awt.geom.Rectangle2D; 049 import java.io.Serializable; 050 import java.util.List; 051 052 import org.jfree.ui.Size2D; 053 054 /** 055 * Arranges a block in the center of its container. This class is immutable. 056 */ 057 public class CenterArrangement implements Arrangement, Serializable { 058 059 /** For serialization. */ 060 private static final long serialVersionUID = -353308149220382047L; 061 062 /** 063 * Creates a new instance. 064 */ 065 public CenterArrangement() { 066 } 067 068 /** 069 * Adds a block to be managed by this instance. This method is usually 070 * called by the {@link BlockContainer}, you shouldn't need to call it 071 * directly. 072 * 073 * @param block the block. 074 * @param key a key that controls the position of the block. 075 */ 076 public void add(Block block, Object key) { 077 // since the flow layout is relatively straightforward, 078 // no information needs to be recorded here 079 } 080 081 /** 082 * Calculates and sets the bounds of all the items in the specified 083 * container, subject to the given constraint. The <code>Graphics2D</code> 084 * can be used by some items (particularly items containing text) to 085 * calculate sizing parameters. 086 * 087 * @param container the container whose items are being arranged. 088 * @param g2 the graphics device. 089 * @param constraint the size constraint. 090 * 091 * @return The size of the container after arrangement of the contents. 092 */ 093 public Size2D arrange(BlockContainer container, Graphics2D g2, 094 RectangleConstraint constraint) { 095 096 LengthConstraintType w = constraint.getWidthConstraintType(); 097 LengthConstraintType h = constraint.getHeightConstraintType(); 098 if (w == LengthConstraintType.NONE) { 099 if (h == LengthConstraintType.NONE) { 100 return arrangeNN(container, g2); 101 } 102 else if (h == LengthConstraintType.FIXED) { 103 throw new RuntimeException("Not implemented."); 104 } 105 else if (h == LengthConstraintType.RANGE) { 106 throw new RuntimeException("Not implemented."); 107 } 108 } 109 else if (w == LengthConstraintType.FIXED) { 110 if (h == LengthConstraintType.NONE) { 111 return arrangeFN(container, g2, constraint); 112 } 113 else if (h == LengthConstraintType.FIXED) { 114 throw new RuntimeException("Not implemented."); 115 } 116 else if (h == LengthConstraintType.RANGE) { 117 throw new RuntimeException("Not implemented."); 118 } 119 } 120 else if (w == LengthConstraintType.RANGE) { 121 if (h == LengthConstraintType.NONE) { 122 return arrangeRN(container, g2, constraint); 123 } 124 else if (h == LengthConstraintType.FIXED) { 125 return arrangeRF(container, g2, constraint); 126 } 127 else if (h == LengthConstraintType.RANGE) { 128 return arrangeRR(container, g2, constraint); 129 } 130 } 131 throw new IllegalArgumentException("Unknown LengthConstraintType."); 132 133 } 134 135 /** 136 * Arranges the blocks in the container with a fixed width and no height 137 * constraint. 138 * 139 * @param container the container. 140 * @param g2 the graphics device. 141 * @param constraint the constraint. 142 * 143 * @return The size. 144 */ 145 protected Size2D arrangeFN(BlockContainer container, Graphics2D g2, 146 RectangleConstraint constraint) { 147 148 List blocks = container.getBlocks(); 149 Block b = (Block) blocks.get(0); 150 Size2D s = b.arrange(g2, RectangleConstraint.NONE); 151 double width = constraint.getWidth(); 152 Rectangle2D bounds = new Rectangle2D.Double((width - s.width) / 2.0, 153 0.0, s.width, s.height); 154 b.setBounds(bounds); 155 return new Size2D((width - s.width) / 2.0, s.height); 156 } 157 158 /** 159 * Arranges the blocks in the container with a fixed with and a range 160 * constraint on the height. 161 * 162 * @param container the container. 163 * @param g2 the graphics device. 164 * @param constraint the constraint. 165 * 166 * @return The size following the arrangement. 167 */ 168 protected Size2D arrangeFR(BlockContainer container, Graphics2D g2, 169 RectangleConstraint constraint) { 170 171 Size2D s = arrangeFN(container, g2, constraint); 172 if (constraint.getHeightRange().contains(s.height)) { 173 return s; 174 } 175 else { 176 RectangleConstraint c = constraint.toFixedHeight( 177 constraint.getHeightRange().constrain(s.getHeight())); 178 return arrangeFF(container, g2, c); 179 } 180 } 181 182 /** 183 * Arranges the blocks in the container with the overall height and width 184 * specified as fixed constraints. 185 * 186 * @param container the container. 187 * @param g2 the graphics device. 188 * @param constraint the constraint. 189 * 190 * @return The size following the arrangement. 191 */ 192 protected Size2D arrangeFF(BlockContainer container, Graphics2D g2, 193 RectangleConstraint constraint) { 194 195 // TODO: implement this properly 196 return arrangeFN(container, g2, constraint); 197 } 198 199 /** 200 * Arranges the blocks with the overall width and height to fit within 201 * specified ranges. 202 * 203 * @param container the container. 204 * @param g2 the graphics device. 205 * @param constraint the constraint. 206 * 207 * @return The size after the arrangement. 208 */ 209 protected Size2D arrangeRR(BlockContainer container, Graphics2D g2, 210 RectangleConstraint constraint) { 211 212 // first arrange without constraints, and see if this fits within 213 // the required ranges... 214 Size2D s1 = arrangeNN(container, g2); 215 if (constraint.getWidthRange().contains(s1.width)) { 216 return s1; // TODO: we didn't check the height yet 217 } 218 else { 219 RectangleConstraint c = constraint.toFixedWidth( 220 constraint.getWidthRange().getUpperBound()); 221 return arrangeFR(container, g2, c); 222 } 223 } 224 225 /** 226 * Arranges the blocks in the container with a range constraint on the 227 * width and a fixed height. 228 * 229 * @param container the container. 230 * @param g2 the graphics device. 231 * @param constraint the constraint. 232 * 233 * @return The size following the arrangement. 234 */ 235 protected Size2D arrangeRF(BlockContainer container, Graphics2D g2, 236 RectangleConstraint constraint) { 237 238 Size2D s = arrangeNF(container, g2, constraint); 239 if (constraint.getWidthRange().contains(s.width)) { 240 return s; 241 } 242 else { 243 RectangleConstraint c = constraint.toFixedWidth( 244 constraint.getWidthRange().constrain(s.getWidth())); 245 return arrangeFF(container, g2, c); 246 } 247 } 248 249 /** 250 * Arranges the block with a range constraint on the width, and no 251 * constraint on the height. 252 * 253 * @param container the container. 254 * @param g2 the graphics device. 255 * @param constraint the constraint. 256 * 257 * @return The size following the arrangement. 258 */ 259 protected Size2D arrangeRN(BlockContainer container, Graphics2D g2, 260 RectangleConstraint constraint) { 261 // first arrange without constraints, then see if the width fits 262 // within the required range...if not, call arrangeFN() at max width 263 Size2D s1 = arrangeNN(container, g2); 264 if (constraint.getWidthRange().contains(s1.width)) { 265 return s1; 266 } 267 else { 268 RectangleConstraint c = constraint.toFixedWidth( 269 constraint.getWidthRange().getUpperBound()); 270 return arrangeFN(container, g2, c); 271 } 272 } 273 274 /** 275 * Arranges the blocks without any constraints. This puts all blocks 276 * into a single row. 277 * 278 * @param container the container. 279 * @param g2 the graphics device. 280 * 281 * @return The size after the arrangement. 282 */ 283 protected Size2D arrangeNN(BlockContainer container, Graphics2D g2) { 284 List blocks = container.getBlocks(); 285 Block b = (Block) blocks.get(0); 286 Size2D s = b.arrange(g2, RectangleConstraint.NONE); 287 b.setBounds(new Rectangle2D.Double(0.0, 0.0, s.width, s.height)); 288 return new Size2D(s.width, s.height); 289 } 290 291 /** 292 * Arranges the blocks with no width constraint and a fixed height 293 * constraint. This puts all blocks into a single row. 294 * 295 * @param container the container. 296 * @param g2 the graphics device. 297 * @param constraint the constraint. 298 * 299 * @return The size after the arrangement. 300 */ 301 protected Size2D arrangeNF(BlockContainer container, Graphics2D g2, 302 RectangleConstraint constraint) { 303 // TODO: for now we are ignoring the height constraint 304 return arrangeNN(container, g2); 305 } 306 307 /** 308 * Clears any cached information. 309 */ 310 public void clear() { 311 // no action required. 312 } 313 314 /** 315 * Tests this instance for equality with an arbitrary object. 316 * 317 * @param obj the object (<code>null</code> permitted). 318 * 319 * @return A boolean. 320 */ 321 public boolean equals(Object obj) { 322 if (obj == this) { 323 return true; 324 } 325 if (!(obj instanceof CenterArrangement)) { 326 return false; 327 } 328 return true; 329 } 330 331 }