/* * 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. Will be null if not being used by the control. */ protected ResourceHolder rowBackgroundColorHolder = null; /** A holder for the value of the row foreground color. Will be null if not being used by the control. */ 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. Will be null if not being used by the control. */ 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. Will be null if not being used by the control. */ 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. *

An item can be registered more than once, but must be unregistered just as many times.

* @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. *

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.

* @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. *

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.

*/ 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. *

The resulting value will override the row's normal color.

* @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. *

The resulting value will override the row's normal color.

* @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//