Frames | No Frames |
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: }