001: /*
002: * ExtendedGridLayoutConstraints.java - a constraints clss for the ExtendedGridLayout
003: * :tabSize=8:indentSize=8:noTabs=false:
004: * :folding=explicit:collapseFolds=1:
005: *
006: * Originally written by Björn Kautler for the jEdit project. This work has been
007: * placed into the public domain. You may use this work in any way and for any
008: * purpose you wish.
009: *
010: * THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, NOT EVEN THE
011: * IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, ASSUMES
012: * _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE RESULTING FROM THE USE, MODIFICATION,
013: * OR REDISTRIBUTION OF THIS SOFTWARE.
014: */
015:
016: package org.gjt.sp.jedit.gui;
017:
018: import java.awt.Component;
019:
020: /**
021: * Specifies constraints for components
022: * that are laid out using the {@code ExtendedGridLayout} class.
023: *
024: * @version 1.0
025: * @author Björn "Vampire" Kautler
026: * @see ExtendedGridLayout
027: * @since jEdit 4.3pre10
028: */
029: public class ExtendedGridLayoutConstraints {
030: /**
031: * Specifies that this component is the
032: * last component in its column or row
033: * and takes up the remaining space.
034: */
035: public static final int REMAINDER = Integer.MAX_VALUE;
036:
037: /**
038: * Specifies the row in which a component starts its display area.
039: * {@code row} has to be non-negative and the default
040: * value is 0.
041: */
042: private int row;
043:
044: /**
045: * Specifies the column in which a component starts its display area.
046: * {@code col} has to be non-negative.
047: */
048: private int col;
049:
050: /**
051: * Specifies the number of cells in a row for the
052: * component's display area.
053: * <p>
054: * Use {@code REMAINDER} to specify that the component's
055: * display area will be from its grid position to the last
056: * cell in the row.
057: * <p>
058: * {@code colspan} has to be {@literal >= 1} and the default
059: * value is 1.
060: *
061: * @see #REMAINDER
062: * @see #rowspan
063: */
064: private int colspan;
065:
066: /**
067: * Specifies the effective number of cells in a row for the
068: * component's display area. This is used internally
069: * to get the effective number of cells in a row in cases
070: * where {@code REMAINDER} is used for colspan.
071: *
072: * @see #REMAINDER
073: * @see #colspan
074: */
075: private int effectiveColspan;
076:
077: /**
078: * Specifies the number of cells in a column for the
079: * component's display area.
080: * <p>
081: * Use {@code REMAINDER} to specify that the component's
082: * display area will be from its grid position to the last
083: * cell in the column.
084: * <p>
085: * {@code rowspan} has to be {@literal >= 1} and the default
086: * value is 1.
087: *
088: * @see #REMAINDER
089: * @see #colspan
090: */
091: private int rowspan;
092:
093: /**
094: * Specifies the effective number of cells in a column for the
095: * component's display area. This is used internally
096: * to get the effective number of cells in a column in cases
097: * where {@code REMAINDER} is used for rowspan.
098: *
099: * @see #REMAINDER
100: * @see #rowspan
101: */
102: private int effectiveRowspan;
103:
104: /**
105: * Specifies if this Constraint is used as placeholder to build the grid.
106: * This is used internally and the default value is {@code false}.
107: */
108: private boolean placeholder;
109:
110: /**
111: * Specifies the mainConstraints object for which this constraints
112: * object is a placeholder. If this constraints object is no placeholder,
113: * mainConstraints is set to {@code null}.
114: */
115: private ExtendedGridLayoutConstraints mainConstraints;
116:
117: /**
118: * Specifies the {@code Component} this constraints object describes.
119: */
120: private Component component;
121:
122: /**
123: * Creates an {@code ExtendedGridLayoutConstraints} object with
124: * all of its fields set to their default value. For further information
125: * about the default values see
126: * {@link #ExtendedGridLayoutConstraints(int, int, int, java.awt.Component)}.
127: *
128: * @param component The {@code Component} this constraints object describes
129: */
130: public ExtendedGridLayoutConstraints(Component component) {
131: this (0, 0, 1, 1, component, false, null);
132: }
133:
134: /**
135: * Creates an {@code ExtendedGridLayoutConstraints} object with
136: * all of its fields set to their default value
137: * except of the row which is specified. For further information
138: * about the default values see
139: * {@link #ExtendedGridLayoutConstraints(int, int, int, java.awt.Component)}.
140: *
141: * @param row The row in which a component starts its display area. First row is 0
142: * @param component The {@code Component} this constraints object d describes
143: * @throws IllegalArgumentException If row {@literal < 0}
144: */
145: public ExtendedGridLayoutConstraints(int row, Component component) {
146: this (row, 0, 1, 1, component, false, null);
147: }
148:
149: /**
150: * Creates an {@code ExtendedGridLayoutConstraints} object with
151: * all of its fields set to the passed-in arguments.
152: *
153: * @param row The row in which a component starts its display area.
154: * First row is 0. Default value is 0.
155: * @param colspan The number of cells in a row for the component's display area.
156: * Use {@code REMAINDER} to specify that the component's
157: * display area will be from its grid position to the last
158: * cell in the row. Default value is 1.
159: * @param rowspan The number of cells in a column for the component's display area.
160: * Use {@code REMAINDER} to specify that the component's
161: * display area will be from its grid position to the last
162: * cell in the column. Default value is 1.
163: * @param component The {@code Component} this constraints object describes
164: * @throws IllegalArgumentException If row {@literal < 0}
165: * @throws IllegalArgumentException If colspan {@literal < 1}
166: * @throws IllegalArgumentException If rowspan {@literal < 1}
167: */
168: public ExtendedGridLayoutConstraints(int row, int colspan,
169: int rowspan, Component component) {
170: this (row, 0, colspan, rowspan, component, false, null);
171: }
172:
173: /**
174: * Creates an {@code ExtendedGridLayoutConstraints} object with
175: * all of its fields set to the passed-in arguments.
176: *
177: * @param row The row in which a component starts its display area.
178: * First row is 0.
179: * @param col The col in which a component starts its display area.
180: * First col is 0.
181: * @param colspan The number of cells in a row for the component's display area.
182: * Use {@code REMAINDER} to specify that the component's
183: * display area will be from its grid position to the last
184: * cell in the row.
185: * @param rowspan The number of cells in a column for the component's display area.
186: * Use {@code REMAINDER} to specify that the component's
187: * display area will be from its grid position to the last
188: * cell in the column.
189: * @param component The {@code Component} this constraints object describes
190: * @param placeholder If this constraints are used as placeholder to build the grid
191: * @param mainConstraints The mainConstraints object for which this constraints
192: * object is a placeholder
193: * @throws IllegalArgumentException If row {@literal < 0}
194: * @throws IllegalArgumentException If col {@literal < 0}
195: * @throws IllegalArgumentException If colspan {@literal < 1}
196: * @throws IllegalArgumentException If rowspan {@literal < 1}
197: */
198: private ExtendedGridLayoutConstraints(int row, int col,
199: int colspan, int rowspan, Component component,
200: boolean placeholder,
201: ExtendedGridLayoutConstraints mainConstraints) {
202: if (row < 0) {
203: throw new IllegalArgumentException(
204: "row must be non-negative (" + row + ')');
205: }
206: if (col < 0) {
207: throw new IllegalArgumentException(
208: "col must be non-negative (" + col + ')');
209: }
210: if (colspan < 1) {
211: throw new IllegalArgumentException(
212: "colspan must be at least 1 (" + colspan + ')');
213: }
214: if (rowspan < 1) {
215: throw new IllegalArgumentException(
216: "rowspan must be at least 1 (" + rowspan + ')');
217: }
218: this .row = row;
219: this .col = col;
220: this .colspan = colspan;
221: effectiveColspan = 1;
222: this .rowspan = rowspan;
223: effectiveRowspan = 1;
224: this .component = component;
225: this .placeholder = placeholder;
226: this .mainConstraints = mainConstraints;
227: }
228:
229: /**
230: * Creates an {@code ExtendedGridLayoutConstraints} object which can be
231: * used as placeholder for building a grid with colspans.
232: *
233: * @param forUsage If the returned object will be used in the grid
234: * and therefor the effectiveColspan should be raised by one
235: * @return The newly created {@code ExtendedGridLayoutConstraints}
236: * object or {@code null} if no colspan is applicable
237: * @see #getRowspanPlaceholder(boolean)
238: */
239: ExtendedGridLayoutConstraints getColspanPlaceholder(boolean forUsage) {
240: if (1 == colspan) {
241: return null;
242: }
243: ExtendedGridLayoutConstraints result = new ExtendedGridLayoutConstraints(
244: row, col + 1, colspan == REMAINDER ? REMAINDER
245: : colspan - 1, rowspan, component, true,
246: null == mainConstraints ? this : mainConstraints);
247: if (forUsage && (result.mainConstraints.row == row)) {
248: result.mainConstraints.effectiveColspan++;
249: }
250: return result;
251: }
252:
253: /**
254: * Creates an {@code ExtendedGridLayoutConstraints} object which can be
255: * used as placeholder for building a grid with rowspans.
256: *
257: * @param forUsage If the returned object will be used in the grid
258: * and therefor the effectiveRowspan should be raised by one
259: * @return The newly created {@code ExtendedGridLayoutConstraints}
260: * object or {@code null} if no rowspan is applicable
261: * @see #getColspanPlaceholder(boolean)
262: */
263: ExtendedGridLayoutConstraints getRowspanPlaceholder(boolean forUsage) {
264: if (1 == rowspan) {
265: return null;
266: }
267: ExtendedGridLayoutConstraints result = new ExtendedGridLayoutConstraints(
268: row + 1, col, colspan, rowspan == REMAINDER ? REMAINDER
269: : rowspan - 1, component, true,
270: null == mainConstraints ? this : mainConstraints);
271: if (forUsage && (result.mainConstraints.col == col)) {
272: result.mainConstraints.effectiveRowspan++;
273: }
274: return result;
275: }
276:
277: /**
278: * @return The row in which the component starts its display area.
279: */
280: public int getRow() {
281: return row;
282: }
283:
284: /**
285: * @return The column in which the component starts its display area.
286: */
287: public int getCol() {
288: return col;
289: }
290:
291: /**
292: * @param col The column in which the component starts its display area.
293: */
294: void setCol(int col) {
295: if (col < 0) {
296: throw new IllegalArgumentException(
297: "col must be non-negative (" + col + ')');
298: }
299: this .col = col;
300: }
301:
302: /**
303: * @return The number of cells in a row for the component's display area
304: * or {@code REMAINDER} if the component's display area will be
305: * from its grid position to the last cell in the row.
306: */
307: public int getColspan() {
308: return colspan;
309: }
310:
311: /**
312: * @return The effective number of cells in a row for the component's display area.
313: */
314: int getEffectiveColspan() {
315: return null == mainConstraints ? effectiveColspan
316: : mainConstraints.effectiveColspan;
317: }
318:
319: /**
320: * @return The number of cells in a column for the component's display area
321: * or {@code REMAINDER} if the component's display area will be
322: * from its grid position to the last cell in the column.
323: */
324: public int getRowspan() {
325: return rowspan;
326: }
327:
328: /**
329: * @return The effective number of cells in a column for the component's display area.
330: */
331: int getEffectiveRowspan() {
332: return null == mainConstraints ? effectiveRowspan
333: : mainConstraints.effectiveRowspan;
334: }
335:
336: /**
337: * @return The {@code Component} this constraints object describes
338: */
339: Component getComponent() {
340: return component;
341: }
342:
343: /**
344: * @return Whether this constraints object is a placeholder or not
345: */
346: public boolean isPlaceholder() {
347: return placeholder;
348: }
349:
350: /**
351: * @return A work copy if this constraints object. This is a flat copy
352: * which means that the reference to the component stays the same.
353: * The returned object could be used without modifying this
354: * constraints object.
355: */
356: ExtendedGridLayoutConstraints getWorkCopy() {
357: return new ExtendedGridLayoutConstraints(row, col, colspan,
358: rowspan, component, placeholder,
359: (null == mainConstraints ? null : mainConstraints
360: .getWorkCopy()));
361: }
362:
363: /**
364: * Indicates whether some other object is "equal to" this one.
365: * <p>
366: * The {@code equals} method implements an equivalence relation
367: * on non-null object references:
368: * <ul>
369: * <li>It is <i>reflexive</i>: for any non-null reference value
370: * {@code x}, {@code x.equals(x)} returns
371: * {@code true}.
372: * <li>It is <i>symmetric</i>: for any non-null reference values
373: * {@code x} and {@code y}, {@code x.equals(y)}
374: * returns {@code true} if and only if
375: * {@code y.equals(x)} returns {@code true}.
376: * <li>It is <i>transitive</i>: for any non-null reference values
377: * {@code x}, {@code y}, and {@code z}, if
378: * {@code x.equals(y)} returns {@code true} and
379: * {@code y.equals(z)} returns {@code true}, then
380: * {@code x.equals(z)} returns {@code true}.
381: * <li>It is <i>consistent</i>: for any non-null reference values
382: * {@code x} and {@code y}, multiple invocations of
383: * <tt>x.equals(y)</tt> consistently return {@code true}
384: * or consistently return {@code false}, provided no
385: * information used in {@code equals} comparisons on the
386: * objects is modified.
387: * <li>For any non-null reference value {@code x},
388: * {@code x.equals(null)} returns {@code false}.
389: * </ul>
390: * <p>
391: * The <tt>equals</tt> method for class
392: * {@code ExtendedGridLayoutConstraints} returns {@code true}
393: * if and only if the constraints objects describe the same {@code Component}
394: *
395: * @param o the reference object with which to compare.
396: * @return {@code true} if this object is the same as the o
397: * argument; {@code false} otherwise.
398: * @see #hashCode()
399: * @see <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/Hashtable.html"><code>java.util.Hashtable</code></a>
400: */
401: public boolean equals(Object o) {
402: if ((o == null)
403: || (!(o instanceof ExtendedGridLayoutConstraints))) {
404: return false;
405: }
406: if (component == null) {
407: return ((ExtendedGridLayoutConstraints) o).component == null;
408: }
409: return component
410: .equals(((ExtendedGridLayoutConstraints) o).component);
411: }
412:
413: /**
414: * Returns a hash code value for the object. This method is
415: * supported for the benefit of hashtables such as those provided by
416: * {@code java.util.Hashtable}.
417: * <p>
418: * The general contract of {@code hashCode} is:
419: * <ul>
420: * <li>Whenever it is invoked on the same object more than once during
421: * an execution of a Java application, the <tt>hashCode</tt> method
422: * must consistently return the same integer, provided no information
423: * used in <tt>equals</tt> comparisons on the object is modified.
424: * This integer need not remain consistent from one execution of an
425: * application to another execution of the same application.
426: * <li>If two objects are equal according to the <tt>equals(Object)</tt>
427: * method, then calling the {@code hashCode} method on each of
428: * the two objects must produce the same integer result.
429: * <li>It is <em>not</em> required that if two objects are unequal
430: * according to the
431: * <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#equals(java.lang.Object)">{@code java.lang.Object#equals(java.lang.Object)}</a>
432: * method, then calling the <tt>hashCode</tt> method on each of the
433: * two objects must produce distinct integer results. However, the
434: * programmer should be aware that producing distinct integer results
435: * for unequal objects may improve the performance of hashtables.
436: * </ul>
437: *
438: * @return a hash code value for this object.
439: * @see #equals(java.lang.Object)
440: * @see <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/Hashtable.html"><code>java.util.Hashtable</code></a>
441: */
442: public int hashCode() {
443: if (null == component) {
444: return 0;
445: }
446: return component.hashCode();
447: }
448:
449: /**
450: * Returns a string representation of the object. In general, the
451: * {@code toString} method returns a string that
452: * "textually represents" this object. The result should
453: * be a concise but informative representation that is easy for a
454: * person to read.
455: *
456: * @return a string representation of the object.
457: */
458: public String toString() {
459: return getClass().getName() + "[row=" + row + ",col=" + col
460: + ",colspan=" + colspan + ",effectiveColspan="
461: + effectiveColspan + ",rowspan=" + rowspan
462: + ",effectiveRowspan=" + effectiveRowspan
463: + ",placeholder=" + placeholder + ",component="
464: + component + ",mainConstraints=" + mainConstraints
465: + "]";
466: }
467: }
|