/*
* ExtendedGridLayoutConstraints.java - a constraints clss for the ExtendedGridLayout
* :tabSize=4:indentSize=4:noTabs=false:
* :folding=explicit:collapseFolds=1:
*
* Originally written by Björn Kautler for the jEdit project. This work has been
* placed into the public domain. You may use this work in any way and for any
* purpose you wish.
*
* THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, NOT EVEN THE
* IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, ASSUMES
* _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE RESULTING FROM THE USE, MODIFICATION,
* OR REDISTRIBUTION OF THIS SOFTWARE.
*/
package org.gjt.sp.jedit.gui;
import java.awt.Component;
/**
* Specifies constraints for components
* that are laid out using the {@code ExtendedGridLayout} class.
*
* @version 1.0
* @author Björn "Vampire" Kautler
* @see ExtendedGridLayout
* @since jEdit 4.3pre10
*/
public class ExtendedGridLayoutConstraints
{
/**
* Specifies that this component is the
* last component in its column or row
* and takes up the remaining space.
*/
public static final int REMAINDER = Integer.MAX_VALUE;
/**
* Specifies the row in which a component starts its display area.
* {@code row} has to be non-negative and the default
* value is 0.
*/
private int row;
/**
* Specifies the column in which a component starts its display area.
* {@code col} has to be non-negative.
*/
private int col;
/**
* Specifies the number of cells in a row for the
* component's display area.
* <p>
* Use {@code REMAINDER} to specify that the component's
* display area will be from its grid position to the last
* cell in the row.
* <p>
* {@code colspan} has to be {@literal >= 1} and the default
* value is 1.
*
* @see #REMAINDER
* @see #rowspan
*/
private int colspan;
/**
* Specifies the effective number of cells in a row for the
* component's display area. This is used internally
* to get the effective number of cells in a row in cases
* where {@code REMAINDER} is used for colspan.
*
* @see #REMAINDER
* @see #colspan
*/
private int effectiveColspan;
/**
* Specifies the number of cells in a column for the
* component's display area.
* <p>
* Use {@code REMAINDER} to specify that the component's
* display area will be from its grid position to the last
* cell in the column.
* <p>
* {@code rowspan} has to be {@literal >= 1} and the default
* value is 1.
*
* @see #REMAINDER
* @see #colspan
*/
private int rowspan;
/**
* Specifies the effective number of cells in a column for the
* component's display area. This is used internally
* to get the effective number of cells in a column in cases
* where {@code REMAINDER} is used for rowspan.
*
* @see #REMAINDER
* @see #rowspan
*/
private int effectiveRowspan;
/**
* Specifies if this Constraint is used as placeholder to build the grid.
* This is used internally and the default value is {@code false}.
*/
private boolean placeholder;
/**
* Specifies the mainConstraints object for which this constraints
* object is a placeholder. If this constraints object is no placeholder,
* mainConstraints is set to {@code null}.
*/
private ExtendedGridLayoutConstraints mainConstraints;
/**
* Specifies the {@code Component} this constraints object describes.
*/
private Component component;
/**
* Creates an {@code ExtendedGridLayoutConstraints} object with
* all of its fields set to their default value. For further information
* about the default values see
* {@link #ExtendedGridLayoutConstraints(int, int, int, java.awt.Component)}.
*
* @param component The {@code Component} this constraints object describes
*/
public ExtendedGridLayoutConstraints(Component component)
{
this(0,0,1,1,component,false,null);
}
/**
* Creates an {@code ExtendedGridLayoutConstraints} object with
* all of its fields set to their default value
* except of the row which is specified. For further information
* about the default values see
* {@link #ExtendedGridLayoutConstraints(int, int, int, java.awt.Component)}.
*
* @param row The row in which a component starts its display area. First row is 0
* @param component The {@code Component} this constraints object d describes
* @throws IllegalArgumentException If row {@literal < 0}
*/
public ExtendedGridLayoutConstraints(int row, Component component)
{
this(row,0,1,1,component,false,null);
}
/**
* Creates an {@code ExtendedGridLayoutConstraints} object with
* all of its fields set to the passed-in arguments.
*
* @param row The row in which a component starts its display area.
* First row is 0. Default value is 0.
* @param colspan The number of cells in a row for the component's display area.
* Use {@code REMAINDER} to specify that the component's
* display area will be from its grid position to the last
* cell in the row. Default value is 1.
* @param rowspan The number of cells in a column for the component's display area.
* Use {@code REMAINDER} to specify that the component's
* display area will be from its grid position to the last
* cell in the column. Default value is 1.
* @param component The {@code Component} this constraints object describes
* @throws IllegalArgumentException If row {@literal < 0}
* @throws IllegalArgumentException If colspan {@literal < 1}
* @throws IllegalArgumentException If rowspan {@literal < 1}
*/
public ExtendedGridLayoutConstraints(int row, int colspan, int rowspan, Component component)
{
this(row,0,colspan,rowspan,component,false,null);
}
/**
* Creates an {@code ExtendedGridLayoutConstraints} object with
* all of its fields set to the passed-in arguments.
*
* @param row The row in which a component starts its display area.
* First row is 0.
* @param col The col in which a component starts its display area.
* First col is 0.
* @param colspan The number of cells in a row for the component's display area.
* Use {@code REMAINDER} to specify that the component's
* display area will be from its grid position to the last
* cell in the row.
* @param rowspan The number of cells in a column for the component's display area.
* Use {@code REMAINDER} to specify that the component's
* display area will be from its grid position to the last
* cell in the column.
* @param component The {@code Component} this constraints object describes
* @param placeholder If this constraints are used as placeholder to build the grid
* @param mainConstraints The mainConstraints object for which this constraints
* object is a placeholder
* @throws IllegalArgumentException If row {@literal < 0}
* @throws IllegalArgumentException If col {@literal < 0}
* @throws IllegalArgumentException If colspan {@literal < 1}
* @throws IllegalArgumentException If rowspan {@literal < 1}
*/
private ExtendedGridLayoutConstraints(int row, int col, int colspan, int rowspan, Component component, boolean placeholder, ExtendedGridLayoutConstraints mainConstraints)
{
if (row < 0)
{
throw new IllegalArgumentException("row must be non-negative (" + row + ')');
}
if (col < 0)
{
throw new IllegalArgumentException("col must be non-negative (" + col + ')');
}
if (colspan < 1)
{
throw new IllegalArgumentException("colspan must be at least 1 (" + colspan + ')');
}
if (rowspan < 1)
{
throw new IllegalArgumentException("rowspan must be at least 1 (" + rowspan + ')');
}
this.row = row;
this.col = col;
this.colspan = colspan;
effectiveColspan = 1;
this.rowspan = rowspan;
effectiveRowspan = 1;
this.component = component;
this.placeholder = placeholder;
this.mainConstraints = mainConstraints;
}
/**
* Creates an {@code ExtendedGridLayoutConstraints} object which can be
* used as placeholder for building a grid with colspans.
*
* @param forUsage If the returned object will be used in the grid
* and therefor the effectiveColspan should be raised by one
* @return The newly created {@code ExtendedGridLayoutConstraints}
* object or {@code null} if no colspan is applicable
* @see #getRowspanPlaceholder(boolean)
*/
ExtendedGridLayoutConstraints getColspanPlaceholder(boolean forUsage)
{
if (1 == colspan)
{
return null;
}
ExtendedGridLayoutConstraints result = new ExtendedGridLayoutConstraints(row,col+1,colspan==REMAINDER ? REMAINDER : colspan-1,rowspan,component,true,null == mainConstraints ? this : mainConstraints);
if (forUsage && (result.mainConstraints.row == row))
{
result.mainConstraints.effectiveColspan++;
}
return result;
}
/**
* Creates an {@code ExtendedGridLayoutConstraints} object which can be
* used as placeholder for building a grid with rowspans.
*
* @param forUsage If the returned object will be used in the grid
* and therefor the effectiveRowspan should be raised by one
* @return The newly created {@code ExtendedGridLayoutConstraints}
* object or {@code null} if no rowspan is applicable
* @see #getColspanPlaceholder(boolean)
*/
ExtendedGridLayoutConstraints getRowspanPlaceholder(boolean forUsage)
{
if (1 == rowspan)
{
return null;
}
ExtendedGridLayoutConstraints result = new ExtendedGridLayoutConstraints(row+1,col,colspan,rowspan==REMAINDER ? REMAINDER : rowspan-1,component,true,null == mainConstraints ? this : mainConstraints);
if (forUsage && (result.mainConstraints.col == col))
{
result.mainConstraints.effectiveRowspan++;
}
return result;
}
/**
* @return The row in which the component starts its display area.
*/
public int getRow()
{
return row;
}
/**
* @return The column in which the component starts its display area.
*/
public int getCol()
{
return col;
}
/**
* @param col The column in which the component starts its display area.
*/
void setCol(int col)
{
if (col < 0)
{
throw new IllegalArgumentException("col must be non-negative (" + col + ')');
}
this.col = col;
}
/**
* @return The number of cells in a row for the component's display area
* or {@code REMAINDER} if the component's display area will be
* from its grid position to the last cell in the row.
*/
public int getColspan()
{
return colspan;
}
/**
* @return The effective number of cells in a row for the component's display area.
*/
int getEffectiveColspan()
{
return null == mainConstraints ? effectiveColspan : mainConstraints.effectiveColspan;
}
/**
* @return The number of cells in a column for the component's display area
* or {@code REMAINDER} if the component's display area will be
* from its grid position to the last cell in the column.
*/
public int getRowspan()
{
return rowspan;
}
/**
* @return The effective number of cells in a column for the component's display area.
*/
int getEffectiveRowspan()
{
return null == mainConstraints ? effectiveRowspan : mainConstraints.effectiveRowspan;
}
/**
* @return The {@code Component} this constraints object describes
*/
Component getComponent()
{
return component;
}
/**
* @return Whether this constraints object is a placeholder or not
*/
public boolean isPlaceholder()
{
return placeholder;
}
/**
* @return A work copy if this constraints object. This is a flat copy
* which means that the reference to the component stays the same.
* The returned object could be used without modifying this
* constraints object.
*/
ExtendedGridLayoutConstraints getWorkCopy()
{
return new ExtendedGridLayoutConstraints(row,col,colspan,rowspan,component,placeholder,(null == mainConstraints ? null : mainConstraints.getWorkCopy()));
}
/**
* Indicates whether some other object is "equal to" this one.
* <p>
* The {@code equals} method implements an equivalence relation
* on non-null object references:
* <ul>
* <li>It is <i>reflexive</i>: for any non-null reference value
* {@code x}, {@code x.equals(x)} returns
* {@code true}.
* <li>It is <i>symmetric</i>: for any non-null reference values
* {@code x} and {@code y}, {@code x.equals(y)}
* returns {@code true} if and only if
* {@code y.equals(x)} returns {@code true}.
* <li>It is <i>transitive</i>: for any non-null reference values
* {@code x}, {@code y}, and {@code z}, if
* {@code x.equals(y)} returns {@code true} and
* {@code y.equals(z)} returns {@code true}, then
* {@code x.equals(z)} returns {@code true}.
* <li>It is <i>consistent</i>: for any non-null reference values
* {@code x} and {@code y}, multiple invocations of
* <tt>x.equals(y)</tt> consistently return {@code true}
* or consistently return {@code false}, provided no
* information used in {@code equals} comparisons on the
* objects is modified.
* <li>For any non-null reference value {@code x},
* {@code x.equals(null)} returns {@code false}.
* </ul>
* <p>
* The <tt>equals</tt> method for class
* {@code ExtendedGridLayoutConstraints} returns {@code true}
* if and only if the constraints objects describe the same {@code Component}
*
* @param o the reference object with which to compare.
* @return {@code true} if this object is the same as the o
* argument; {@code false} otherwise.
* @see #hashCode()
* @see <a href="http://download.oracle.com/javase/6/docs/api/java/util/Hashtable.html"><code>java.util.Hashtable</code></a>
*/
public boolean equals(Object o)
{
if ((o == null) ||
(!(o instanceof ExtendedGridLayoutConstraints)))
{
return false;
}
if (component == null)
{
return ((ExtendedGridLayoutConstraints)o).component == null;
}
return component.equals(((ExtendedGridLayoutConstraints)o).component);
}
/**
* Returns a hash code value for the object. This method is
* supported for the benefit of hashtables such as those provided by
* {@code java.util.Hashtable}.
* <p>
* The general contract of {@code hashCode} is:
* <ul>
* <li>Whenever it is invoked on the same object more than once during
* an execution of a Java application, the <tt>hashCode</tt> method
* must consistently return the same integer, provided no information
* used in <tt>equals</tt> comparisons on the object is modified.
* This integer need not remain consistent from one execution of an
* application to another execution of the same application.
* <li>If two objects are equal according to the <tt>equals(Object)</tt>
* method, then calling the {@code hashCode} method on each of
* the two objects must produce the same integer result.
* <li>It is <em>not</em> required that if two objects are unequal
* according to the
* <a href="http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#equals(java.lang.Object)">{@code java.lang.Object#equals(java.lang.Object)}</a>
* method, then calling the <tt>hashCode</tt> method on each of the
* two objects must produce distinct integer results. However, the
* programmer should be aware that producing distinct integer results
* for unequal objects may improve the performance of hashtables.
* </ul>
*
* @return a hash code value for this object.
* @see #equals(java.lang.Object)
* @see <a href="http://download.oracle.com/javase/6/docs/api/java/util/Hashtable.html"><code>java.util.Hashtable</code></a>
*/
public int hashCode()
{
if (null == component)
{
return 0;
}
return component.hashCode();
}
/**
* Returns a string representation of the object. In general, the
* {@code toString} method returns a string that
* "textually represents" this object. The result should
* be a concise but informative representation that is easy for a
* person to read.
*
* @return a string representation of the object.
*/
public String toString()
{
return getClass().getName() + "[row=" + row + ",col=" + col
+ ",colspan=" + colspan + ",effectiveColspan=" + effectiveColspan
+ ",rowspan=" + rowspan + ",effectiveRowspan=" + effectiveRowspan
+ ",placeholder=" + placeholder + ",component=" + component
+ ",mainConstraints=" + mainConstraints + "]";
}
}