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