Files
Brainstorm/Foundation SWT/src/com/foundation/view/swt/TableComponent.java
2014-05-30 10:31:51 -07:00

2239 lines
86 KiB
Java

/*
* Copyright (c) 2005,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Pattern;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Region;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Widget;
import com.common.comparison.Comparator;
import com.common.debug.Debug;
import com.common.thread.IRunnable;
import com.common.util.ICollection;
import com.common.util.IHashMap;
import com.common.util.IHashSet;
import com.common.util.IIterator;
import com.common.util.IList;
import com.common.util.LiteHashMap;
import com.common.util.LiteHashSet;
import com.common.util.LiteList;
import com.foundation.metadata.Attribute;
import com.foundation.view.*;
import com.foundation.view.resource.AbstractResourceService;
import com.foundation.view.resource.ResourceReference;
import com.foundation.view.swt.util.SwtUtilities;
public abstract class TableComponent extends CollectionComponent {
/** The font resource for the control rows. (Note: This overrides the base font for the control defined by the Component class.) */
private MultiResourceAssociation rowFont = new MultiResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_FONT, false, null);
/** The background color resource for the control. */
private MultiResourceAssociation rowBackgroundColorCustom = new MultiResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_COLOR, false, null);
/** The foreground color resource for the control. */
private MultiResourceAssociation rowForegroundColorCustom = new MultiResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_COLOR, false, null);
/** The background color resource for the control. */
private SingleResourceAssociation rowBackgroundColor = new SingleResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_COLOR, false, null);
/** The foreground color resource for the control. */
private SingleResourceAssociation rowForegroundColor = new SingleResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_COLOR, false, null);
/** The background color resource for the control. */
private SingleResourceAssociation rowBackgroundColorAlt = new SingleResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_COLOR, false, null);
/** The foreground color resource for the control. */
private SingleResourceAssociation rowForegroundColorAlt = new SingleResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_COLOR, false, null);
/** The selection color resource for the control. */
private VariableResourceAssociation rowSelectionGradient = new VariableResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_GRADIENT, false, null);
/** The row height used. */
private SingleResourceAssociation rowHeight = new SingleResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_INTEGER, false, null);
/** A holder for the value of the row background color. <b>Will be null if not being used by the control.</b> */
protected ResourceHolder rowBackgroundColorHolder = null;
/** A holder for the value of the row foreground color. <b>Will be null if not being used by the control.</b> */
protected ResourceHolder rowForegroundColorHolder = null;
/** A holder for the value of the alternate row background color. This is used to alternate between colors for rows. This is overridden by custom colors for a row. <b>Will be null if not being used by the control.</b> */
protected ResourceHolder rowBackgroundColorAltHolder = null;
/** A holder for the value of the alternate row foreground color. This is used to alternate between colors for rows. This is overridden by custom colors for a row. <b>Will be null if not being used by the control.</b> */
protected ResourceHolder rowForegroundColorAltHolder = null;
/** The holder for the row selection color that applies to all rows. */
private ResourceHolder selectionGradientHolder = new ResourceHolder(this);
/** The collection of visible columns ordered by their model side zero based index. */
private IList tableColumns = new LiteList(16);
/** A mapping of rows by the collection values. This is primarily used to manage the selection(s). RowObject's contain a referenceCount to handle multiple instances of the same item in the collection. */
private LiteHashMap rowObjectByValueMap = new LiteHashMap(100, com.common.comparison.Comparator.getLogicalComparator(), null);
/** Tracks whether or not to try updating the selection if the collection changed. */
private boolean isSelectionInvalid = false;
/** The currently selected index (on the server) if auto synchronizing and allowing only a single selection. */
private TableRowObject currentlySelectedRow = null;
/** The optional gradient used to fill the background for rows that are selected. This is the value to be used if the individual row doesn't have a value. */
protected JefGradient selectionGradient = null;
/** The first color in the gradient. This is the value to be used if the individual row doesn't have a value. */
protected Color selectionGradientColor1 = null;
/** The second color in the gradient. This is the value to be used if the individual row doesn't have a value. */
protected Color selectionGradientColor2 = null;
/** The desired row height. This may be set to a positive number if the measure item event need be used to set the row height. */
protected int rowHeightValue = -1;
/** Allows us to ignore requests to update row coloring. */
private boolean suspendAlternatingRowColorUpdating = false;
/** The lowest from index used when calling the update method for alternating color updating while suspended, or -1 if no updating is required. */
private int suspendedAlternatingRowColorUpdateFromIndex = -1;
/** The mapping of image decoration data by the decoration object. This is used to improve efficiency when placing a decoration on multiple rows. */
protected IHashMap decorationDataMap = new LiteHashMap(10);
/**
* Maintains the image for the decoration. Also allows a decoration to be shared by multiple rows.
*/
protected class DecorationData implements IResourceHolderComponent {
private ResourceHolder imageHolder = new ResourceHolder(this);
private int referenceCount = 1;
private Image image = null;
private ImageDecoration decoration;
private int alpha;
/**
* DecorationData constructor.
* @param decoration The decoration this data object supports.
*/
public DecorationData(ImageDecoration decoration) {
this.decoration = decoration;
imageHolder.setValue(decoration.getImageReference());
alpha = (int) Math.round(255 * decoration.getAlpha());
}//DecorationData()//
/**
* Gets the alpha value to use when rendering the image.
* @return The alpha for drawing the image.
*/
public int getAlpha() {
return alpha;
}//getAlpha()//
/**
* Increments the reference counter for the decoration.
*/
public void incrementReferenceCount() {
referenceCount++;
}//incrementReferenceCount()//
/**
* Decrements the reference counter for the decoration.
* @return The reference count for the decoration data.
*/
public int decrementReferenceCount() {
return --referenceCount;
}//decrementReferenceCount()//
/* (non-Javadoc)
* @see com.foundation.view.IResourceHolderComponent#getResourceService()
*/
public AbstractResourceService getResourceService() {
return TableComponent.this.getResourceService();
}//getResourceService()//
/* (non-Javadoc)
* @see com.foundation.view.IResourceHolderComponent#resourceHolderChanged(com.foundation.view.AbstractMultiResourceHolder, com.common.util.IHashSet, java.lang.Object, java.lang.Object)
*/
public void resourceHolderChanged(AbstractMultiResourceHolder resourceHolder, IHashSet rows, Object oldValue, Object newValue) {
}//resourceHolderChanged()//
/* (non-Javadoc)
* @see com.foundation.view.IResourceHolderComponent#resourceHolderChanged(com.foundation.view.AbstractMultiResourceHolder, java.lang.Object, java.lang.Object, java.lang.Object)
*/
public void resourceHolderChanged(AbstractMultiResourceHolder resourceHolder, Object row, Object oldValue, Object newValue) {
}//resourceHolderChanged()//
/* (non-Javadoc)
* @see com.foundation.view.IResourceHolderComponent#resourceHolderChanged(com.foundation.view.AbstractResourceHolder, java.lang.Object, java.lang.Object)
*/
public void resourceHolderChanged(AbstractResourceHolder resourceHolder, Object oldValue, Object newValue, int flags) {
if(image != null) {
destroyImage(image);
}//if//
image = createImage((JefImage) newValue);
}//resourceHolderChanged()//
/**
* Disposes of the resources held by the decoration data.
*/
public void dispose() {
if(image != null) {
destroyImage(image);
imageHolder.release();
image = null;
}//if//
}//dispose()//
/**
* Gets the image for the decoration.
* @return The decoration's image, or null if none could be found.
*/
public Image getImage() {
return image;
}//getImage()//
}//DecorationData//
/**
* A customized row object.
*/
protected class TableRowObject extends RowObject implements IResourceHolderComponent {
/** The single table item object as defined by the control (TableItem). If this is null then controlItems should not be null. */
public Object controlItem = null;
/** A collection of table item objects as defined by the control (TableItem). If this is null then controlItem should not be null. */
public IList controlItems = null;
/** A holder for the value of the row background color. If this holder has a value for a row then it will override the normal row coloring. */
public ResourceHolder rowBackgroundColorCustomHolder = null;
/** A holder for the value of the row foreground color. If this holder has a value for a row then it will override the normal row coloring. */
public ResourceHolder rowForegroundColorCustomHolder = null;
/** A holder for the value of the row selection color. TODO: This should be moved into the SimpleTableRowObject and should become a single ResourceHolder. It should be null until used, and if the input becomes null then it should be removed. */
public ResourceHolder rowSelectionGradientHolder = null;
/** A holder for the value of the row font. (Note: This overrides the base font for the control defined by the Component class.) */
public ResourceHolder rowFontHolder = null;
/** The highlight decoration data currently applied to the row(s). */
public HighlightDecoration highlightDecoration = null;
/** The optional gradient used to fill the background for rows that are selected. */
public JefGradient selectionGradient = null;
/** The first color in the gradient. */
public Color selectionGradientColor1 = null;
/** The second color in the gradient. */
public Color selectionGradientColor2 = null;
/** The set of DecoratonData instances that are applied to the row. The data contains the image to be displayed. */
public IList decorations = null;
/**
* TableRowObject constructor.
* @param value The value that this row object represents.
*/
public TableRowObject(Object value) {
super(value);
}//TableRowObject()//
/**
* Adds a control item that represents this row object in the table.
* @param item The control item which is control dependant (ie TableItem).
*/
public void addControlItem(Object item) {
if((controlItem == null) && (controlItems == null)) {
controlItem = item;
}//if//
else if(controlItem != null) {
controlItems = new LiteList(10, 40);
controlItems.add(controlItem);
controlItems.add(item);
controlItem = null;
}//else if//
else {
controlItems.add(item);
}//else//
}//addControlItem()//
/**
* Replaces the old control item with the new.
* @param oldItem The control item to be replaced.
* @param newItem The control item to replace the old.
*/
public void replaceControlItem(Object oldItem, Object newItem) {
if((controlItem != null) || (controlItems == null)) {
controlItem = newItem;
}//if//
else {
controlItems.replace(oldItem, newItem);
}//else//
}//replaceControlItem()//
/**
* Releases any resources held by the row object.
*/
public void dispose() {
if(rowBackgroundColorCustomHolder != null) rowBackgroundColorCustomHolder.release();
if(rowForegroundColorCustomHolder != null) rowForegroundColorCustomHolder.release();
if(rowSelectionGradientHolder != null) rowSelectionGradientHolder.release();
if(rowFontHolder != null) rowFontHolder.release();
if(selectionGradientColor1 != null) destroyColor(selectionGradientColor1);
if(selectionGradientColor2 != null) destroyColor(selectionGradientColor2);
selectionGradient = null;
if(decorations != null) {
for(int index = 0; index < decorations.getSize(); index++) {
DecorationData next = (DecorationData) decorations.get(index);
if(next.decrementReferenceCount() == 0) {
decorationDataMap.remove(next.decoration);
next.dispose();
}//if//
}//for//
}//if//
super.dispose();
}//dispose()//
/* (non-Javadoc)
* @see com.foundation.view.IResourceHolderComponent#resourceHolderChanged(com.foundation.view.AbstractResourceHolder, java.lang.Object, java.lang.Object)
*/
public void resourceHolderChanged(AbstractResourceHolder resourceHolder, Object oldValue, Object newValue, int flags) {
verifyThread();
if(resourceHolder == rowBackgroundColorCustomHolder) {
if(controlItem == null) {
for(int index = 0; index < (controlItems == null ? 0 : controlItems.getSize()); index++) {
TableItem tableItem = (TableItem) controlItems.get(index);
destroyColor(tableItem.getBackground());
tableItem.setBackground(createColor((JefColor) newValue));
}//for//
}//if//
else {
TableItem tableItem = (TableItem) controlItem;
destroyColor(tableItem.getBackground());
tableItem.setBackground(createColor((JefColor) newValue));
}//else//
}//if//
else if(resourceHolder == rowForegroundColorCustomHolder) {
if(controlItem == null) {
for(int index = 0; index < (controlItems == null ? 0 : controlItems.getSize()); index++) {
TableItem tableItem = (TableItem) controlItems.get(index);
destroyColor(tableItem.getForeground());
tableItem.setForeground(createColor((JefColor) newValue));
}//for//
}//if//
else {
TableItem tableItem = (TableItem) controlItem;
destroyColor(tableItem.getForeground());
tableItem.setForeground(createColor((JefColor) newValue));
}//else//
}//else if//
else if(resourceHolder == rowSelectionGradientHolder) {
JefGradient color = newValue instanceof JefColor ? new JefGradient((JefColor) newValue) : (JefGradient) newValue;
selectionGradient = color;
destroyColor(selectionGradientColor1);
destroyColor(selectionGradientColor2);
selectionGradientColor1 = color != null && color.getStartColor() != null ? createColor(color.getStartColor()) : null;
selectionGradientColor2 = color != null && color.getEndColor() != null ? createColor(color.getEndColor()) : null;
}//else if//
else if(resourceHolder == rowFontHolder) {
if(controlItem == null) {
for(int index = 0; index < (controlItems == null ? 0 : controlItems.getSize()); index++) {
TableItem tableItem = (TableItem) controlItems.get(index);
destroyFont(tableItem.getFont());
tableItem.setFont(createFont((JefFont[]) newValue));
}//for//
}//if//
else {
TableItem tableItem = (TableItem) controlItem;
destroyFont(tableItem.getFont());
tableItem.setFont(createFont((JefFont[]) newValue));
}//else//
}//else if//
else {
Debug.log(new RuntimeException("Missing resource holder handler."));
}//else//
}//resourceHolderChanged()//
/* (non-Javadoc)
* @see com.foundation.view.IResourceHolderComponent#resourceHolderChanged(com.foundation.view.AbstractMultiResourceHolder, java.lang.Object, java.lang.Object, java.lang.Object)
*/
public void resourceHolderChanged(AbstractMultiResourceHolder resourceHolder, Object row, Object oldValue, Object newValue) {
//Never used.//
}//resourceHolderChanged()//
/* (non-Javadoc)
* @see com.foundation.view.IResourceHolderComponent#resourceHolderChanged(com.foundation.view.AbstractMultiResourceHolder, com.common.util.IHashSet, java.lang.Object, java.lang.Object)
*/
public void resourceHolderChanged(AbstractMultiResourceHolder resourceHolder, IHashSet rows, Object oldValue, Object newValue) {
//Never used.//
}//resourceHolderChanged()//
/* (non-Javadoc)
* @see com.foundation.view.IResourceHolderComponent#getResourceService()
*/
public AbstractResourceService getResourceService() {
return TableComponent.this.getResourceService();
}//getResourceService()//
}//TableRowObject//
/**
* Encapsulates all the data pertaining to a single column in the table component.
*/
public static abstract class AbstractColumn implements IAbstractComponent, IInternalAbstractComponent {
/**
* Registers an item in the collection with this column.
* <p>An item can be registered more than once, but must be unregistered just as many times.</p>
* @param item The item to be registered.
* @param rowObject The row object for the item.
*/
protected abstract void registerItem(Object item, TableRowObject rowObject);
/**
* Unregisters an item that had been previously registered.
* @param item The item to be unregistered.
*/
protected abstract void unregisterItem(Object item);
/**
* Unregisters all items that had been previously registered.
*/
protected abstract void unregisterAllItems();
/**
* Gets the column's creation index.
* @return The index assigned to this column and used to facilitate communication with the actual column resource in the display.
*/
protected abstract int getIndex();
/**
* Sets the column's creation index.
* @param index The index assigned to this column and used to facilitate communication with the actual column resource in the display.
*/
protected abstract void setIndex(int index);
/**
* Initializes the column before the table component is initialized.
*/
protected abstract void initialize();
/**
* Refreshes the column.
*/
protected abstract void refresh();
/**
* Releases the column before the table component is released.
*/
protected abstract void release();
/* (non-Javadoc)
* @see com.foundation.view.swt.IInternalAbstractComponent#getSwtWidget()
*/
public Widget getSwtWidget() {
return null;
}//getSwtWidget()//
}//AbstractColumn//
/**
* TableComponent constructor.
* @param parent The parent container for this component.
* @param name The name of the component.
* @param style The style for the control.
*/
public TableComponent(Container parent, String name, int style) {
super(parent, name, style);
}//TableComponent()//
/**
* Gets the SWT table that represents this simple table.
* @return The SWT table providing visualization for this simple table.
*/
public org.eclipse.swt.widgets.Table getSwtTable() {
return (org.eclipse.swt.widgets.Table) getSwtWidget();
}//getSwtTable()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IAbstractSwtContainer#getSwtComposite()
*/
public Composite getSwtComposite() {
return getSwtTable();
}//getSwtComposite()//
/**
* Gets the flag indicating whether the selection should be updated when the collection changes.
* @return Whether or not to try updating the selection if the collection changed.
*/
protected boolean isSelectionInvalid() {
return isSelectionInvalid;
}//isSelectionInvalid()//
/**
* Adds a column to the component.
* @param column The column to be added.
*/
protected void addColumn(AbstractColumn column) {
if(isInitialized()) {
//Allow the collection to suspend activites that would adversly affect performance while the collection make large scale changes.//
preChangeCollection();
}//if//
try {
tableColumns.add(column.getIndex(), column);
//Update the other column indices.//
for(int index = column.getIndex() + 1; index < tableColumns.getSize(); index++) {
((AbstractColumn) tableColumns.get(index)).setIndex(index);
}//for//
//Notify the control.//
controlAddColumn(column, column.getIndex());
}//try//
finally {
if(isInitialized()) {
//Allow the table to refresh its self.//
postChangeCollection();
}//if//
}//finally//
}//addColumn()//
/**
* Gets the number of columns in the table.
* @return The count of columns.
*/
protected int getColumnCount() {
return tableColumns.getSize();
}//getColumnCount()//
/**
* Gets the column at the given index.
* @param index The zero based column index.
* @return The column at the given index.
*/
protected AbstractColumn getColumn(int index) {
return (AbstractColumn) tableColumns.get(index);
}//getColumn()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#internalViewRefreshCollection(com.common.util.ICollection, com.common.util.ICollection)
*/
protected void internalViewRefreshCollection(ICollection newCollection, ICollection oldCollection) {
if(newCollection != null) {
IIterator itemIterator = newCollection.iterator();
//Remove all existing rows of data.//
controlRemoveAll();
//Get the array of strings representing the list contents.//
while(itemIterator.hasNext()) {
Object item = itemIterator.next();
TableRowObject rowObject = getRowObject(item);
Object controlItem;
//Add the row to the control and then track the item it generates.//
controlItem = controlAddRow(rowObject, -1);
rowObject.addControlItem(controlItem);
}//while//
}//if//
else {
//Remove all existing rows of data.//
controlRemoveAll();
forceSelectionEvent();
}//else//
//If the selection was invalid previously then refresh the selection since it may no longer be invalid.//
if(isSelectionInvalid) {
internalViewRefreshSelection();
}//if//
}//internalViewRefreshCollection()//
/**
* Creates a row object representing the row of data.
* @param value The row value.
* @return The row object that encapsulates the row value and related data.
*/
protected TableRowObject createRowObject(Object value) {
return new TableRowObject(value);
}//createRowObject()//
/**
* Gets the row object for the given row value.
* @param value The value that the row represents.
* @return The row metadata.
*/
protected TableRowObject getRowObject(Object value) {
return (TableRowObject) rowObjectByValueMap.get(value);
}//getRowObject()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#internalViewRefreshSelection(java.lang.Object)
*/
protected void internalViewRefreshSelection(Object selectedItem) {
if(selectedItem != null) {
TableRowObject rowObject = getRowObject(selectedItem);
if(rowObject == null) {
isSelectionInvalid = true;
internalViewRefreshSelection(null);
}//if//
else {
isSelectionInvalid = false;
internalViewRefreshSelection(new TableRowObject[] {rowObject});
}//else//
}//if//
else {
//No selection.//
internalViewRefreshSelection(null);
}//else//
}//internalViewRefreshSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#internalViewRefreshSelections(com.common.util.ICollection, com.common.util.ICollection)
*/
protected void internalViewRefreshSelections(ICollection newSelections, ICollection oldSelections) {
if(newSelections != null) {
LiteList selectionRows = new LiteList(newSelections.getSize());
TableRowObject[] selectionRowArray = null;
IIterator selectionIterator = newSelections.iterator();
//Apply differences between the selection collection and the control selection. Also remove all impossible selections.//
while(selectionIterator.hasNext()) {
Object selection = selectionIterator.next();
TableRowObject rowObject = getRowObject(selection);
if(rowObject == null) {
//An invalid selection because the selection is not in the collection of displayed values.//
selectionIterator.remove();
}//if//
else {
selectionRows.add(rowObject);
}//else//
}//while//
selectionRows.toArray(selectionRowArray = new TableRowObject[selectionRows.getSize()]);
internalViewRefreshSelection(selectionRowArray);
}//if//
else {
//Remove all selections.//
internalViewRefreshSelection(null);
}//else//
}//internalViewRefreshSelections()//
/**
* Refreshes the selections given the selected row objects.
* @param rowObjects The selected row objects. If this is null then there will be no selections.
*/
private void internalViewRefreshSelection(TableRowObject[] rowObjects) {
//For single-selection collections, set the currently selected id.//
if(!getAllowMultiSelection()) {
if((rowObjects != null) && (rowObjects.length > 1)) {
currentlySelectedRow = null;
//Error: Invalid message value!//
Debug.log(new RuntimeException("Error: Invalid message parameter! MESSAGE_SET_SELECTION"));
}//if//
else {
currentlySelectedRow = ((rowObjects == null) || (rowObjects.length == 0)) ? null : rowObjects[0];
}//else//
if(currentlySelectedRow != null) {
Object itemData = currentlySelectedRow.controlItem == null ? currentlySelectedRow.controlItems.getFirst() : currentlySelectedRow.controlItem;
controlSetSelection(itemData);
}//if//
else {
controlRemoveAllSelections();
}//else//
}//if//
else { //Allow multiple selections.//
if((rowObjects == null) || (rowObjects.length == 0)) {
//Clear all selections.//
controlRemoveAllSelections();
}//if//
else {
//TODO: Does this cause tracking? Where the user sees the selections occuring over time.//
//Clear all selections and then add the new selections.//
controlRemoveAllSelections();
internalAddSelections(rowObjects);
}//else//
}//else//
}//internalViewRefreshSelection()//
/**
* Adds the selections to the currently selected set.
* @param rowObjects The row objects to be selected.
*/
private void internalAddSelections(TableRowObject[] rowObjects) {
for(int index = 0; index < rowObjects.length; index++) {
internalAddSelection(rowObjects[index]);
}//for//
}//internalAddSelections()//
/**
* Adds the selection to the currently selected set.
* @param rowObject The row object to be selected.
*/
private void internalAddSelection(TableRowObject rowObject) {
if(rowObject.controlItems != null) {
//Search for the first table item that isn't selected.//
for(int index = 0; index < rowObject.controlItems.getSize(); index++) {
Object item = rowObject.controlItems.get(index);
if(!controlIsSelected(item)) {
controlAddSelection(item);
break;
}//if//
}//while//
}//if//
else {
controlAddSelection(rowObject.controlItem);
}//else//
}//internalAddSelections()//
/**
* Removes the selection from the currently selected set.
* @param rowObject The row object to no longer be selected.
*/
private void internalRemoveSelection(TableRowObject rowObject) {
if(rowObject.controlItems != null) {
//Search for the last table item that is selected.//
for(int index = rowObject.controlItems.getSize() - 1; index >= 0; index--) {
Object item = rowObject.controlItems.get(index);
if(controlIsSelected(item)) {
controlRemoveSelection(item);
break;
}//if//
}//for//
}//if//
else {
controlRemoveSelection(rowObject.controlItem);
}//else//
}//internalRemoveSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
//Initialize all the columns.//
for(int columnIndex = 0; columnIndex < tableColumns.getSize(); columnIndex++) {
((AbstractColumn) tableColumns.get(columnIndex)).initialize();
}//for//
rowBackgroundColor.initialize();
rowForegroundColor.initialize();
rowBackgroundColorAlt.initialize();
rowForegroundColorAlt.initialize();
rowSelectionGradient.initialize();
rowBackgroundColorCustom.initialize();
rowForegroundColorCustom.initialize();
rowFont.initialize();
rowHeight.initialize();
//Setup the listener for the measure item event.//
initializeMeasureItemListener();
//Setup the listener for the paint item event.//
initializePaintItemListener();
//Setup the listener for the paint event.//
initializePaintListener();
//Setup the listener for the erase item event.//
initializeEraseItemListener();
super.internalViewInitialize();
}//internalViewInitialize()//
/**
* Initializes the measure item listener.
*/
protected void initializeMeasureItemListener() {
getSwtTable().addListener(SWT.MeasureItem, new Listener() {
public void handleEvent(Event event) {
switch(event.type) {
case SWT.MeasureItem: {
if((rowHeightValue > 0) && (getSwtTable().getItemHeight() != rowHeightValue)) {
event.height = rowHeightValue;
}//if//
break;
}//case//
}//switch//
}//handleEvent()//
});
}//initializeMeasureItemListener()//
/**
* Initializes the paint listener.
*/
protected void initializePaintListener() {
}//initializePaintListener()//
/**
* Initializes the paint item listener.
*/
protected void initializePaintItemListener() {
getSwtTable().addListener(SWT.PaintItem, new Listener() {
public void handleEvent(Event event) {
int columnIndex = event.index;
TableItem item = (TableItem) event.item;
if(columnIndex == 0) {
TableRowObject rowObject = (TableRowObject) item.getData();
if(rowObject != null && rowObject.decorations != null) {
int xOffset = 0;
//Render each of the decorations in their current ordering.//
for(int decorationIndex = 0; decorationIndex < rowObject.decorations.getSize(); decorationIndex++) {
DecorationData nextDecoration = (DecorationData) rowObject.decorations.get(decorationIndex);
Rectangle imageArea = nextDecoration.getImage().getBounds();
int alpha = event.gc.getAlpha();
int yOffset = 0;
event.gc.setAdvanced(true);
event.gc.setAlpha(nextDecoration.getAlpha());
event.gc.drawImage(nextDecoration.getImage(), xOffset + event.x, yOffset + event.y);
xOffset += imageArea.width + 1;
event.gc.setAlpha(alpha);
}//for//
}//if//
}//if//
}//handleEvent()//
});
}//initializePaintItemListener()//
/**
* Initializes the erase item listener.
*/
protected void initializeEraseItemListener() {
getSwtTable().addListener(SWT.EraseItem, new Listener() {
//Note: The RowObject can be null if the event is fired due to an item being added.//
public void handleEvent(Event event) {
TableRowObject rowObject = (TableRowObject) event.item.getData();
JefGradient gradient = rowObject == null ? null : rowObject.selectionGradient;
Color color1 = rowObject == null ? null : rowObject.selectionGradientColor1;
Color color2 = rowObject == null ? null : rowObject.selectionGradientColor2;
event.detail &= ~SWT.HOT;
//Use the table wide gradient options if the row specific ones are not set.//
if(gradient == null || color1 == null) {
gradient = selectionGradient;
color1 = selectionGradientColor1;
color2 = selectionGradientColor2;
}//if//
//Only draw if there is at least one custom color and this is a selected row.//
if(gradient != null && color1 != null && (event.detail & SWT.SELECTED) != 0) {
GC gc = event.gc;
Rectangle area = getSwtTable().getClientArea();
int columnCount = getSwtTable().getColumnCount();
Rectangle rect = event.getBounds();
int direction = gradient.getDirection();
int alpha1 = gradient.getStartColor().getAlpha();
int alpha2 = gradient.getEndColor() != null ? gradient.getEndColor().getAlpha() : 0;
if(event.index == columnCount - 1 || columnCount == 0) {
int width = area.x + area.width - event.x;
if(width > 0) {
Region r = new Region();
gc.getClipping(r);
r.add(event.x, event.y, width, event.height);
gc.setClipping(r);
r.dispose();
}//if//
}//if//
rect.x = 0;
rect.width = area.width;
//Draw either a gradient or a filled rectangle.//
if(color2 != null && color2 != color1 && alpha1 != alpha2) {
gc.setAdvanced(true);
//Use the alphas if we can.//
if(gc.getAdvanced()) {
Pattern pattern = new Pattern(getDisplay(), (direction == JefGradient.REVERSE_DIAGONAL ? area.width : 0), 0, (direction == JefGradient.VERTICAL ? 1 : direction == JefGradient.REVERSE_DIAGONAL ? 0 : area.width), (direction == JefGradient.HORIZONTAL ? 1 : rect.height), color1, alpha1, color2, alpha2);
gc.setBackgroundPattern(pattern);
gc.fillRectangle(rect.x, rect.y, rect.width, rect.height);
}//if//
else {
Color foreground = gc.getForeground();
Color background = gc.getBackground();
gc.setForeground(color1);
gc.setBackground(color2); //getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND)
gc.fillGradientRectangle(rect.x, rect.y, rect.width, rect.height, direction == JefGradient.VERTICAL);
gc.setForeground(foreground);
gc.setBackground(background);
}//else//
}//if//
else {
Color foreground = gc.getForeground();
Color background = gc.getBackground();
gc.setAdvanced(true);
//Use the alpha if we can.//
if(gc.getAdvanced()) {
gc.setAlpha(alpha1);
}//if//
gc.setForeground(color1);
gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
gc.fillRectangle(rect.x, rect.y, rect.width, rect.height);
gc.setForeground(foreground);
gc.setBackground(background);
}//else//
event.detail &= ~SWT.SELECTED;
}//if//
}//handleEvent()//
});
}//initializeEraseItemListener()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
internalViewRefreshRowHeight();
if(rowSelectionGradient.isSingle() && rowSelectionGradient.refresh(null)) {
selectionGradientHolder.setValue(rowSelectionGradient.getValue(null));
}//if//
if(rowBackgroundColor.refresh()) {
if(rowBackgroundColorHolder == null) {
rowBackgroundColorHolder = new ResourceHolder(this);
}//if//
rowBackgroundColorHolder.setValue(rowBackgroundColor.getValue(), false);
}//if//
if(rowForegroundColor.refresh()) {
if(rowForegroundColorHolder == null) {
rowForegroundColorHolder = new ResourceHolder(this);
}//if//
rowForegroundColorHolder.setValue(rowForegroundColor.getValue(), false);
}//if//
if(rowBackgroundColorAlt.refresh()) {
if(rowBackgroundColorAltHolder == null) {
rowBackgroundColorAltHolder = new ResourceHolder(this);
}//if//
rowBackgroundColorAltHolder.setValue(rowBackgroundColorAlt.getValue(), false);
}//if//
if(rowForegroundColorAlt.refresh()) {
if(rowForegroundColorAltHolder == null) {
rowForegroundColorAltHolder = new ResourceHolder(this);
}//if//
rowForegroundColorAltHolder.setValue(rowForegroundColorAlt.getValue(), false);
}//if//
if(rowBackgroundColorHolder != null || rowForegroundColorHolder != null || rowBackgroundColorAltHolder != null || rowForegroundColorAltHolder != null) {
updateRowColors(0);
}//if//
super.internalViewRefresh();
//Refresh all the columns.//
for(int columnIndex = 0; columnIndex < tableColumns.getSize(); columnIndex++) {
((AbstractColumn) tableColumns.get(columnIndex)).refresh();
}//for//
}//internalViewRefresh()//
/**
* Refreshes the component's row height.
*/
protected void internalViewRefreshRowHeight() {
if(rowHeight.refresh()) {
Integer height = (Integer) rowHeight.getValue();
if(height != null) {
rowHeightValue = height.intValue();
}//if//
else {
rowHeightValue = -1;
}//else//
}//if//
}//internalViewRefreshRowHeight()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
IIterator iterator = rowObjectByValueMap.valueIterator();
rowBackgroundColorCustom.release();
rowForegroundColorCustom.release();
rowBackgroundColor.release();
rowBackgroundColorCustom.release();
rowForegroundColorCustom.release();
if(rowBackgroundColorHolder != null) rowBackgroundColorHolder.release();
rowForegroundColor.release();
if(rowForegroundColorHolder != null) rowForegroundColorHolder.release();
rowBackgroundColorAlt.release();
if(rowBackgroundColorAltHolder != null) rowBackgroundColorAltHolder.release();
rowForegroundColorAlt.release();
if(rowForegroundColorAltHolder != null) rowForegroundColorAltHolder.release();
rowSelectionGradient.release();
rowFont.release();
rowHeight.release();
while(iterator.hasNext()) {
((TableRowObject) iterator.next()).dispose();
}//while//
iterator = decorationDataMap.valueIterator();
while(iterator.hasNext()) {
((DecorationData) iterator.next()).dispose();
}//while//
//Remove all mappings.//
rowObjectByValueMap.removeAll();
//Release all the columns.//
for(int columnIndex = 0; columnIndex < tableColumns.getSize(); columnIndex++) {
((AbstractColumn) tableColumns.get(columnIndex)).release();
}//for//
super.internalViewRelease();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.MultiResourceAssociation, java.lang.Object)
*/
protected void internalOnValueChanged(MultiResourceAssociation resourceAssociation, Object item, Object data, boolean isUpdate) {
if(isInitialized()) {
if(resourceAssociation == rowBackgroundColorCustom) {
if(item != null) {
//Verify that the item cell data has actually been altered.//
if(rowBackgroundColorCustom.refresh(item)) {
TableRowObject rowObject = getRowObject(item);
if(rowObject.highlightDecoration == null || rowObject.highlightDecoration.getBackgroundColor() == null) {
Object value = rowBackgroundColorCustom.getValue(item);
if(rowObject.rowBackgroundColorCustomHolder == null && value != null) {
rowObject.rowBackgroundColorCustomHolder = new ResourceHolder(rowObject);
}//if//
rowObject.rowBackgroundColorCustomHolder.setValue(value);
if(value == null && rowObject.rowBackgroundColorCustomHolder != null) {
rowObject.rowBackgroundColorCustomHolder.release();
rowObject.rowBackgroundColorCustomHolder = null;
}//if//
}//if//
}//if//
}//if//
else {
//TODO: Does this ever get called?
if(rowBackgroundColorCustom.refresh(null)) {
Object value = rowBackgroundColorCustom.getValue(null);
IIterator iterator = getRowObjects();
while(iterator.hasNext()) {
TableRowObject rowObject = (TableRowObject) iterator.next();
if(rowObject.highlightDecoration == null || rowObject.highlightDecoration.getBackgroundColor() == null) {
if(rowObject.rowBackgroundColorCustomHolder == null && value != null) {
rowObject.rowBackgroundColorCustomHolder = new ResourceHolder(rowObject);
}//if//
rowObject.rowBackgroundColorCustomHolder.setValue(value);
if(value == null && rowObject.rowBackgroundColorCustomHolder != null) {
rowObject.rowBackgroundColorCustomHolder.release();
rowObject.rowBackgroundColorCustomHolder = null;
}//if//
}//if//
}//while//
}//if//
}//else//
}//if//
else if(resourceAssociation == rowForegroundColorCustom) {
if(item != null) {
//Verify that the item cell data has actually been altered.//
if(rowForegroundColorCustom.refresh(item)) {
TableRowObject rowObject = getRowObject(item);
if(rowObject.highlightDecoration == null || rowObject.highlightDecoration.getForegroundColor() == null) {
Object value = rowForegroundColorCustom.getValue(item);
if(rowObject.rowForegroundColorCustomHolder == null && value != null) {
rowObject.rowForegroundColorCustomHolder = new ResourceHolder(rowObject);
}//if//
rowObject.rowForegroundColorCustomHolder.setValue(value);
if(value == null && rowObject.rowForegroundColorCustomHolder != null) {
rowObject.rowForegroundColorCustomHolder.release();
rowObject.rowForegroundColorCustomHolder = null;
}//if//
}//if//
}//if//
}//if//
else {
//TODO: Does this ever get called?
if(rowForegroundColorCustom.refresh(null)) {
Object value = rowForegroundColorCustom.getValue(null);
IIterator iterator = getRowObjectValues();
while(iterator.hasNext()) {
TableRowObject rowObject = (TableRowObject) iterator.next();
if(rowObject.highlightDecoration == null || rowObject.highlightDecoration.getForegroundColor() == null) {
if(rowObject.rowForegroundColorCustomHolder == null && value != null) {
rowObject.rowForegroundColorCustomHolder = new ResourceHolder(rowObject);
}//if//
rowObject.rowForegroundColorCustomHolder.setValue(value);
if(value == null && rowObject.rowForegroundColorCustomHolder != null) {
rowObject.rowForegroundColorCustomHolder.release();
rowObject.rowForegroundColorCustomHolder = null;
}//if//
}//if//
}//while//
}//if//
}//else//
}//else if//
else if(rowSelectionGradient.hasAssociation(resourceAssociation)) {
if(item != null) {
//Verify that the item cell data has actually been altered.//
if(rowSelectionGradient.refresh(item)) {
TableRowObject rowObject = getRowObject(item);
if(rowObject.highlightDecoration == null || rowObject.highlightDecoration.getSelectionGradient() == null) {
Object value = rowSelectionGradient.getValue(item);
if(rowObject.rowSelectionGradientHolder == null && value != null) {
rowObject.rowSelectionGradientHolder = new ResourceHolder(rowObject);
}//if//
rowObject.rowSelectionGradientHolder.setValue(value);
if(value == null && rowObject.rowSelectionGradientHolder != null) {
rowObject.rowSelectionGradientHolder.release();
rowObject.rowSelectionGradientHolder = null;
}//if//
}//if//
}//if//
}//if//
else {
//TODO: Does this ever get called?
if(rowSelectionGradient.refresh(null)) {
Object value = rowSelectionGradient.getValue(null);
IIterator iterator = getRowObjectValues();
while(iterator.hasNext()) {
TableRowObject rowObject = (TableRowObject) iterator.next();
if(rowObject.highlightDecoration == null || rowObject.highlightDecoration.getSelectionGradient() == null) {
if(rowObject.rowSelectionGradientHolder == null && value != null) {
rowObject.rowSelectionGradientHolder = new ResourceHolder(rowObject);
}//if//
rowObject.rowSelectionGradientHolder.setValue(value);
if(value == null && rowObject.rowSelectionGradientHolder != null) {
rowObject.rowSelectionGradientHolder.release();
rowObject.rowSelectionGradientHolder = null;
}//if//
}//if//
}//while//
}//if//
}//else//
}//else if//
else if(resourceAssociation == rowFont) {
if(item != null) {
//Verify that the item cell data has actually been altered.//
if(rowFont.refresh(item)) {
TableRowObject rowObject = getRowObject(item);
if(rowObject.highlightDecoration == null || rowObject.highlightDecoration.getFont() == null) {
Object value = rowFont.getValue(item);
if(rowObject.rowFontHolder == null && value != null) {
rowObject.rowFontHolder = new ResourceHolder(rowObject);
}//if//
rowObject.rowFontHolder.setValue(value);
if(value == null && rowObject.rowFontHolder != null) {
rowObject.rowFontHolder.release();
rowObject.rowFontHolder = null;
}//if//
}//if//
}//if//
}//if//
else {
//TODO: Does this ever get called?
if(rowFont.refresh(null)) {
Object value = rowFont.getValue(null);
IIterator iterator = getRowObjectValues();
while(iterator.hasNext()) {
TableRowObject rowObject = (TableRowObject) iterator.next();
if(rowObject.highlightDecoration == null || rowObject.highlightDecoration.getFont() == null) {
if(rowObject.rowFontHolder == null && value != null) {
rowObject.rowFontHolder = new ResourceHolder(rowObject);
}//if//
rowObject.rowFontHolder.setValue(value);
if(value == null && rowObject.rowFontHolder != null) {
rowObject.rowFontHolder.release();
rowObject.rowFontHolder = null;
}//if//
}//if//
}//while//
}//if//
}//else//
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, item, data, isUpdate);
}//else//
}//if//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == rowHeight) {
internalViewRefreshRowHeight();
}//if//
else if(rowSelectionGradient.hasAssociation(resourceAssociation)) {
if(rowSelectionGradient.refresh(null)) {
selectionGradientHolder.setValue(rowSelectionGradient.getValue(null));
}//if//
}//else if//
else if(resourceAssociation == rowBackgroundColor) {
if(rowBackgroundColor.refresh()) {
rowBackgroundColorHolder.setValue(rowBackgroundColor.getValue());
}//if//
}//else if//
else if(resourceAssociation == rowForegroundColor) {
if(rowForegroundColor.refresh()) {
rowForegroundColorHolder.setValue(rowForegroundColor.getValue());
}//if//
}//else if//
else if(resourceAssociation == rowBackgroundColorAlt) {
if(rowBackgroundColorAlt.refresh()) {
rowBackgroundColorAltHolder.setValue(rowBackgroundColorAlt.getValue());
}//if//
}//else if//
else if(resourceAssociation == rowForegroundColorAlt) {
if(rowForegroundColorAlt.refresh()) {
rowForegroundColorAltHolder.setValue(rowForegroundColorAlt.getValue());
}//if//
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#internalResourceHolderChanged(com.foundation.view.swt.ResourceHolder, java.lang.Object, java.lang.Object)
*/
protected void internalResourceHolderChanged(ResourceHolder resource, Object oldValue, Object newValue, int flags) {
if(resource == selectionGradientHolder) {
JefGradient color = newValue instanceof JefColor ? new JefGradient((JefColor) newValue) : (JefGradient) newValue;
selectionGradient = color;
if(selectionGradientColor1 != null) {
destroyColor(selectionGradientColor1);
}//if//
if(selectionGradientColor2 != null) {
destroyColor(selectionGradientColor2);
}//if//
selectionGradientColor1 = color != null && color.getStartColor() != null ? createColor(color.getStartColor()) : null;
selectionGradientColor2 = color != null && color.getEndColor() != null ? createColor(color.getEndColor()) : null;
}//if//
else if(resource == rowBackgroundColorHolder) {
Table table = getSwtTable();
int itemCount = table.getItemCount();
int incrementCount = rowBackgroundColorAltHolder == null ? 1 : 2;
//For each row (or every other row if using an alt color also), check if the current color is custom, if not replace it.//
for(int index = 0; index < itemCount; index += incrementCount) {
TableItem next = table.getItem(index);
TableRowObject rowObject = (TableRowObject) next.getData();
if(rowObject.rowBackgroundColorCustomHolder == null) {
destroyColor(next.getBackground());
next.setBackground(createColor((JefColor) newValue));
}//if//
}//for//
}//else if//
else if(resource == rowForegroundColorHolder) {
Table table = getSwtTable();
int itemCount = table.getItemCount();
int incrementCount = rowForegroundColorAltHolder == null ? 1 : 2;
//For each row (or every other row if using an alt color also), check if the current color is custom, if not replace it.//
for(int index = 0; index < itemCount; index += incrementCount) {
TableItem next = table.getItem(index);
TableRowObject rowObject = (TableRowObject) next.getData();
if(rowObject.rowForegroundColorCustomHolder == null) {
destroyColor(next.getForeground());
next.setForeground(createColor((JefColor) newValue));
}//if//
}//for//
}//else if//
else if(resource == rowBackgroundColorAltHolder) {
Table table = getSwtTable();
int itemCount = table.getItemCount();
//Use the primary color if the alternate is null.//
if(newValue == null) {
newValue = rowBackgroundColorHolder.getValue();
}//if//
//For every odd row, check if the current color is custom, if not replace it.//
for(int index = 1; index < itemCount; index += 2) {
TableItem next = table.getItem(index);
TableRowObject rowObject = (TableRowObject) next.getData();
if(rowObject.rowBackgroundColorCustomHolder == null) {
destroyColor(next.getBackground());
next.setBackground(createColor((JefColor) newValue));
}//if//
}//for//
}//else if//
else if(resource == rowForegroundColorAltHolder) {
Table table = getSwtTable();
int itemCount = table.getItemCount();
//Use the primary color if the alternate is null.//
if(newValue == null) {
newValue = rowForegroundColorHolder.getValue();
}//if//
//For every odd row, check if the current color is custom, if not replace it.//
for(int index = 1; index < itemCount; index += 2) {
TableItem next = table.getItem(index);
TableRowObject rowObject = (TableRowObject) next.getData();
if(rowObject.rowForegroundColorCustomHolder == null) {
destroyColor(next.getForeground());
next.setForeground(createColor((JefColor) newValue));
}//if//
}//for//
}//else if//
else {
super.internalResourceHolderChanged(resource, oldValue, newValue, flags);
}//else//
}//internalResourceHolderChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#internalPreChangeCollection()
*/
protected void internalPreChangeCollection() {
super.internalPreChangeCollection();
suspendAlternatingRowColorUpdating = true;
}//internalPreChangeCollection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#internalPostChangeCollection()
*/
protected void internalPostChangeCollection() {
super.internalPostChangeCollection();
suspendAlternatingRowColorUpdating = false;
//Update the editors and renderers after large scale changes to the collection.//
updateRowColors(suspendedAlternatingRowColorUpdateFromIndex);
}//internalPostChangeCollection()//
/**
* Updates the row coloring.
* @param fromIndex The zero based index of the first row to examine.
*/
protected void updateRowColors(int fromIndex) {
if(fromIndex >= 0) {
if(!suspendAlternatingRowColorUpdating) {
Table table = getSwtTable();
//Warning: Don't just call createColor once since it must be called for each use to maintain a proper counter.//
JefColor foreground = rowForegroundColorHolder != null ? (JefColor) rowForegroundColorHolder.getValue() : null;
JefColor altForeground = rowForegroundColorAltHolder != null ? (JefColor) rowForegroundColorAltHolder.getValue() : foreground;
JefColor background = rowBackgroundColorHolder != null ? (JefColor) rowBackgroundColorHolder.getValue() : null;
JefColor altBackground = rowBackgroundColorAltHolder != null ? (JefColor) rowBackgroundColorAltHolder.getValue() : background;
for(int nextIndex = fromIndex; nextIndex < table.getItemCount(); nextIndex++) {
TableItem tableItem = table.getItem(nextIndex);
TableRowObject rowObject = (TableRowObject) tableItem.getData();
//Ensure there isn't a custom color, then set the correct color for the background.//
if(background != null && rowObject.rowBackgroundColorCustomHolder == null) {
destroyColor(tableItem.getBackground());
if((nextIndex % 2) == 1) {
tableItem.setBackground(createColor(altBackground));
}//if//
else {
tableItem.setBackground(createColor(background));
}//else//
}//if//
//Ensure there isn't a custom color, then set the correct color for the foreground.//
if(foreground != null && rowObject.rowForegroundColorCustomHolder == null) {
destroyColor(tableItem.getForeground());
if((nextIndex % 2) == 1) {
tableItem.setForeground(createColor(altForeground));
}//if//
else {
tableItem.setForeground(createColor(foreground));
}//else//
}//if//
}//for//
}//if//
else {
suspendedAlternatingRowColorUpdateFromIndex = suspendedAlternatingRowColorUpdateFromIndex == -1 ? fromIndex : Math.min(suspendedAlternatingRowColorUpdateFromIndex, fromIndex);
}//else//
}//if//
}//updateRowColors()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#itemAdded(java.lang.Object, int)
*/
protected final void itemAdded(Object item, int index) {
TableRowObject rowObject = null;
Object controlItem;
registerItem(item);
rowObject = getRowObject(item);
controlItem = controlAddRow(rowObject, index);
rowObject.addControlItem(controlItem);
}//itemAdded()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#itemRemoved(java.lang.Object, int)
*/
protected final void itemRemoved(Object item, int index) {
TableRowObject rowObject = getRowObject(item);
//Unregister the item so that we don't keep row objects around longer than necessary, and we unregister any listeners.//
unregisterItem(item);
//Note: Since removals are most often of selected items we will first try removing selected objects with the same object id.//
//If the exact row isn't specified or if there is only one of the item in the list then we can easily remove it.//
//Note: We currently do not support marking the table items with an index from the model, so the index is currently ignored.//
if(/*(index == -1) && */(rowObject.controlItems != null)) {
IIterator itemIterator = rowObject.controlItems.iterator();
Object controlItem = null;
//Search for the last table item that is selected.//
while((itemIterator.hasNext()) && (controlItem == null)) {
Object nextItem = itemIterator.next();
if(controlIsSelected(nextItem)) {
controlItem = nextItem;
}//if//
}//while//
//If we couldn't find a selected item, then remove the last item.//
if(controlItem == null) {
controlItem = rowObject.controlItems.remove(rowObject.controlItems.getSize() - 1);
}//if//
if(controlItem != null) {
if(controlIsSelected(controlItem)) {
//Ensure the selection is first removed.//
controlRemoveSelection(controlItem);
}//if//
//Remove the item from the table.//
controlRemoveRow(controlItem);
//Remove the control item mapping in the row object.//
rowObject.controlItems.remove(controlItem);
//Optimize the row object.//
if(rowObject.controlItems.getSize() == 1) {
rowObject.controlItem = rowObject.controlItems.getFirst();
rowObject.controlItems = null;
}//if//
}//if//
}//if//
else if(rowObject.controlItem != null) {
if(controlIsSelected(rowObject.controlItem)) {
//Ensure the selection is first removed.//
controlRemoveSelection(rowObject.controlItem);
}//if//
//Remove the item from the collection.//
controlRemoveRow(rowObject.controlItem);
//Clean up the row object.//
rowObject.controlItem = null;
}//else if//
}//itemRemoved()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#itemAllRemoved()
*/
protected final void itemAllRemoved() {
unregisterItems();
controlRemoveAll();
forceSelectionEvent();
}//itemAllRemoved()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#itemSorted(int[])
*/
protected void itemSorted(int[] mapping) {
controlOrderRows(mapping);
}//itemSorted()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#selectionAdded(java.lang.Object)
*/
protected void selectionAdded(Object value) {
TableRowObject rowObject = getRowObject(value);
if(rowObject != null) {
internalAddSelection(rowObject);
}//if//
}//selectionAdded()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#selectionRemoved(java.lang.Object)
*/
protected void selectionRemoved(Object value) {
TableRowObject rowObject = getRowObject(value);
if(rowObject != null) {
internalRemoveSelection(rowObject);
}//if//
}//selectionRemoved()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#selectionAllRemoved()
*/
protected void selectionAllRemoved() {
controlRemoveAllSelections();
}//selectionAllRemoved()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#registerItem(java.lang.Object)
*/
protected final void registerItem(Object item) {
TableRowObject rowObject = getRowObject(item);
//Add a value wrapper as necessary.//
if(rowObject != null) {
rowObject.referenceCount++;
}//if//
else {
rowObject = createRowObject(item);
//Add the object to the mappings.//
rowObjectByValueMap.put(item, rowObject);
}//else//
registerItem(item, rowObject);
}//registerItem()//
/**
* Registers the collection item with any and all listeners and associations.
* <p>This method provides the control an opportunity to register the item with any MultiResourceAssociations that are a part of the main control, and/or with any columns for those controls with them.</p>
* @param item The item in the collection being displayed.
* @param rowObject The row object for the item.
*/
protected void registerItem(Object item, TableRowObject rowObject) {
//Add the item to each of the columns so we receive updates.//
for(int index = 0; index < tableColumns.getSize(); index++) {
((AbstractColumn) tableColumns.get(index)).registerItem(item, rowObject);
}//for//
internalItemAdded(item);
//Register the item with the associations.//
rowBackgroundColorCustom.registerItem(item, rowObject);
if(rowBackgroundColorCustom.refresh(item)) {
if(rowObject.rowBackgroundColorCustomHolder == null) {
rowObject.rowBackgroundColorCustomHolder = new ResourceHolder(rowObject);
}//if//
rowObject.rowBackgroundColorCustomHolder.setValue(rowBackgroundColorCustom.getValue(item));
}//if//
rowForegroundColorCustom.registerItem(item, rowObject);
if(rowForegroundColorCustom.refresh(item)) {
if(rowObject.rowForegroundColorCustomHolder == null) {
rowObject.rowForegroundColorCustomHolder = new ResourceHolder(rowObject);
}//if//
rowObject.rowForegroundColorCustomHolder.setValue(rowForegroundColorCustom.getValue(item));
}//if//
if(rowSelectionGradient.isMulti()) {
rowSelectionGradient.registerItem(item, rowObject);
if(rowSelectionGradient.refresh(item)) {
if(rowObject.rowSelectionGradientHolder == null) {
rowObject.rowSelectionGradientHolder = new ResourceHolder(rowObject);
}//if//
rowObject.rowSelectionGradientHolder.setValue(rowSelectionGradient.getValue(item));
}//if//
}//if//
rowFont.registerItem(item, rowObject);
if(rowFont.refresh(item)) {
if(rowObject.rowFontHolder == null) {
rowObject.rowFontHolder = new ResourceHolder(rowObject);
}//if//
rowObject.rowFontHolder.setValue(rowFont.getValue(item));
}//if//
}//registerItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#unregisterItem(java.lang.Object)
*/
protected void unregisterItem(Object item) {
TableRowObject rowObject = getRowObject(item);
//Cleanup after the value wrapper.//
if(rowObject != null) {
if(rowObject.referenceCount == 1) {
rowObjectByValueMap.remove(item);
rowObject.dispose();
rowObject.value = null;
}//if//
else {
rowObject.referenceCount--;
}//else//
}//if//
//Unregister the value with the columns so we stop receiving updates.//
for(int index = 0; index < tableColumns.getSize(); index++) {
((AbstractColumn) tableColumns.get(index)).unregisterItem(item);
}//for//
internalItemRemoved(item);
rowBackgroundColorCustom.unregisterItem(item);
rowForegroundColorCustom.unregisterItem(item);
rowSelectionGradient.unregisterItem(item);
rowFont.unregisterItem(item);
}//unregisterItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#unregisterItems()
*/
protected void unregisterItems() {
IIterator iterator = rowObjectByValueMap.valueIterator();
while(iterator.hasNext()) {
((TableRowObject) iterator.next()).dispose();
}//while//
//Clean up after the items.//
internalItemsRemoved();
//Cleanup the row objects.//
rowObjectByValueMap.removeAll();
//Unregister the items from the columns so we stop recieving updates.//
for(int index = 0; index < tableColumns.getSize(); index++) {
((AbstractColumn) tableColumns.get(index)).unregisterAllItems();
}//for//
internalItemsRemoved();
rowBackgroundColorCustom.unregisterAllItems();
rowForegroundColorCustom.unregisterAllItems();
rowSelectionGradient.unregisterAllItems();
rowFont.unregisterAllItems();
}//unregisterItems()//
/**
* Gets an iterator over the objects that the RowObject instances are indexed by.
* @return An iterator over the row objects that the RowObject instances describe.
*/
protected IIterator getRowObjectValues() {
return rowObjectByValueMap.keyIterator();
}//getRowObjectValues()//
/**
* Gets an iterator over all the row object metadata.
* @return An iterator over the RowObject instances.
*/
protected IIterator getRowObjects() {
return rowObjectByValueMap.valueIterator();
}//getRowObjects()//
/**
* Synchronizes the selection from the view to the model.
* @param selectedRows The selected row objects.
*/
protected void synchronizeSelection(TableRowObject[] selectedRows) {
if(getAllowMultiSelection()) {
ICollection modelSelections = getModelSelections(); //Note: This is the model's collection of selections - changes made to this collection are being applied to the model.//
//Prevent the selection additions from causing a feedback loop.//
suspendSelectionHooks = true;
try {
//We require that the collection for the selections be created by the model.//
if(modelSelections != null) {
if(selectedRows != null) {
LiteHashSet selectedRowSet;
IIterator iterator = modelSelections.iterator();
LiteList removed = new LiteList(modelSelections.getSize());
selectedRowSet = new LiteHashSet(selectedRows.length, LiteHashSet.DEFAULT_LOAD_FACTOR, Comparator.getIdentityComparator(), LiteHashSet.STYLE_ADD_DUPLICATES);
for(int index = 0; index < selectedRows.length; index++) {
selectedRowSet.add(selectedRows[index].value);
}//for//
//Iterate over the model's selections, removing those that are not currently selected and tracking those not yet in the model selection collection.//
while(iterator.hasNext()) {
Object nextValue = iterator.next();
TableRowObject nextRowObject = nextValue == null ? null : getRowObject(nextValue);
if(nextRowObject != null) {
//Check to see if the model selection is in the view.//
if(!selectedRowSet.remove(nextRowObject.value)) {
//Remove the selection from the model if it is not currently selected in the view.//
removed.add(nextValue);
}//if//
}//if//
else {
//Remove the model selection since it is invalid.//
removed.add(nextValue);
}//else//
}//while//
//Add any selections not already in the model selection collection.//
modelSelections.replaceAll(removed, selectedRowSet);
}//if//
else {
modelSelections.removeAll();
}//else//
}//if//
}//try//
finally {
suspendSelectionHooks = false;
}//finally//
}//if//
}//synchronizeSelection()//
/**
* Synchronizes the selection from the view to the model.
* @param selectedRow The selected row object.
*/
protected void synchronizeSelection(TableRowObject selectedRow) {
setModelSelection(selectedRow == null ? null : selectedRow.value);
}//synchronizeSelection()//
/**
* Synchronizes the selection(s) with the server if the selection(s) have changed.
* <p>The message to the server will be delayed so that rapid changes result in only one server message. Multi-select collections will send all selections instead of optimizing and only sending changes.</p>
*/
protected void synchronizeSelection() {
TableRowObject selectedRow = getAllowMultiSelection() ? null : controlGetSelection();
TableRowObject[] selectedRows = getAllowMultiSelection() ? controlGetSelections() : null;
updateSelectionLinks();
//TODO: Is there any point in trying to optimize things by only sending changes in a multi-select scenario? The problem is the message ordering on the server is unknown.//
if(selectedRows != null) {
if(selectedRows.length == 0) {
selectedRows = null;
}//if//
}//if//
if(getAutoSynchronizeSelection()) {
if(getAllowMultiSelection() || (currentlySelectedRow != selectedRow)) {
currentlySelectedRow = selectedRow;
if(getAutoSynchronizeSelectionDelay() > 0) {
//Start a task to send the selections to the server after a short delay.//
synchronized(this) {
final TableRowObject taskSelectedRow = selectedRow;
final TableRowObject[] taskSelectedRows = selectedRows;
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
}//if//
autoSynchronizeSelectionTask = new Task() {
public void execute() {
//Make sure that this task is still valid and is not being superceeded.//
synchronized(TableComponent.this) {
if(autoSynchronizeSelectionTask == this) {
//Cleanup after the task.//
autoSynchronizeSelectionTask = null;
getEventLoop().executeAsync(new IRunnable() {
public Object run() {
if(getAllowMultiSelection()) {
synchronizeSelection(taskSelectedRows);
}//if//
else {
synchronizeSelection(taskSelectedRow);
}//else//
if(getAutoValidate()) {
postSynchronizeValidate();
}//if//
return null;
}//run()//
});
}//if//
}//synchronized//
}//run()//
};
addTask(autoSynchronizeSelectionTask, getAutoSynchronizeSelectionDelay());
}//synchronized//
}//if//
else {
if(getAllowMultiSelection()) {
synchronizeSelection(selectedRows);
}//if//
else {
synchronizeSelection(selectedRow);
}//else//
if(getAutoValidate()) {
postSynchronizeValidate();
}//if//
}//else//
}//if//
}//if//
}//internalSynchronizeSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#updateHiddenData(java.lang.Object, int, java.lang.Object)
*/
protected void updateHiddenData(Object item, int hiddenDataIndex, Object value) {
if(getAllowMultiSelection()) {
boolean updateSelectionLinks = false;
TableRowObject[] selectedRowObjects = controlGetSelections();
if((selectedRowObjects != null) && (selectedRowObjects.length > 0)) {
//Determine whether any of the selections match with the hidden data's item to see whether we need to update any hidden data linkages.//
for(int selectionIndex = 0; (!updateSelectionLinks) && (selectionIndex < selectedRowObjects.length); selectionIndex++) {
updateSelectionLinks = selectedRowObjects[selectionIndex].value == item;
}//for//
}//if//
if(updateSelectionLinks) {
updateSelectionLinks(selectedRowObjects, getHiddenData(hiddenDataIndex));
}//if//
}//if//
else {
TableRowObject selectedRowObject = controlGetSelection();
if((selectedRowObject != null) && (selectedRowObject.value == item)) {
getHiddenData(hiddenDataIndex).invokeLinkage(selectedRowObject != null ? selectedRowObject.value : null);
}//if//
}//else//
}//updateHiddenData()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#updateSelectionLinks()
*/
protected void updateSelectionLinks() {
super.updateSelectionLinks();
if(getHiddenDataCount() > 0) {
if(getAllowMultiSelection()) {
TableRowObject[] selectedRowObjects = controlGetSelections();
for(int hiddenDataIndex = 0; hiddenDataIndex < getHiddenDataCount(); hiddenDataIndex++) {
updateSelectionLinks(selectedRowObjects, getHiddenData(hiddenDataIndex));
}//for//
}//if//
else {
TableRowObject selectedRowObject = controlGetSelection();
for(int hiddenDataIndex = 0; hiddenDataIndex < getHiddenDataCount(); hiddenDataIndex++) {
getHiddenData(hiddenDataIndex).invokeLinkage(selectedRowObject != null ? selectedRowObject.value : null);
}//for//
}//else//
}//if//
}//updateSelectionLinks()//
/**
* Updates selection linkages associated with the hidden data 'column'.
* @param selectedRowObjects The set of selected row objects.
* @param hiddenData The hidden data whose linkages will be updated.
*/
protected void updateSelectionLinks(TableRowObject[] selectedRowObjects, HiddenData hiddenData) {
Object[] values = null;
if((selectedRowObjects != null) && (selectedRowObjects.length > 0)) {
values = new Object[selectedRowObjects.length];
for(int index = 0; index < values.length; index++) {
values[index] = selectedRowObjects[index].value;
}//for//
}//if//
hiddenData.invokeLinkage(values);
}//updateSelectionLinks()//
/**
* Sets the component's default background color.
* @param backgroundColor The default background color.
*/
public void setRowBackgroundColor(JefColor backgroundColor) {
verifyThread();
this.rowBackgroundColor.setDefaultValue(backgroundColor);
}//setRowHeaderBackgroundColor()//
/**
* Sets the component's default background color.
* @param backgroundColor The default background color.
*/
public void setRowBackgroundColor(ResourceReference backgroundColor) {
verifyThread();
this.rowBackgroundColor.setDefaultValue(backgroundColor);
}//setRowHeaderBackgroundColor()//
/**
* Sets the component's default foreground color.
* @param foregroundColor The default foreground color.
*/
public void setRowForegroundColor(JefColor foregroundColor) {
verifyThread();
this.rowForegroundColor.setDefaultValue(foregroundColor);
}//setRowHeaderForegroundColor()//
/**
* Sets the component's default foreground color.
* @param foregroundColor The default foreground color.
*/
public void setRowForegroundColor(ResourceReference foregroundColor) {
verifyThread();
this.rowForegroundColor.setDefaultValue(foregroundColor);
}//setRowHeaderForegroundColor()//
/**
* Sets the component's default background alternate color.
* @param backgroundColorAlt The default background alternate color.
*/
public void setRowBackgroundColorAlt(JefColor backgroundColorAlt) {
verifyThread();
this.rowBackgroundColorAlt.setDefaultValue(backgroundColorAlt);
}//setRowHeaderBackgroundColorAlt()//
/**
* Sets the component's default background alternate color.
* @param backgroundColorAlt The default background alternate color.
*/
public void setRowBackgroundColorAlt(ResourceReference backgroundColorAlt) {
verifyThread();
this.rowBackgroundColorAlt.setDefaultValue(backgroundColorAlt);
}//setRowHeaderBackgroundColorAlt()//
/**
* Sets the component's default foreground alternate color.
* @param foregroundColorAlt The default foreground alternate color.
*/
public void setRowForegroundColorAlt(JefColor foregroundColorAlt) {
verifyThread();
this.rowForegroundColorAlt.setDefaultValue(foregroundColorAlt);
}//setRowHeaderForegroundColorAlt()//
/**
* Sets the component's default foreground alternate color.
* @param foregroundColorAlt The default foreground alternate color.
*/
public void setRowForegroundColorAlt(ResourceReference foregroundColorAlt) {
verifyThread();
this.rowForegroundColorAlt.setDefaultValue(foregroundColorAlt);
}//setRowHeaderForegroundColorAlt()//
/**
* Sets the component's default selection gradient.
* @param selectionGradient The default selection gradient.
*/
public void setRowSelectionGradient(JefGradient selectionGradient) {
verifyThread();
this.rowSelectionGradient.setDefaultValue(selectionGradient);
}//setRowHeaderSelectionGradient()//
/**
* Sets the component's default selection gradient.
* @param selectionGradient The default selection gradient.
*/
public void setRowSelectionGradient(ResourceReference selectionGradient) {
verifyThread();
this.rowSelectionGradient.setDefaultValue(selectionGradient);
}//setRowSelectionGradient()//
/**
* Sets the font for the row header. This will be the default font if there is a font attribute associated with this component.
* @param font The default font metadata.
*/
public void setRowFont(JefFont[] font) {
verifyThread();
this.rowFont.setDefaultValue(font);
}//setRowHeaderFont()//
/**
* Sets the font for the row header. This will be the default font if there is a font attribute associated with this component.
* @param font The default font metadata.
*/
public void setRowFont(ResourceReference font) {
verifyThread();
this.rowFont.setDefaultValue(font);
}//setRowHeaderFont()//
/**
* Sets the height for the rows.
* @param height The row height in pixels.
*/
public void setRowHeight(Integer height) {
verifyThread();
this.rowHeight.setDefaultValue(height);
}//setRowHeight()//
/**
* Sets the association container used to access the row background color for each row.
* <p>The resulting value will override the row's normal color.</p>
* @param container The row background color association metadata.
*/
public void setRowBackgroundColorCustomAssociation(MultiAssociationContainer container) {
verifyThread();
this.rowBackgroundColorCustom.setAssociations(container);
}//setRowBackgroundColorCustomAssociation()//
/**
* Sets the association container used to access the row foreground color for each row.
* <p>The resulting value will override the row's normal color.</p>
* @param container The row foreground color association metadata.
*/
public void setRowForegroundColorCustomAssociation(MultiAssociationContainer container) {
verifyThread();
this.rowForegroundColorCustom.setAssociations(container);
}//setRowForegroundColorCustomAssociation()//
/**
* Sets the association container used to access the row background color.
* @param container The row background color association metadata.
*/
public void setRowBackgroundColorAssociation(SingleAssociationContainer container) {
verifyThread();
this.rowBackgroundColor.setAssociations(container);
}//setRowBackgroundColorAssociation()//
/**
* Sets the association container used to access the row foreground color.
* @param container The row foreground color association metadata.
*/
public void setRowForegroundColorAssociation(SingleAssociationContainer container) {
verifyThread();
this.rowForegroundColor.setAssociations(container);
}//setRowForegroundColorAssociation()//
/**
* Sets the association container used to access the alternate row background color.
* @param container The alternate row background color association metadata.
*/
public void setRowBackgroundColorAltAssociation(SingleAssociationContainer container) {
verifyThread();
this.rowBackgroundColorAlt.setAssociations(container);
}//setRowBackgroundColorAltAssociation()//
/**
* Sets the association container used to access the alternate row foreground color.
* @param container The alternate row foreground color association metadata.
*/
public void setRowForegroundColorAltAssociation(SingleAssociationContainer container) {
verifyThread();
this.rowForegroundColorAlt.setAssociations(container);
}//setRowForegroundColorAltAssociation()//
/**
* Sets the association container used to access the row selection color.
* @param container The row selection color association metadata.
*/
public void setRowSelectionGradientAssociation(AssociationContainer container) {
verifyThread();
this.rowSelectionGradient.setAssociations(container);
}//setRowSelectionGradientAssociation()//
/**
* Sets the association container used to access the row font.
* @param container The row font association metadata.
*/
public void setRowFontAssociation(MultiAssociationContainer container) {
verifyThread();
this.rowFont.setAssociations(container);
}//setRowFontAssociation()//
/**
* Sets the association container used to access the row height.
* @param container The row font association metadata.
*/
public void setRowHeightAssociation(SingleAssociationContainer container) {
verifyThread();
this.rowHeight.setAssociations(container);
}//setRowHeightAssociation()//
/**
* Determines whether the control is capable of processing collection item decorations.
* @return Whether the control can handle collection item decorations.
*/
protected boolean canDecorate() {
return true;
}//canDecorate()//
/* (non-Javadoc)
* @see com.foundation.controller.IDecorationMultiListener#isListening(java.lang.Class, java.lang.Object, com.foundation.metadata.Attribute)
*/
public boolean isListening(Class decorationType, Object object, Attribute attribute) {
return super.isListening(decorationType, object, attribute) && (HighlightDecoration.class.isAssignableFrom(decorationType) || ImageDecoration.class.isAssignableFrom(decorationType));
}//isListening()//
/* (non-Javadoc)
* @see com.foundation.controller.IDecorationMultiListener#addDecoration(com.foundation.view.AbstractDecoration, java.lang.Object, com.foundation.metadata.Attribute)
*/
public void addDecoration(AbstractDecoration decoration, Object object, Attribute attribute) {
if(decoration instanceof HighlightDecoration) {
TableRowObject rowObject = getRowObject(object);
//Attach the decoration metadata to the row data so we don't overwrite the changes when the row data changes.//
rowObject.highlightDecoration = (HighlightDecoration) decoration;
//If there is a decoration background color then use it.//
if(rowObject.highlightDecoration.getBackgroundColor() != null) {
if(rowObject.rowBackgroundColorCustomHolder == null) {
rowObject.rowBackgroundColorCustomHolder = new ResourceHolder(rowObject);
}//if//
rowObject.rowBackgroundColorCustomHolder.setValue(rowObject.highlightDecoration.getBackgroundColor());
}//if//
//If there is a decoration foreground color then use it.//
if(rowObject.highlightDecoration.getForegroundColor() != null) {
if(rowObject.rowForegroundColorCustomHolder == null) {
rowObject.rowForegroundColorCustomHolder = new ResourceHolder(rowObject);
}//if//
rowObject.rowForegroundColorCustomHolder.setValue(rowObject.highlightDecoration.getForegroundColor());
}//if//
//If there is a decoration font then use it.//
if(rowObject.highlightDecoration.getFont() != null) {
if(rowObject.rowFontHolder == null) {
rowObject.rowFontHolder = new ResourceHolder(rowObject);
}//if//
rowObject.rowFontHolder.setValue(rowObject.highlightDecoration.getFont());
}//if//
//If there is a decoration font then use it.//
if(rowObject.highlightDecoration.getSelectionGradient() != null) {
if(rowObject.rowSelectionGradientHolder == null) {
rowObject.rowSelectionGradientHolder = new ResourceHolder(rowObject);
}//if//
rowObject.rowSelectionGradientHolder.setValue(rowObject.highlightDecoration.getSelectionGradient());
}//if//
//TODO: Once we allow row based tool tips we need to place on here to override the row's tooltip.
//TODO: If the object is selected we may need to repaint the control to force the re-rendering of the selection.
}//if//
else if(decoration instanceof ImageDecoration) { //TODO: Support ControlDecoration also or instead?
DecorationData decorationData = (DecorationData) decorationDataMap.get(decoration);
TableRowObject rowObject = getRowObject(object);
if(decorationData == null) {
decorationData = new DecorationData((ImageDecoration) decoration);
decorationDataMap.put(decoration, decorationData);
}//if//
else {
decorationData.incrementReferenceCount();
}//else//
if(rowObject.decorations == null) {
//TODO: Add a sorting algorithm?
rowObject.decorations = new LiteList(4, 10);
}//if//
rowObject.decorations.add(decorationData);
}//else if//
}//addDecoration()//
/* (non-Javadoc)
* @see com.foundation.controller.IDecorationMultiListener#removeDecoration(com.foundation.view.AbstractDecoration, java.lang.Object, com.foundation.metadata.Attribute)
*/
public void removeDecoration(AbstractDecoration decoration, Object object, Attribute attribute) {
if(decoration instanceof HighlightDecoration) {
TableRowObject rowObject = getRowObject(object);
//If there is a decoration background color then replace it.//
if(rowObject.highlightDecoration.getBackgroundColor() != null) {
Object value = rowBackgroundColorCustom.getValue(rowObject.getValue());
//Set the value even if null so that the row updates.//
rowObject.rowBackgroundColorCustomHolder.setValue(value);
//Release the holder if not being used.//
if(value == null) {
rowObject.rowBackgroundColorCustomHolder.release();
rowObject.rowBackgroundColorCustomHolder = null;
}//if//
}//if//
//If there is a decoration foreground color then replace it.//
if(rowObject.highlightDecoration.getForegroundColor() != null) {
Object value = rowForegroundColorCustom.getValue(rowObject.getValue());
//Set the value even if null so that the row updates.//
rowObject.rowForegroundColorCustomHolder.setValue(value);
//Release the holder if not being used.//
if(value == null) {
rowObject.rowForegroundColorCustomHolder.release();
rowObject.rowForegroundColorCustomHolder = null;
}//if//
}//if//
//If there is a decoration foreground color then replace it.//
if(rowObject.highlightDecoration.getSelectionGradient() != null) {
Object value = rowSelectionGradient.getValue(rowObject.getValue());
//Set the value even if null so that the row updates.//
rowObject.rowSelectionGradientHolder.setValue(value);
//Release the holder if not being used.//
if(value == null) {
rowObject.rowSelectionGradientHolder.release();
rowObject.rowSelectionGradientHolder = null;
}//if//
}//if//
//If there is a decoration font then replace it.//
if(rowObject.highlightDecoration.getFont() != null) {
Object value = rowFont.getValue(rowObject.getValue());
//Set the value even if null so that the row updates.//
rowObject.rowFontHolder.setValue(value);
//Release the holder if not being used.//
if(value == null) {
rowObject.rowFontHolder.release();
rowObject.rowFontHolder = null;
}//if//
}//if//
//Detach the decoration metadata from the row data.//
rowObject.highlightDecoration = null;
//TODO: If the object is selected we may need to repaint the control to force the re-rendering of the selection.
}//if//
else if(decoration instanceof ImageDecoration) {
DecorationData decorationData = (DecorationData) decorationDataMap.get(decoration);
TableRowObject rowObject = getRowObject(object);
if(decorationData.decrementReferenceCount() == 0) {
decorationDataMap.remove(decoration);
decorationData.dispose();
}//if//
rowObject.decorations.remove(decorationData);
if(rowObject.decorations.getSize() == 0) {
rowObject.decorations = null;
}//if//
}//else if//
}//removeDecoration()//
/**
* Adds a column to the right of existing columns.
* @param columnData The metadata for the column. This should be associated with the table column.
*/
protected abstract void controlAddColumn(AbstractColumn columnData);
/**
* Adds a column at the index in the set of existing columns.
* @param columnData The metadata for the column. This should be associated with the table column.
* @param columnIndex The index of the affected column.
*/
protected abstract void controlAddColumn(AbstractColumn columnData, int columnIndex);
/**
* Removes the specified column.
* @param columnIndex The index of the affected column.
*/
protected abstract void controlRemoveColumn(int columnIndex);
/**
* Asks the control to reorder the rows based on the given mapping.
* @param mapping The mapping array of old indices indexed by the new row index.
*/
protected abstract void controlOrderRows(int[] mapping);
/**
* Adds the control dependant row.
* @param rowObject The row object to associate with the row.
* @param index The index at which this row should be displayed in the collection of rows. This will be -1 if not provided.
* @return The table item object representing the affected row. The type control dependant.
*/
protected abstract Object controlAddRow(TableRowObject rowObject, int index);
/**
* Removes a row from the control.
* @param itemData The table item object representing the affected row. The type control dependant.
*/
protected abstract void controlRemoveRow(Object itemData);
/**
* Removes all displayed items from the control.
*/
protected abstract void controlRemoveAll();
/**
* Gets the row objects for the rows selected within the control.
* @return The collection of row objects for the currently selected rows, or null if empty.
*/
protected abstract TableRowObject[] controlGetSelections();
/**
* Gets the row object for the row selected within the control.
* @return The selected row object, or null if there isn't a selection.
*/
protected abstract TableRowObject controlGetSelection();
/**
* Sets the selected values in the control.
* @param itemData The table item objects representing the selected rows. The list contents are control dependant (ie TableItem).
*/
protected abstract void controlSetSelections(IList itemData);
/**
* Sets the selected value in the control.
* @param itemData The table item object representing the selected row. The type is control dependant (ie TableItem).
*/
protected abstract void controlSetSelection(Object itemData);
/**
* Adds a selected value in the control.
* @param itemData The table item object representing the selected row. The type is control dependant (ie TableItem).
*/
protected abstract void controlAddSelection(Object itemData);
/**
* Deselects a value in the control.
* @param itemData The table item object representing the selected row. The type is control dependant (ie TableItem).
*/
protected abstract void controlRemoveSelection(Object itemData);
/**
* Deselects all rows in the control.
*/
protected abstract void controlRemoveAllSelections();
/**
* Checks to see if a value is selected.
* @param itemData The table item object representing the possibly selected row. The type is control dependant (ie TableItem).
* @return Whether the row is currently selected.
*/
protected abstract boolean controlIsSelected(Object itemData);
/**
* Forces the selection event handler to be called.
*/
protected abstract void forceSelectionEvent(); //Should call widgetSelected implemented by the subclass. This name may need to change.//
}//TableComponent//