001 /* ========================================================================
002 * JCommon : a free general purpose class library for the Java(tm) platform
003 * ========================================================================
004 *
005 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006 *
007 * Project Info: http://www.jfree.org/jcommon/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 * LCBLayout.java
029 * --------------
030 * (C) Copyright 2000-2005, by Object Refinery Limited.
031 *
032 * Original Author: David Gilbert (for Object Refinery Limited);
033 * Contributor(s): -;
034 *
035 * $Id: LCBLayout.java,v 1.5 2005/11/16 15:58:40 taqua Exp $
036 *
037 * Changes (from 26-Oct-2001)
038 * --------------------------
039 * 26-Oct-2001 : Changed package to com.jrefinery.layout.* (DG);
040 * 10-Oct-2002 : Fixed errors reported by Checkstyle (DG);
041 */
042
043 package org.jfree.layout;
044
045 import java.awt.Component;
046 import java.awt.Container;
047 import java.awt.Dimension;
048 import java.awt.Insets;
049 import java.awt.LayoutManager;
050 import java.io.Serializable;
051
052 /**
053 * Specialised layout manager for a grid of components.
054 *
055 * @author David Gilbert
056 */
057 public class LCBLayout implements LayoutManager, Serializable {
058
059 /** For serialization. */
060 private static final long serialVersionUID = -2531780832406163833L;
061
062 /** A constant for the number of columns in the layout. */
063 private static final int COLUMNS = 3;
064
065 /** Tracks the column widths. */
066 private int[] colWidth;
067
068 /** Tracks the row heights. */
069 private int[] rowHeight;
070
071 /** The gap between each label and component. */
072 private int labelGap;
073
074 /** The gap between each component and button. */
075 private int buttonGap;
076
077 /** The gap between rows. */
078 private int vGap;
079
080 /**
081 * Creates a new LCBLayout with the specified maximum number of rows.
082 *
083 * @param maxrows the maximum number of rows.
084 */
085 public LCBLayout(final int maxrows) {
086 this.labelGap = 10;
087 this.buttonGap = 6;
088 this.vGap = 2;
089 this.colWidth = new int[COLUMNS];
090 this.rowHeight = new int[maxrows];
091 }
092
093 /**
094 * Returns the preferred size using this layout manager.
095 *
096 * @param parent the parent.
097 *
098 * @return the preferred size using this layout manager.
099 */
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 }