001: /*
002: * Copyright (c) 2002-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package com.jgoodies.forms.extras;
032:
033: import java.awt.Component;
034: import java.awt.Container;
035: import java.util.NoSuchElementException;
036:
037: import com.jgoodies.forms.layout.CellConstraints;
038: import com.jgoodies.forms.layout.FormLayout;
039:
040: /**
041: * Constists only of static methods that provide convenience behavior
042: * for working with the <code>FormLayout</code>.<p>
043: *
044: * <strong>Note:</strong> This class is not part of the binary Form library.
045: * It comes with the Forms distributions as an extra.
046: * <strong>The API is work in progress and may change without notice;
047: * this class may even be completely removed from future distributions.</strong>
048: * If you want to use this class, you may consider copying it into
049: * your codebase.
050: *
051: * @author Karsten Lentzsch
052: * @version $Revision: 1.5 $
053: */
054:
055: public final class FormLayoutUtils {
056:
057: private FormLayoutUtils() {
058: // Override default constructor; prevents instantiation.
059: }
060:
061: // Tests ******************************************************************
062:
063: /**
064: * Checks and answers whether the given FormLayout container
065: * contains a component in the specified column.<p>
066: *
067: * For every container child component, we look up the associated
068: * <code>CellConstraints</code> object from the layout and
069: * compare its horizontal grid origin with the specified column index.
070: *
071: * @param container the layout container
072: * @param columnIndex the index of the column to test
073: * @return true if the column contains a component, false otherwise
074: * @throws IllegalArgumentException if the container's layout is
075: * not a <code>FormLayout</code>
076: */
077: public static boolean columnContainsComponent(Container container,
078: int columnIndex) {
079: for (ConstraintIterator iterator = new ConstraintIterator(
080: container); iterator.hasNext();) {
081: if (columnIndex == iterator.nextConstraints().gridX) {
082: return true;
083: }
084: }
085: return false;
086: }
087:
088: /**
089: * Checks and answers whether the given FormLayout container
090: * contains a component in the specified row.<p>
091: *
092: * For every container child component, we look up the associated
093: * <code>CellConstraints</code> object from the layout and
094: * compare its vertical grid origin with the specified row index.
095: *
096: * @param container the layout container
097: * @param rowIndex the index of the row to test
098: * @return true if the row contains a component, false otherwise
099: * @throws IllegalArgumentException if the container's layout is
100: * not a <code>FormLayout</code>
101: */
102: public static boolean rowContainsComponent(Container container,
103: int rowIndex) {
104: for (ConstraintIterator iterator = new ConstraintIterator(
105: container); iterator.hasNext();) {
106: if (rowIndex == iterator.nextConstraints().gridY) {
107: return true;
108: }
109: }
110: return false;
111: }
112:
113: /**
114: * Checks and answers whether the specified column is grouped
115: * in the given FormLayout. A column <code>col</code> is grouped,
116: * if and only if there's a column group <em>group</em>
117: * that includes <code>col</code>'s index.
118: *
119: * @param layout the layout to be inspected
120: * @param columnIndex the index of the column to be checked
121: * @return true if the column is grouped, false if not
122: */
123: public static boolean isGroupedColumn(FormLayout layout,
124: int columnIndex) {
125: return isGrouped(layout.getColumnGroups(), columnIndex);
126: }
127:
128: /**
129: * Checks and answers whether the specified row is grouped
130: * in the given FormLayout. A row <code>row</code> is grouped,
131: * if and only if there's a row group <em>group</em>
132: * that includes <code>row</code>'s index.
133: *
134: * @param layout the layout to be inspected
135: * @param rowIndex the index of the row to be checked
136: * @return true if the column is grouped, false if not
137: */
138: public static boolean isGroupedRow(FormLayout layout, int rowIndex) {
139: return isGrouped(layout.getRowGroups(), rowIndex);
140: }
141:
142: // Helper Code ***********************************************************
143:
144: /**
145: * Checks and answers whether the specified index is contained
146: * in one of the given group indices.
147: *
148: * @param allGroupIndices an array of arrays of group indices
149: * @param index the index to be tested
150: * @return true if index is contained in one of the groups
151: */
152: private static boolean isGrouped(int[][] allGroupIndices, int index) {
153: for (int group = 0; group < allGroupIndices.length; group++) {
154: int[] groupIndices = allGroupIndices[group];
155: for (int i = 0; i < groupIndices.length; i++) {
156: int aGroupIndex = groupIndices[i];
157: if (index == aGroupIndex) {
158: return true;
159: }
160: }
161: }
162: return false;
163: }
164:
165: /**
166: * Iterates over a FormLayout container's <code>CellConstraints</code>.
167: * The container's child component collection and the layout's
168: * constraints collection must not be changed during the iteration;
169: * otherwise the behavior of this iterator is unspecified and unsafe.
170: *
171: * @author Karsten
172: * @version $Revision: 1.5 $
173: *
174: * @see FormLayout
175: * @see CellConstraints
176: */
177: public static class ConstraintIterator {
178:
179: /**
180: * Refers to the FormLayout instance used to look up constraints.
181: */
182: private final FormLayout layout;
183:
184: /**
185: * Holds a copy of the container's components.
186: */
187: private final Component[] components;
188:
189: /**
190: * The current index in the component array.
191: * Used to determine whether there are more elements
192: * and to look up the next constraints.
193: */
194: private int index;
195:
196: // Instance Creation *************************************************
197:
198: /**
199: * Constructs a ConstraintIterator for the given FormLayout container.
200: * Useful to iterate over the container's <code>CellConstraints</code>.
201: *
202: * @param container the layout container
203: * @throws IllegalArgumentException if the container's layout is
204: * not a <code>FormLayout</code>
205: */
206: public ConstraintIterator(Container container) {
207: if (!(container.getLayout() instanceof FormLayout)) {
208: throw new IllegalArgumentException(
209: "The container must use an instance of FormLayout.");
210: }
211: layout = (FormLayout) container.getLayout();
212: components = container.getComponents();
213: index = 0;
214: }
215:
216: /**
217: * Returns <tt>true</tt> if the iteration has more elements. (In other
218: * words, returns <tt>true</tt> if <tt>next</tt> would return an element
219: * rather than throwing an exception.)
220: *
221: * @return true if the iterator has more elements.
222: */
223: public boolean hasNext() {
224: return index < components.length;
225: }
226:
227: /**
228: * Returns the next element in the iteration.
229: *
230: * @return the next element in the iteration.
231: * @throws NoSuchElementException iteration has no more elements.
232: */
233: public CellConstraints nextConstraints() {
234: if (!hasNext())
235: throw new NoSuchElementException(
236: "The constraint iterator has no more elements.");
237:
238: return layout.getConstraints(components[index++]);
239: }
240:
241: }
242:
243: }
|