Source for org.jfree.layout.LCBLayout

   1: /* ========================================================================
   2:  * JCommon : a free general purpose class library for the Java(tm) platform
   3:  * ========================================================================
   4:  *
   5:  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
   6:  * 
   7:  * Project Info:  http://www.jfree.org/jcommon/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:  * LCBLayout.java
  29:  * --------------
  30:  * (C) Copyright 2000-2005, by Object Refinery Limited.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   -;
  34:  *
  35:  * $Id: LCBLayout.java,v 1.5 2005/11/16 15:58:40 taqua Exp $
  36:  *
  37:  * Changes (from 26-Oct-2001)
  38:  * --------------------------
  39:  * 26-Oct-2001 : Changed package to com.jrefinery.layout.* (DG);
  40:  * 10-Oct-2002 : Fixed errors reported by Checkstyle (DG);
  41:  */
  42: 
  43: package org.jfree.layout;
  44: 
  45: import java.awt.Component;
  46: import java.awt.Container;
  47: import java.awt.Dimension;
  48: import java.awt.Insets;
  49: import java.awt.LayoutManager;
  50: import java.io.Serializable;
  51: 
  52: /**
  53:  * Specialised layout manager for a grid of components.
  54:  *
  55:  * @author David Gilbert
  56:  */
  57: public class LCBLayout implements LayoutManager, Serializable {
  58: 
  59:     /** For serialization. */
  60:     private static final long serialVersionUID = -2531780832406163833L;
  61:     
  62:     /** A constant for the number of columns in the layout. */
  63:     private static final int COLUMNS = 3;
  64: 
  65:     /** Tracks the column widths. */
  66:     private int[] colWidth;
  67: 
  68:     /** Tracks the row heights. */
  69:     private int[] rowHeight;
  70: 
  71:     /** The gap between each label and component. */
  72:     private int labelGap;
  73: 
  74:     /** The gap between each component and button. */
  75:     private int buttonGap;
  76: 
  77:     /** The gap between rows. */
  78:     private int vGap;
  79: 
  80:     /**
  81:      * Creates a new LCBLayout with the specified maximum number of rows.
  82:      *
  83:      * @param maxrows  the maximum number of rows.
  84:      */
  85:     public LCBLayout(final int maxrows) {
  86:         this.labelGap = 10;
  87:         this.buttonGap = 6;
  88:         this.vGap = 2;
  89:         this.colWidth = new int[COLUMNS];
  90:         this.rowHeight = new int[maxrows];
  91:     }
  92: 
  93:     /**
  94:      * Returns the preferred size using this layout manager.
  95:      *
  96:      * @param parent  the parent.
  97:      *
  98:      * @return the preferred size using this layout manager.
  99:     */
 100:     public Dimension preferredLayoutSize(final Container parent) {
 101: 
 102:         synchronized (parent.getTreeLock()) {
 103:             final Insets insets = parent.getInsets();
 104:             final int ncomponents = parent.getComponentCount();
 105:             final int nrows = ncomponents / COLUMNS;
 106:             for (int c = 0; c < COLUMNS; c++) {
 107:                 for (int r = 0; r < nrows; r++) {
 108:                     final Component component 
 109:                         = parent.getComponent(r * COLUMNS + c);
 110:                     final Dimension d = component.getPreferredSize();
 111:                     if (this.colWidth[c] < d.width) {
 112:                         this.colWidth[c] = d.width;
 113:                     }
 114:                     if (this.rowHeight[r] < d.height) {
 115:                         this.rowHeight[r] = d.height;
 116:                     }
 117:                 }
 118:             }
 119:             int totalHeight = this.vGap * (nrows - 1);
 120:             for (int r = 0; r < nrows; r++) {
 121:                 totalHeight = totalHeight + this.rowHeight[r];
 122:             }
 123:             final int totalWidth = this.colWidth[0] + this.labelGap 
 124:                 + this.colWidth[1] + this.buttonGap + this.colWidth[2];
 125:             return new Dimension(
 126:                 insets.left + insets.right + totalWidth + this.labelGap 
 127:                     + this.buttonGap,
 128:                 insets.top + insets.bottom + totalHeight + this.vGap
 129:             );
 130:         }
 131: 
 132:     }
 133: 
 134:     /**
 135:      * Returns the minimum size using this layout manager.
 136:      *
 137:      * @param parent  the parent.
 138:      *
 139:      * @return the minimum size using this layout manager.
 140:      */
 141:     public Dimension minimumLayoutSize(final Container parent) {
 142: 
 143:         synchronized (parent.getTreeLock()) {
 144:             final Insets insets = parent.getInsets();
 145:             final int ncomponents = parent.getComponentCount();
 146:             final int nrows = ncomponents / COLUMNS;
 147:             for (int c = 0; c < COLUMNS; c++) {
 148:                 for (int r = 0; r < nrows; r++) {
 149:                     final Component component 
 150:                         = parent.getComponent(r * COLUMNS + c);
 151:                     final Dimension d = component.getMinimumSize();
 152:                     if (this.colWidth[c] < d.width) {
 153:                         this.colWidth[c] = d.width;
 154:                     }
 155:                     if (this.rowHeight[r] < d.height) {
 156:                         this.rowHeight[r] = d.height;
 157:                     }
 158:                 }
 159:             }
 160:             int totalHeight = this.vGap * (nrows - 1);
 161:             for (int r = 0; r < nrows; r++) {
 162:                 totalHeight = totalHeight + this.rowHeight[r];
 163:             }
 164:             final int totalWidth = this.colWidth[0] + this.labelGap 
 165:                 + this.colWidth[1] + this.buttonGap + this.colWidth[2];
 166:             return new Dimension(
 167:                 insets.left + insets.right + totalWidth + this.labelGap 
 168:                 + this.buttonGap,
 169:                 insets.top + insets.bottom + totalHeight + this.vGap
 170:             );
 171:         }
 172: 
 173:     }
 174: 
 175:     /**
 176:      * Lays out the components.
 177:      *
 178:      * @param parent  the parent.
 179:      */
 180:     public void layoutContainer(final Container parent) {
 181: 
 182:         synchronized (parent.getTreeLock()) {
 183:             final Insets insets = parent.getInsets();
 184:             final int ncomponents = parent.getComponentCount();
 185:             final int nrows = ncomponents / COLUMNS;
 186:             for (int c = 0; c < COLUMNS; c++) {
 187:                 for (int r = 0; r < nrows; r++) {
 188:                     final Component component 
 189:                         = parent.getComponent(r * COLUMNS + c);
 190:                     final Dimension d = component.getPreferredSize();
 191:                     if (this.colWidth[c] < d.width) {
 192:                         this.colWidth[c] = d.width;
 193:                     }
 194:                     if (this.rowHeight[r] < d.height) {
 195:                         this.rowHeight[r] = d.height;
 196:                     }
 197:                 }
 198:             }
 199:             int totalHeight = this.vGap * (nrows - 1);
 200:             for (int r = 0; r < nrows; r++) {
 201:                 totalHeight = totalHeight + this.rowHeight[r];
 202:             }
 203:             final int totalWidth = this.colWidth[0] + this.colWidth[1] 
 204:                                                     + this.colWidth[2];
 205: 
 206:             // adjust the width of the second column to use up all of parent
 207:             final int available = parent.getWidth() - insets.left 
 208:                 - insets.right - this.labelGap - this.buttonGap;
 209:             this.colWidth[1] = this.colWidth[1] + (available - totalWidth);
 210: 
 211:             // *** DO THE LAYOUT ***
 212:             int x = insets.left;
 213:             for (int c = 0; c < COLUMNS; c++) {
 214:                 int y = insets.top;
 215:                 for (int r = 0; r < nrows; r++) {
 216:                     final int i = r * COLUMNS + c;
 217:                     if (i < ncomponents) {
 218:                         final Component component = parent.getComponent(i);
 219:                         final Dimension d = component.getPreferredSize();
 220:                         final int h = d.height;
 221:                         final int adjust = (this.rowHeight[r] - h) / 2;
 222:                         parent.getComponent(i).setBounds(x, y + adjust, 
 223:                                 this.colWidth[c], h);
 224:                     }
 225:                     y = y + this.rowHeight[r] + this.vGap;
 226:                 }
 227:                 x = x + this.colWidth[c];
 228:                 if (c == 0) {
 229:                     x = x + this.labelGap;
 230:                 }
 231:                 if (c == 1) {
 232:                     x = x + this.buttonGap;
 233:                 }
 234:             }
 235: 
 236:         }
 237: 
 238:     }
 239: 
 240:     /**
 241:      * Not used.
 242:      *
 243:      * @param comp  the component.
 244:      */
 245:     public void addLayoutComponent(final Component comp) {
 246:         // not used
 247:     }
 248: 
 249:     /**
 250:      * Not used.
 251:      *
 252:      * @param comp  the component.
 253:      */
 254:     public void removeLayoutComponent(final Component comp) {
 255:         // not used
 256:     }
 257: 
 258:     /**
 259:      * Not used.
 260:      *
 261:      * @param name  the component name.
 262:      * @param comp  the component.
 263:      */
 264:     public void addLayoutComponent(final String name, final Component comp) {
 265:         // not used
 266:     }
 267: 
 268:     /**
 269:      * Not used.
 270:      *
 271:      * @param name  the component name.
 272:      * @param comp  the component.
 273:      */
 274:     public void removeLayoutComponent(final String name, final Component comp) {
 275:         // not used
 276:     }
 277: 
 278: }