io.guise.framework.component.Table Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of guise-framework Show documentation
Show all versions of guise-framework Show documentation
Guise™ Internet application framework.
/*
* Copyright © 2005-2008 GlobalMentor, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.guise.framework.component;
import java.beans.*;
import java.util.*;
import java.util.concurrent.*;
import static java.util.Objects.*;
import static com.globalmentor.java.Classes.*;
import static io.guise.framework.theme.Theme.*;
import com.globalmentor.beans.*;
import com.globalmentor.collections.DecoratorReadWriteLockMap;
import com.globalmentor.collections.ReadWriteLockMap;
import com.globalmentor.util.*;
import io.guise.framework.GuiseSession;
import io.guise.framework.component.layout.Border;
import io.guise.framework.converter.*;
import io.guise.framework.event.*;
import io.guise.framework.geometry.Extent;
import io.guise.framework.model.*;
import io.guise.framework.model.ui.AbstractPresentationModel;
import io.guise.framework.model.ui.PresentationModel;
import io.guise.framework.prototype.AbstractActionPrototype;
import io.guise.framework.prototype.ActionPrototype;
import io.guise.framework.style.FontStyle;
import io.guise.framework.validator.*;
/**
* A table component.
*
* Property changes to a column's UI model are repeated with the component as the source and the column UI model as the target.
*
* @author Garret Wilson
*/
public class Table extends AbstractCompositeStateControl, Table.CellComponentState> implements EditComponent, TableModel {
/** The display row count bound property. */
public static final String DISPLAY_ROW_COUNT_PROPERTY = getPropertyName(Table.class, "displayRowCount");
/** The display row start index bound property. */
public static final String DISPLAY_ROW_START_INDEX_PROPERTY = getPropertyName(Table.class, "displayRowStartIndex");
/** The table model used by this component. */
private final TableModel tableModel;
/** @return The table model used by this component. */
protected TableModel getTableModel() {
return tableModel;
}
/** The prototype for the first action. */
private final ActionPrototype firstActionPrototype;
/** @return The prototype for the first action. */
public ActionPrototype getFirstActionPrototype() {
return firstActionPrototype;
}
/** The prototype for the previous action. */
private final ActionPrototype previousActionPrototype;
/** @return The prototype for the previous action. */
public ActionPrototype getPreviousActionPrototype() {
return previousActionPrototype;
}
/** The prototype for the next action. */
private final ActionPrototype nextActionPrototype;
/** @return The prototype for the next action. */
public ActionPrototype getNextActionPrototype() {
return nextActionPrototype;
}
/** The prototype for the last action. */
private final ActionPrototype lastActionPrototype;
/** @return The prototype for the last action. */
public ActionPrototype getLastActionPrototype() {
return lastActionPrototype;
}
/** The number of rows to display at one time, or -1 the row count is not restricted. */
private int displayRowCount = -1;
/** @return The number of rows to display at one time, or -1 the row count is not restricted. */
public int getDisplayRowCount() {
return displayRowCount;
}
/**
* Sets the number of rows to display at one time. This is a bound property of type Integer
.
* @param newDisplayRowCount The number of rows to display at one time, or -1 the row count is not restricted.
* @see #DISPLAY_ROW_COUNT_PROPERTY
*/
public void setDisplayRowCount(final int newDisplayRowCount) {
if(displayRowCount != newDisplayRowCount) { //if the value is really changing
final int oldDisplayRowCount = displayRowCount; //get the old value
displayRowCount = newDisplayRowCount; //actually change the value
firePropertyChange(DISPLAY_ROW_COUNT_PROPERTY, new Integer(oldDisplayRowCount), new Integer(newDisplayRowCount)); //indicate that the value changed
}
}
/** The index of the first row to display. */
private int displayRowStartIndex = 0;
/** @return The index of the first row to display. */
public int getDisplayRowStartIndex() {
return displayRowStartIndex;
}
/**
* Sets the index of the first row to display. This is a bound property of type Integer
.
* @param newDisplayRowStartIndex The index of the first row to display.
* @throws IndexOutOfBoundsException if the given index is less than zero.
* @see #DISPLAY_ROW_START_INDEX_PROPERTY
*/
public void setDisplayRowStartIndex(final int newDisplayRowStartIndex) {
if(newDisplayRowStartIndex < 0) { //if the index is less than zero
throw new IndexOutOfBoundsException("Display row index cannot be be less than zero: " + newDisplayRowStartIndex);
}
if(displayRowStartIndex != newDisplayRowStartIndex) { //if the value is really changing
final int oldDisplayRowStartIndex = displayRowStartIndex; //get the old value
displayRowStartIndex = newDisplayRowStartIndex; //actually change the value
firePropertyChange(DISPLAY_ROW_START_INDEX_PROPERTY, new Integer(oldDisplayRowStartIndex), new Integer(newDisplayRowStartIndex)); //indicate that the value changed
}
}
/**
* Whether the table is editable and the cells will allow the the user to change their values, if their respective columns are designated as editable as well.
*/
private boolean editable = true;
@Override
public boolean isEditable() {
return editable;
}
@Override
public void setEditable(final boolean newEditable) {
if(editable != newEditable) { //if the value is really changing
final boolean oldEditable = editable; //get the old value
editable = newEditable; //actually change the value
firePropertyChange(EDITABLE_PROPERTY, Boolean.valueOf(oldEditable), Boolean.valueOf(newEditable)); //indicate that the value changed
}
}
/** The property change listener that updates prototype properties. */
final protected PropertyChangeListener updatePrototypesPropertyChangeListener = new PropertyChangeListener() {
@Override
public void propertyChange(final PropertyChangeEvent propertyChangeEvent) { //when the property changes
updatePrototypes(); //update the prototypes
}
};
/** The map of cell representation strategies for value classes. */
private final Map, CellRepresentationStrategy>> valueClassCellRepresentationStrategyMap = new ConcurrentHashMap, CellRepresentationStrategy>>();
/**
* Installs the given cell representation strategy to produce representation components for the given value class. The specified representation strategy will
* only be used if there is no representation strategy for a given column.
* @param The type of value represented.
* @param valueClass The value class with which the strategy should be associated.
* @param cellRepresentationStrategy The strategy for generating components to represent values of the given type.
* @return The representation strategy previously associated with the given value class.
* @see #setCellRepresentationStrategy(TableColumnModel, CellRepresentationStrategy)
*/
@SuppressWarnings("unchecked")
//we check the generic types before putting them in the map, so it's fine to cast the retrieved values
public CellRepresentationStrategy super V> setCellRepresentationStrategy(final Class valueClass,
CellRepresentationStrategy cellRepresentationStrategy) {
return (CellRepresentationStrategy super V>)valueClassCellRepresentationStrategyMap.put(valueClass, cellRepresentationStrategy); //associate the strategy with the value class in the map
}
/**
* Returns the given cell representation strategy assigned to produce representation components for the given value class. The returned representation
* strategy can be overridden by a representation strategy associated with a particular column.
* @param The type of value represented.
* @param valueClass The value class with which the strategy should be associated.
* @return The strategy for generating components to represent values of the given type, or null
if there is no associated representation
* strategy.
* @see #getCellRepresentationStrategy(TableColumnModel)
*/
@SuppressWarnings("unchecked")
//we check the generic types before putting them in the map, so it's fine to cast the retrieved values
public CellRepresentationStrategy super V> getCellRepresentationStrategy(final Class valueClass) {
return (CellRepresentationStrategy super V>)valueClassCellRepresentationStrategyMap.get(valueClass); //return the strategy linked to the value class in the map
}
/** The map of cell representation strategies for columns. */
private final Map, CellRepresentationStrategy>> columnCellRepresentationStrategyMap = new ConcurrentHashMap, CellRepresentationStrategy>>();
/**
* Installs the given cell representation strategy to produce representation components for the given column. A cell representation strategy for a particular
* column will override a cell representation strategy registered for a given type.
* @param The type of value the column represents.
* @param column The column with which the strategy should be associated.
* @param cellRepresentationStrategy The strategy for generating components to represent values in the given column.
* @return The representation strategy previously associated with the given column.
* @see #setCellRepresentationStrategy(Class, CellRepresentationStrategy)
*/
@SuppressWarnings("unchecked")
//we check the generic types before putting them in the map, so it's fine to cast the retrieved values
public CellRepresentationStrategy super V> setCellRepresentationStrategy(final TableColumnModel column,
CellRepresentationStrategy cellRepresentationStrategy) {
return (CellRepresentationStrategy super V>)columnCellRepresentationStrategyMap.put(column, cellRepresentationStrategy); //associate the strategy with the column in the map
}
/**
* Returns the given cell representation strategy assigned to produce representation components for the given column. A cell representation strategy for a
* particular column will override a cell representation strategy registered for a given type.
* @param The type of value the column represents.
* @param column The column with which the strategy should be associated.
* @return The strategy for generating components to represent values in the given column, or null
if there is no associated representation
* strategy.
* @see #getCellRepresentationStrategy(Class)
*/
@SuppressWarnings("unchecked")
//we check the generic types before putting them in the map, so it's fine to cast the retrieved values
public CellRepresentationStrategy super V> getCellRepresentationStrategy(final TableColumnModel column) {
return (CellRepresentationStrategy super V>)columnCellRepresentationStrategyMap.get(column); //return the strategy linked to the column in the map
}
/**
* {@inheritDoc}
*
* This version is provided to allow public access.
*
*/
@Override
public Component getComponent(final TableModel.Cell> cell) {
return super.getComponent(cell); //delegate to the parent version
}
/**
* {@inheritDoc}
*
* This implementation delegates to {@link #createTypedComponentState(io.guise.framework.model.TableModel.Cell)}.
*
*/
@Override
protected CellComponentState createComponentState(final TableModel.Cell> cell) {
return createTypedComponentState(cell); //delegate to the typed version
}
/**
* Creates a component state to represent the given object.
* @param The type of value contained in the cell.
* @param cell The object with which the component state is to be associated.
* @return The component state to represent the given object.
* @throws IllegalArgumentException if the given object is not an appropriate object for a component state to be created.
* @throws IllegalStateException if there is no registered cell representation strategy appropriate for the cell.
*/
protected CellComponentState createTypedComponentState(final TableModel.Cell cell) {
final TableModel tableModel = getTableModel(); //get the table model
final int rowIndex = cell.getRowIndex(); //get the row index
final TableColumnModel column = cell.getColumn(); //get the cell column
final boolean editable = isEditable() && column.isEditable(); //see if the cell is editable (a cell is only editable if both its table and column are editable)
//TODO del final TableModel.Cell cell=new TableModel.Cell(rowIndex, column); //create a cell object representing this row and column
//TODO fix editable if(cellComponentState==null || cellComponentState.isEditable()!=editable) //if there is no component for this cell, or the component has a different editable status
CellRepresentationStrategy super T> cellRepresentationStrategy = getCellRepresentationStrategy(column); //see if there is a cell representation strategy registered for the column
if(cellRepresentationStrategy == null) { //if there is no cell representation strategy for the column
final Class valueClass = column.getValueClass(); //get the value class of the column
final Iterator> valueAncestorClassIterator = getAncestorClasses(valueClass).iterator(); //get all the ancestor classes of the value class, in increasing order of distance and abstractness
while(cellRepresentationStrategy == null && valueAncestorClassIterator.hasNext()) { //keep iterating until we find a cell representation strategy
final Class super T> valueAncestorClass = (Class super T>)valueAncestorClassIterator.next(); //get the next ancestor class
cellRepresentationStrategy = getCellRepresentationStrategy(valueAncestorClass); //see if there is a cell representation strategy registered for the value class ancestor
}
if(cellRepresentationStrategy == null) { //if there is no cell representation strategy for the value class, either
throw new IllegalStateException("No cell representation strategy registered for value class " + valueClass);
}
}
final Component valueComponent = cellRepresentationStrategy.createComponent(this, tableModel, rowIndex, column, editable, false, false); //create a new component for the cell
return new CellComponentState(valueComponent, editable); //create a new component state for the cell's component and metadata
}
/**
* Ensures the component for a particular row and column exists.
* @param The type of value contained in the cells of the column.
* @param rowIndex The zero-based cell row index.
* @param column The cell column.
* @return The child component representing the given cell.
*/
/*TODO del when works
public Component verifyCellComponent(final int rowIndex, final TableColumnModel column)
{
final TableModel tableModel=getTableModel(); //get the table model
final boolean editable=isEditable() && column.isEditable(); //see if the cell is editable (a cell is only editable if both its table and column are editable)
final TableModel.Cell cell=new TableModel.Cell(rowIndex, column); //create a cell object representing this row and column
CellComponentState cellComponentState=getComponentState(cell); //get the component information for this cell
if(cellComponentState==null || cellComponentState.isEditable()!=editable) { //if there is no component for this cell, or the component has a different editable status
final Component valueComponent=getCellRepresentationStrategy(column).createComponent(this, tableModel, rowIndex, column, editable, false, false); //create a new component for the cell
//TODO del valueComponent.setParent(this); //tell this component that this table component is its parent
cellComponentState=new CellComponentState(valueComponent, editable); //create a new component state for the cell's component and metadata
putComponentState(cell, cellComponentState); //store the component state in the map for next time
}
return cellComponentState.getComponent(); //return the representation component
}
*/
/** The map of UI models for columns. */
private final ReadWriteLockMap, ColumnUIModel> columnUIModelMap = new DecoratorReadWriteLockMap, ColumnUIModel>(
new HashMap, ColumnUIModel>());
/**
* Retrieves the UI model for the given column. If no UI model yet exists for the given column, one will be created. There is normally no need for
* applications to call this method directly.
* @param column The column for which a UI model should be returned.
* @return The UI model for the given column.
* @throws NullPointerException if the given column is null
.
*/
public ColumnUIModel getColumnUIModel(final TableColumnModel> column) { //if we ever allow columns to be removed, automatically remove the corresponding UI model and remove its repeat property change listener
requireNonNull(column, "Column cannot be null.");
ColumnUIModel columnUIModel; //we'll find a column UI model and store it here
columnUIModelMap.readLock().lock(); //get a read lock to the column UI model map
try {
columnUIModel = columnUIModelMap.get(column); //try to get the column UI model
} finally {
columnUIModelMap.readLock().unlock(); //always release the read lock
}
if(columnUIModel == null) { //if there is as of yet no column UI model
columnUIModelMap.writeLock().lock(); //get a write lock to the map
try {
columnUIModel = columnUIModelMap.get(column); //try to get the column UI model again
if(columnUIModel == null) { //if there still is no column UI model
columnUIModel = new ColumnUIModel(); //create a new column UI model
columnUIModel.addPropertyChangeListener(getRepeatPropertyChangeListener()); //repeat constraints property change events
columnUIModelMap.put(column, columnUIModel); //store the column UI model in the map
}
} finally {
columnUIModelMap.writeLock().unlock(); //always release the write lock
}
}
return columnUIModel; //return the column UI model we found
}
/**
* Returns the label font families for a given column.
* @param column The column for which the label font families should be returned.
* @return The prioritized list of label font family names, or null
if no label font family names have been specified.
* @throws NullPointerException if the given column is null
.
*/
public List getColumnLabelFontFamilies(final TableColumnModel> column) {
return getColumnUIModel(column).getLabelFontFamilies();
}
/**
* Sets the font families of the label for a given column. This is a bound property.
* @param column The column for which the label font families should be set.
* @param newLabelFontFamilies The new prioritized list of label font family names, or null
if no label font family names are specified.
* @throws NullPointerException if the given column is null
.
* @see ColumnUIModel#LABEL_FONT_FAMILIES_PROPERTY
*/
public void setColumnLabelFontFamilies(final TableColumnModel> column, final List newLabelFontFamilies) {
getColumnUIModel(column).setLabelFontFamilies(newLabelFontFamilies);
}
/**
* Sets the font families of the labels of all columns. This is a bound property for each column.
* @param newLabelFontFamilies The new prioritized list of label font family names, or null
if no label font family names are specified.
* @see ColumnUIModel#LABEL_FONT_FAMILIES_PROPERTY
*/
public void setColumnLabelFontFamilies(final List newLabelFontFamilies) {
for(final TableColumnModel> column : getColumns()) { //for each column
setColumnLabelFontFamilies(column, newLabelFontFamilies); //set the label font families
}
}
/**
* Returns the label font size for a given column.
* @param column The column for which the label font size should be returned.
* @return The size of the label font from baseline to baseline, or null
if no label font size has been specified.
* @throws NullPointerException if the given column is null
.
*/
public Extent getColumnLabelFontSize(final TableColumnModel> column) {
return getColumnUIModel(column).getLabelFontSize();
}
/**
* Sets the label font size of a given column. This is a bound property.
* @param column The column for which the label font size should be set.
* @param newLabelFontSize The new size of the label font from baseline to baseline, or null
there is no label font size specified.
* @throws NullPointerException if the given column is null
.
* @see ColumnUIModel#LABEL_FONT_SIZE_PROPERTY
*/
public void setColumnLabelFontSize(final TableColumnModel> column, final Extent newLabelFontSize) {
getColumnUIModel(column).setLabelFontSize(newLabelFontSize);
}
/**
* Sets the label font size of all columns. This is a bound property for each column.
* @param newLabelFontSize The new size of the label font from baseline to baseline, or null
there is no label font size specified.
* @see ColumnUIModel#LABEL_FONT_SIZE_PROPERTY
*/
public void setColumnLabelFontSize(final Extent newLabelFontSize) {
for(final TableColumnModel> column : getColumns()) { //for each column
setColumnLabelFontSize(column, newLabelFontSize); //set the label font size
}
}
/**
* Returns the label font style for a given column.
* @param column The column for which the label font style should be returned.
* @return The style of the label font.
* @throws NullPointerException if the given column is null
.
*/
public FontStyle getColumnLabelFontStyle(final TableColumnModel> column) {
return getColumnUIModel(column).getLabelFontStyle();
}
/**
* Sets the style of the label font for a given column. This is a bound property.
* @param column The column for which the label font size should be set.
* @param newLabelFontStyle The style of the label font.
* @throws NullPointerException if the given column and/or label font style is null
.
* @see ColumnUIModel#LABEL_FONT_STYLE_PROPERTY
*/
public void setColumnLabelFontStyle(final TableColumnModel> column, final FontStyle newLabelFontStyle) {
getColumnUIModel(column).setLabelFontStyle(newLabelFontStyle);
}
/**
* Sets the style of the label font for all columns. This is a bound property of each column.
* @param newLabelFontStyle The style of the label font.
* @throws NullPointerException if the given label font style is null
.
* @see ColumnUIModel#LABEL_FONT_STYLE_PROPERTY
*/
public void setColumnLabelFontStyle(final FontStyle newLabelFontStyle) {
for(final TableColumnModel> column : getColumns()) { //for each column
setColumnLabelFontStyle(column, newLabelFontStyle); //set the label font style
}
}
/**
* Returns the label font weight for a given column.
* @param column The column for which the label font weight should be returned.
* @return The weight of the label font relative to a normal value of 0.5.
* @throws NullPointerException if the given column is null
.
*/
public double getColumnLabelFontWeight(final TableColumnModel> column) {
return getColumnUIModel(column).getLabelFontWeight();
}
/**
* Sets the weight of the label font of a given column. The weight of the label font relative to a normal value of 0.5. A font weight of 0.75 is equivalent to
* a bold font. It is recommended that the constant variables {@link PresentationModel#FONT_WEIGHT_NORMAL} and {@link PresentationModel#FONT_WEIGHT_BOLD} be
* used for the most compatibility across platforms. This is a bound property of type {@link Double}.
* @param column The column for which the label font weight should be set.
* @param newLabelFontWeight The weight of the label font relative to a normal value of 0.5.
* @throws NullPointerException if the given column is null
.
* @see PresentationModel#FONT_WEIGHT_PROPERTY
* @see PresentationModel#FONT_WEIGHT_NORMAL
* @see PresentationModel#FONT_WEIGHT_BOLD
*/
public void setColumnLabelFontWeight(final TableColumnModel> column, final double newLabelFontWeight) {
getColumnUIModel(column).setLabelFontWeight(newLabelFontWeight);
}
/**
* Sets the weight of the label font of all columns. The weight of the label font relative to a normal value of 0.5. A font weight of 0.75 is equivalent to a
* bold font. It is recommended that the constant variables {@link PresentationModel#FONT_WEIGHT_NORMAL} and {@link PresentationModel#FONT_WEIGHT_BOLD} be
* used for the most compatibility across platforms. This is a bound property of type {@link Double}.
* @param newLabelFontWeight The weight of the label font relative to a normal value of 0.5.
* @see PresentationModel#FONT_WEIGHT_PROPERTY
* @see PresentationModel#FONT_WEIGHT_NORMAL
* @see PresentationModel#FONT_WEIGHT_BOLD
*/
public void setColumnLabelFontWeight(final double newLabelFontWeight) {
for(final TableColumnModel> column : getColumns()) { //for each column
setColumnLabelFontWeight(column, newLabelFontWeight); //set the label font weight
}
}
/**
* Returns the padding extent of the indicated column border.
* @param column The column for which a padding extent should be returned.
* @param border The border for which a padding extent should be returned.
* @return The padding extent of the given column border.
* @throws NullPointerException if the given column is null
.
*/
public Extent getColumnPaddingExtent(final TableColumnModel> column, final Border border) {
return getColumnUIModel(column).getPaddingExtent(border);
}
/**
* Returns the padding extent of the column line near page near border.
* @param column The column for which a padding extent should be returned.
* @return The padding extent of the given column border.
* @throws NullPointerException if the given column is null
.
*/
public Extent getColumnPaddingLineNearExtent(final TableColumnModel> column) {
return getColumnUIModel(column).getPaddingLineNearExtent();
}
/**
* Returns the padding extent of the column line far page near border.
* @param column The column for which a padding extent should be returned.
* @return The padding extent of the given column border.
* @throws NullPointerException if the given column is null
.
*/
public Extent getColumnPaddingLineFarExtent(final TableColumnModel> column) {
return getColumnUIModel(column).getPaddingLineFarExtent();
}
/**
* Returns the padding extent of the column line near page far border.
* @param column The column for which a padding extent should be returned.
* @return The padding extent of the given column border.
* @throws NullPointerException if the given column is null
.
*/
public Extent getColumnPaddingPageNearExtent(final TableColumnModel> column) {
return getColumnUIModel(column).getPaddingPageNearExtent();
}
/**
* Returns the padding extent of the column line far page far border.
* @param column The column for which a padding extent should be returned.
* @return The padding extent of the given column border.
* @throws NullPointerException if the given column is null
.
*/
public Extent getColumnPaddingPageFarExtent(final TableColumnModel> column) {
return getColumnUIModel(column).getPaddingPageFarExtent();
}
/**
* Sets the padding extent of a given column border. The padding extent of each column border represents a bound property.
* @param column The column for which the padding extent should be set.
* @param border The border for which the padding extent should be set.
* @param newPaddingExtent The padding extent.
* @throws NullPointerException if the given column, border and/or padding extent is null
.
* @see ColumnUIModel#PADDING_LINE_NEAR_EXTENT_PROPERTY
* @see ColumnUIModel#PADDING_LINE_FAR_EXTENT_PROPERTY
* @see ColumnUIModel#PADDING_PAGE_NEAR_EXTENT_PROPERTY
* @see ColumnUIModel#PADDING_PAGE_FAR_EXTENT_PROPERTY
*/
public void setColumnPaddingExtent(final TableColumnModel> column, final Border border, final Extent newPaddingExtent) {
getColumnUIModel(column).setPaddingExtent(border, newPaddingExtent);
}
/**
* Sets the padding extent of the column line near border. This is a bound property.
* @param column The column for which the padding extent should be set.
* @param newPaddingExtent The padding extent.
* @throws NullPointerException if the given column and/or padding extent is null
.
* @see ColumnUIModel#PADDING_LINE_NEAR_EXTENT_PROPERTY
*/
public void setColumnPaddingLineNearExtent(final TableColumnModel> column, final Extent newPaddingExtent) {
getColumnUIModel(column).setPaddingLineNearExtent(newPaddingExtent);
}
/**
* Sets the padding extent of the column line far border. This is a bound property.
* @param column The column for which the padding extent should be set.
* @param newPaddingExtent The padding extent, or null
if the default padding extent should be used.
* @throws NullPointerException if the given column and/or padding extent is null
.
* @see ColumnUIModel#PADDING_LINE_FAR_EXTENT_PROPERTY
*/
public void setColumnPaddingLineFarExtent(final TableColumnModel> column, final Extent newPaddingExtent) {
getColumnUIModel(column).setPaddingLineFarExtent(newPaddingExtent);
}
/**
* Sets the padding extent of the column page near border. This is a bound property.
* @param column The column for which the padding extent should be set.
* @param newPaddingExtent The padding extent, or null
if the default padding extent should be used.
* @throws NullPointerException if the given columna and/or padding extent is null
.
* @see ColumnUIModel#PADDING_PAGE_NEAR_EXTENT_PROPERTY
*/
public void setColumnPaddingPageNearExtent(final TableColumnModel> column, final Extent newPaddingExtent) {
getColumnUIModel(column).setPaddingPageNearExtent(newPaddingExtent);
}
/**
* Sets the padding extent of the column page far border. This is a bound property.
* @param column The column for which the padding extent should be set.
* @param newPaddingExtent The padding extent, or null
if the default padding extent should be used.
* @throws NullPointerException if the given column and/or padding extent is null
.
* @see ColumnUIModel#PADDING_PAGE_FAR_EXTENT_PROPERTY
*/
public void setColumnPaddingPageFarExtent(final TableColumnModel> column, final Extent newPaddingExtent) {
getColumnUIModel(column).setPaddingPageFarExtent(newPaddingExtent);
}
/**
* Sets the padding extent of all borders of a column. The padding extent of each column border represents a bound property.
* @param column The column for which the padding extent should be set.
* @param newPaddingExtent The padding extent.
* @throws NullPointerException if the given column and/or padding extent is null
.
* @see ColumnUIModel#PADDING_LINE_NEAR_EXTENT_PROPERTY
* @see ColumnUIModel#PADDING_LINE_FAR_EXTENT_PROPERTY
* @see ColumnUIModel#PADDING_PAGE_NEAR_EXTENT_PROPERTY
* @see ColumnUIModel#PADDING_PAGE_FAR_EXTENT_PROPERTY
*/
public void setColumnPaddingExtent(final TableColumnModel> column, final Extent newPaddingExtent) {
getColumnUIModel(column).setPaddingExtent(newPaddingExtent);
}
/**
* Sets the padding extent of a all column borders of all columns. The padding extent of each column border represents a bound property.
* @param border The border for which the padding extent should be set.
* @param newPaddingExtent The padding extent.
* @throws NullPointerException if the border and/or padding extent is null
.
* @see ColumnUIModel#PADDING_LINE_NEAR_EXTENT_PROPERTY
* @see ColumnUIModel#PADDING_LINE_FAR_EXTENT_PROPERTY
* @see ColumnUIModel#PADDING_PAGE_NEAR_EXTENT_PROPERTY
* @see ColumnUIModel#PADDING_PAGE_FAR_EXTENT_PROPERTY
*/
public void setColumnPaddingExtent(final Border border, final Extent newPaddingExtent) {
for(TableColumnModel> column : getColumns()) { //for each column
getColumnUIModel(column).setPaddingExtent(border, newPaddingExtent); //set the padding extent of the border for this column
}
}
/**
* Sets the padding extent of the line near border of all columns. This is a bound property.
* @param newPaddingExtent The padding extent.
* @throws NullPointerException if the given padding extent is null
.
* @see ColumnUIModel#PADDING_LINE_NEAR_EXTENT_PROPERTY
*/
public void setColumnPaddingLineNearExtent(final Extent newPaddingExtent) {
setColumnPaddingExtent(Border.LINE_NEAR, newPaddingExtent);
}
/**
* Sets the padding extent of the line far border of all columns. This is a bound property.
* @param newPaddingExtent The padding extent, or null
if the default padding extent should be used.
* @throws NullPointerException if the given padding extent is null
.
* @see ColumnUIModel#PADDING_LINE_FAR_EXTENT_PROPERTY
*/
public void setColumnPaddingLineFarExtent(final Extent newPaddingExtent) {
setColumnPaddingExtent(Border.LINE_FAR, newPaddingExtent);
}
/**
* Sets the padding extent of the page near border of all columns. This is a bound property.
* @param newPaddingExtent The padding extent, or null
if the default padding extent should be used.
* @throws NullPointerException if the given padding extent is null
.
* @see ColumnUIModel#PADDING_PAGE_NEAR_EXTENT_PROPERTY
*/
public void setColumnPaddingPageNearExtent(final Extent newPaddingExtent) {
setColumnPaddingExtent(Border.PAGE_NEAR, newPaddingExtent);
}
/**
* Sets the padding extent of the page far border of all columns. This is a bound property.
* @param newPaddingExtent The padding extent, or null
if the default padding extent should be used.
* @throws NullPointerException if the given padding extent is null
.
* @see ColumnUIModel#PADDING_PAGE_FAR_EXTENT_PROPERTY
*/
public void setColumnPaddingPageFarExtent(final Extent newPaddingExtent) {
setColumnPaddingExtent(Border.PAGE_FAR, newPaddingExtent);
}
/**
* Sets the padding extent of all borders of all columns. The padding extent of each border represents a bound property. This is a convenience method that
* calls {@link #setColumnPaddingExtent(Border, Extent)} for each border.
* @param newPaddingExtent The padding extent.
* @throws NullPointerException if the given padding extent is null
.
* @see ColumnUIModel#PADDING_LINE_NEAR_EXTENT_PROPERTY
* @see ColumnUIModel#PADDING_LINE_FAR_EXTENT_PROPERTY
* @see ColumnUIModel#PADDING_PAGE_NEAR_EXTENT_PROPERTY
* @see ColumnUIModel#PADDING_PAGE_FAR_EXTENT_PROPERTY
*/
public void setColumnPaddingExtent(final Extent newPaddingExtent) {
for(final Border border : Border.values()) { //for each border
setColumnPaddingExtent(border, newPaddingExtent); //set this padding extent
}
}
/**
* Value class and column names constructor with a default data model. Default cell representation strategies will be installed for the value classes of the
* indicated columns.
* @param The type of values in all the cells in the table.
* @param valueClass The class indicating the type of values held in the model.
* @param columnNames The names to serve as label headers for the columns.
* @throws NullPointerException if the given value class is null
.
*/
public Table(final Class valueClass, final String... columnNames) {
this(new DefaultTableModel(valueClass, null, columnNames)); //construct the class with no default data
}
/**
* Columns constructor with a default data model. Default cell representation strategies will be installed for the value classes of the given columns.
* @param columns The models representing the table columns.
*/
public Table(final TableColumnModel>... columns) {
this(new DefaultTableModel(null, columns)); //construct the class with no default data
}
/**
* Value class, table data, and column names constructor with a default data model. Default cell representation strategies will be installed for the value
* classes of the indicated columns.
* @param The type of values in all the cells in the table.
* @param valueClass The class indicating the type of values held in the model.
* @param rowValues The two-dimensional list of values, where the first index represents the row and the second represents the column, or null
if
* no default values should be given.
* @param columnNames The names to serve as label headers for the columns.
* @throws NullPointerException if the given value class is null
.
* @throws IllegalArgumentException if the given number of columns does not equal the number of columns in any given data row.
* @throws ClassCastException if one of the values in a row is not compatible with the type of its column.
*/
public Table(final Class valueClass, final C[][] rowValues, final String... columnNames) {
this(new DefaultTableModel(valueClass, rowValues, columnNames)); //construct the class with a default model
}
/**
* Table data and columns constructor with a default data model. Default cell representation strategies will be installed for the value classes of the given
* columns.
* @param rowValues The two-dimensional list of values, where the first index represents the row and the second represents the column, or null
if
* no default values should be given.
* @param columns The models representing the table columns.
* @throws IllegalArgumentException if the given number of columns does not equal the number of columns in any given data row.
* @throws ClassCastException if one of the values in a row is not compatible with the type of its column.
*/
public Table(final Object[][] rowValues, final TableColumnModel>... columns) {
this(new DefaultTableModel(rowValues, columns)); //construct the class with a default model
}
/**
* Table model constructor. Default cell representation strategies will be installed for the value classes of all the model's columns.
* @param tableModel The component data model.
* @throws NullPointerException if the given table model is null
.
*/
public Table(final TableModel tableModel) {
this.tableModel = requireNonNull(tableModel, "Table model cannot be null."); //save the table model
this.tableModel.addPropertyChangeListener(getRepeatPropertyChangeListener()); //listen and repeat all property changes of the table model
this.tableModel.addVetoableChangeListener(getRepeatVetoableChangeListener()); //listen and repeat all vetoable changes of the table model
//TODO listen to and repeat table model events
for(final TableColumnModel> column : tableModel.getColumns()) { //install a default cell representation strategy for each column's value class
installDefaultCellRepresentationStrategy(column); //create and install a default representation strategy for this column's value class
}
getSession().addPropertyChangeListener(GuiseSession.LOCALE_PROPERTY, new AbstractGenericPropertyChangeListener() { //listen for the session locale changing
@Override
public void propertyChange(GenericPropertyChangeEvent propertyChangeEvent) { //if the locale changes
clearComponentStates(); //clear all the components and component states in case they are locale-related TODO probably transfer this up to the abstract composite state class
}
});
if(tableModel instanceof ListListenable) { //if this table model allows list listeners TODO improve this; create a table model listener---maybe that will implement ListListener
final ListListenable