Source for org.jfree.chart.block.CenterArrangement

   1: /* ===========================================================
   2:  * JFreeChart : a free chart library for the Java(tm) platform
   3:  * ===========================================================
   4:  *
   5:  * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
   6:  *
   7:  * Project Info:  http://www.jfree.org/jfreechart/index.html
   8:  *
   9:  * This library is free software; you can redistribute it and/or modify it 
  10:  * under the terms of the GNU Lesser General Public License as published by 
  11:  * the Free Software Foundation; either version 2.1 of the License, or 
  12:  * (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but 
  15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  16:  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
  17:  * License for more details.
  18:  *
  19:  * You should have received a copy of the GNU Lesser General Public
  20:  * License along with this library; if not, write to the Free Software
  21:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
  22:  * USA.  
  23:  *
  24:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
  25:  * in the United States and other countries.]
  26:  *
  27:  * ----------------------
  28:  * CenterArrangement.java
  29:  * ----------------------
  30:  * (C) Copyright 2005-2007, by Object Refinery Limited.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   -;
  34:  *
  35:  * Changes:
  36:  * --------
  37:  * 08-Mar-2005 : Version 1 (DG);
  38:  * ------------- JFREECHART 1.0.x ---------------------------------------------
  39:  * 20-Jul-2006 : Set bounds of contained block when arranging (DG);
  40:  * 
  41:  */
  42: 
  43: package org.jfree.chart.block;
  44: 
  45: import java.awt.Graphics2D;
  46: import java.awt.geom.Rectangle2D;
  47: import java.io.Serializable;
  48: import java.util.List;
  49: 
  50: import org.jfree.ui.Size2D;
  51: 
  52: /**
  53:  * Arranges a block in the center of its container.  This class is immutable.
  54:  */
  55: public class CenterArrangement implements Arrangement, Serializable {
  56:     
  57:     /** For serialization. */
  58:     private static final long serialVersionUID = -353308149220382047L; 
  59:     
  60:     /**
  61:      * Creates a new instance.
  62:      */
  63:     public CenterArrangement() {   
  64:     }
  65:      
  66:     /**
  67:      * Adds a block to be managed by this instance.  This method is usually 
  68:      * called by the {@link BlockContainer}, you shouldn't need to call it 
  69:      * directly.
  70:      * 
  71:      * @param block  the block.
  72:      * @param key  a key that controls the position of the block.
  73:      */
  74:     public void add(Block block, Object key) {
  75:         // since the flow layout is relatively straightforward, 
  76:         // no information needs to be recorded here
  77:     }
  78:     
  79:     /**
  80:      * Calculates and sets the bounds of all the items in the specified 
  81:      * container, subject to the given constraint.  The <code>Graphics2D</code>
  82:      * can be used by some items (particularly items containing text) to 
  83:      * calculate sizing parameters.
  84:      * 
  85:      * @param container  the container whose items are being arranged.
  86:      * @param g2  the graphics device.
  87:      * @param constraint  the size constraint.
  88:      * 
  89:      * @return The size of the container after arrangement of the contents.
  90:      */
  91:     public Size2D arrange(BlockContainer container, Graphics2D g2,
  92:                           RectangleConstraint constraint) {
  93:         
  94:         LengthConstraintType w = constraint.getWidthConstraintType();
  95:         LengthConstraintType h = constraint.getHeightConstraintType();
  96:         if (w == LengthConstraintType.NONE) {
  97:             if (h == LengthConstraintType.NONE) {
  98:                 return arrangeNN(container, g2);  
  99:             }
 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: }