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

719 lines
28 KiB
Java

/*
* Copyright (c) 2002,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 com.common.util.*;
import com.common.util.optimized.*;
/**
* Used as a base class for collection components that are indexed.
* Components such as a list of strings may be indexed such that objects from which the strings are derived cannot be attached to the row since there isn't the concept of a row.
* This class tracks the mapping between the row value and the value's index in the collection to allow selections and updates to be converted to and from values and indices.
*/
public abstract class IndexedCollectionComponent extends CollectionComponent {
/** A mapping of collection values by the control assigned indexes. */
private IIndexedCollection valueByIndexMap = new LiteList(100);
/** A mapping of control assigned indices by the collection values. Since the item can be in the collection more than once we will either store an Integer or an IntArray. */
private LiteHashMap indexByValueMap = new LiteHashMap(100, com.common.comparison.Comparator.getLogicalComparator(), null);
/**
* IndexedCollectionComponent constructor.
* @param parent The parent container.
* @param name The name of the component.
* @param style The style for the control.
*/
public IndexedCollectionComponent(Container parent, String name, int style) {
super(parent, name, style);
}//IndexedCollectionComponent()//
/**
* Gets the control specific data for a collection item.
* @param item The item data which will eventually make it to the visual control.
* @return The data for the item. This can be an array of values if necessary.
*/
protected abstract Object getItemData(Object item);
/* (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;
int[] selectedIndices = controlGetSelections();
Object[] selectedValues = new Object[selectedIndices.length];
if((selectedIndices != null) && (selectedIndices.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 < selectedIndices.length); selectionIndex++) {
Object selectionValue = valueByIndexMap.get(selectedIndices[selectionIndex]);
updateSelectionLinks = selectionValue == item;
selectedValues[selectionIndex] = selectionValue;
}//for//
}//if//
if(updateSelectionLinks) {
getHiddenData(hiddenDataIndex).invokeLinkage(selectedValues);
}//if//
}//if//
else {
int selectedIndex = controlGetSelection();
if(selectedIndex != -1) {
Object selectedValue = valueByIndexMap.get(selectedIndex);
if(selectedValue == item) {
getHiddenData(hiddenDataIndex).invokeLinkage(selectedValue);
}//if//
}//if//
}//else//
}//updateHiddenData()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#updateSelectionLinks()
*/
protected void updateSelectionLinks() {
super.updateSelectionLinks();
if(getHiddenDataCount() > 0) {
if(getAllowMultiSelection()) {
int[] selectedIndices = controlGetSelections();
Object[] selectedValues = selectedIndices != null && selectedIndices.length > 0 ? new Object[selectedIndices.length] : null;
if(selectedValues != null) {
//Collect the selected values.//
for(int selectionIndex = 0; selectionIndex < selectedIndices.length; selectionIndex++) {
selectedValues[selectionIndex] = valueByIndexMap.get(selectedIndices[selectionIndex]);
}//for//
}//if//
//Update the hidden data linkages.//
for(int hiddenDataIndex = 0; hiddenDataIndex < getHiddenDataCount(); hiddenDataIndex++) {
getHiddenData(hiddenDataIndex).invokeLinkage(selectedValues);
}//for//
}//if//
else {
int selectedIndex = controlGetSelection();
Object selectedValue = selectedIndex != -1 ? valueByIndexMap.get(selectedIndex) : null;
//Update the hidden data linkages.//
for(int hiddenDataIndex = 0; hiddenDataIndex < getHiddenDataCount(); hiddenDataIndex++) {
getHiddenData(hiddenDataIndex).invokeLinkage(selectedValue);
}//for//
}//else//
}//if//
}//updateSelectionLinks()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#internalViewRefreshCollection(com.common.util.ICollection, com.common.util.ICollection)
*/
protected void internalViewRefreshCollection(ICollection newCollection, ICollection oldCollection) {
//TODO: Make this simpler - this is not at all as easy as the tcv code & is less useful.//
if((newCollection != null) && (newCollection.getSize() > 0)) {
Object[] items = new Object[newCollection.getSize()];
IIterator iterator = newCollection.iterator();
int removedCount = 0;
//Remove all index mappings so we reflect the latest collection ordering (in case the user wants the order to reflect a new collection order).//
valueByIndexMap.removeAll();
indexByValueMap.removeAll();
//Get the array of strings representing the list contents.//
while(iterator.hasNext()) {
Object value = iterator.next();
//Prevent two objects that are exactly the same from being added to the collection control.//
if(indexByValueMap.containsKey(value)) {
//Do nothing.//
removedCount++;
}//if//
else {
int valueIndex = addValueToMappings(value);
//Add the value to the item array.//
items[valueIndex] = getItemData(value);
}//else//
}//while//
//Truncate the array so we don't have nulls at the end.//
if(removedCount > 0) {
Object[] newItems = new Object[items.length - removedCount];
System.arraycopy(items, 0, newItems, 0, newItems.length);
items = newItems;
}//if//
//Set the collection contents.//
controlSetItems(items);
}//if//
else {
//Remove all existing items.//
controlRemoveAll();
}//else//
}//internalViewRefreshCollection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#internalViewRefreshSelection(java.lang.Object)
*/
protected void internalViewRefreshSelection(Object selectedItem) {
//TODO: Make this simpler - this is not at all as easy as the tcv code & is less useful.//
int selectionIndex = controlGetSelection();
int modelSelectionIndex = -1;
Object controlSelection = selectionIndex != -1 ? valueByIndexMap.get(selectionIndex) : null;
Object indexData = selectedItem != null ? indexByValueMap.get(selectedItem) : null;
if(indexData == null) {
modelSelectionIndex = -1;
}//if//
else if(indexData instanceof Integer) {
modelSelectionIndex = ((Integer) indexData).intValue();
}//else if//
else {
//Select the first one if the selection is not one of the possible ones.//
if(!((IntArray) indexData).containsValue(modelSelectionIndex)) {
modelSelectionIndex = ((IntArray) indexData).get(0); //Use the first occurance of the object.//
}//if//
}//else//
if((getAllowUserItems()) && (selectedItem != null) && (indexData == null)) {
//Set a custom selection for the control (currently only supported for string values).//
controlSetCustomItem(selectedItem);
selectionIndex = -1;
}//if//
else if(controlSelection != selectedItem) {
//Set the control selection.//
controlSetSelection(modelSelectionIndex);
}//else if//
}//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) {
//TODO: Make this simpler - this is not at all as easy as the tcv code & is less useful.//
if(newSelections != null) {
int[] controlSelections = controlGetSelections();
boolean[] markedSelections = new boolean[controlSelections.length];
IIterator selectionIterator = newSelections.iterator();
for(int index = 0; index < markedSelections.length; index++) {
markedSelections[index] = false;
}//for//
//Apply differences between the selection collection and the control selection. Also remove all impossible selections.//
while(selectionIterator.hasNext()) {
Object modelSelection = selectionIterator.next();
Object indexData = indexByValueMap.get(modelSelection);
if(indexData == null) {
//An invalid selection because the selection is not in the collection of displayed values.//
selectionIterator.remove();
}//if//
else if(indexData instanceof Integer) {
int selectionIndex = ((Integer) indexData).intValue();
for(int index = 0; index < controlSelections.length; index++) {
if(controlSelections[index] == selectionIndex) {
if(!markedSelections[index]) {
//The selection is already in the control.//
markedSelections[index] = true;
selectionIndex = -1;
break;
}//if//
else {
//Cannot have two of the same value selected if the value is only in the data collection once.//
selectionIterator.remove();
selectionIndex = -1;
}//else//
}//if//
}//for//
//If we did not find the selected object in the array of currently selected indexes, then add it now.//
if(selectionIndex != -1) {
controlAddSelection(selectionIndex);
}//if//
}//else if//
else {
IntArray indices = (IntArray) indexData;
boolean wasFound = false;
//This is a complex bit of code that must as best as possible identify whether the selection is already represented in the control.//
for(int index = 0; index < controlSelections.length; index++) {
//If the control selection is one of the indexes assigned to the selected object then check to see if we have already identified it as used.//
if(indices.containsValue(controlSelections[index])) {
if(!markedSelections[index]) {
//The selection is already in the control and has not already been marked.//
markedSelections[index] = true;
wasFound = true;
break;
}//if//
}//if//
}//for//
//If we did not find the selected object in the array of currently selected indexes, then add it now.//
if(!wasFound) {
IIntIterator indicesIterator = indices.iterator();
boolean wasAdded = false;
//Since we don't know exactly which one to add, we will have to search for one that is not selected.//
//Note: We could seemingly do this faster by querying the control, but that would require a round trip query to the control which may be very expensive.//
while((!wasAdded) && (indicesIterator.hasNext())) {
int nextIndex = indicesIterator.next();
//Search the control selections for the next possible selection index.//
for(int index = 0; index < controlSelections.length; index++) {
if(nextIndex == controlSelections[index]) {
nextIndex = -1;
break;
}//if//
}//for//
//If the next possible selection index was not in the control's selection collection then we can add it.//
if(nextIndex != -1) {
controlAddSelection(nextIndex);
wasAdded = true;
}//if//
}//while//
if(!wasAdded) {
//Cannot have more references to a value in the selection collection than are in the data collection.//
selectionIterator.remove();
}//if//
}//if//
}//else//
}//while//
//Remove all control selections that have not been marked. These selections were not represented in the model collection of selections.//
for(int index = 0; index < markedSelections.length; index++) {
if(!markedSelections[index]) {
controlRemoveSelection(controlSelections[index]);
}//if//
}//for//
}//if//
else {
//Remove all selections.//
controlSetSelection(-1);
}//else//
}//internalViewRefreshSelections()//
/**
* Synchronizes the selection to the model from the view.
* <p>This method has no logic to examine the auto synchronization state. It simply synchronizes the selection immediatly.</p>
*/
protected void synchronizeSelection() {
if(getAllowMultiSelection()) {
int[] controlSelectionIndices = controlGetSelections();
ICollection modelSelections = getModelSelections();
//Prevent the selection additions from causing a feedback loop.//
suspendSelectionHooks = true;
try {
if(modelSelections != null) {
Object[] controlSelectionObjects = new Object[controlSelectionIndices.length];
boolean[] markedControlSelections = new boolean[controlSelectionObjects.length];
IIterator modelSelectionIterator = modelSelections.iterator();
LiteList removed = new LiteList(modelSelections.getSize());
LiteList added = new LiteList(controlSelectionIndices.length);
for(int index = 0; index < controlSelectionIndices.length; index++) {
controlSelectionObjects[index] = valueByIndexMap.get(controlSelectionIndices[index]);
markedControlSelections[index] = false;
}//for//
//Add selected items to the selection collection.//
while(modelSelectionIterator.hasNext()) {
Object modelSelection = modelSelectionIterator.next();
boolean found = false;
for(int index = 0; (!found) && (index < markedControlSelections.length); index++) {
if(!markedControlSelections[index]) {
if(controlSelectionObjects[index] == modelSelection) {
markedControlSelections[index] = true;
found = true;
}//if//
}//if//
}//for//
if(!found) {
removed.add(modelSelection);
}//if//
}//while//
for(int index = 0; index < markedControlSelections.length; index++) {
if(!markedControlSelections[index]) {
added.add(controlSelectionObjects[index]);
}//if//
}//for//
modelSelections.replaceAll(removed, added);
}//if//
}//try//
finally {
suspendSelectionHooks = false;
}//finally//
}//if//
else {
int selectionIndex = controlGetSelection();
Object controlSelection = selectionIndex != -1 ? valueByIndexMap.get(selectionIndex) : null;
if((getAllowUserItems()) && (selectionIndex == -1) && (controlGetText().length() > 0)) {
setModelSelection(controlGetText());
}//if//
else {
setModelSelection(controlSelection);
}//else if//
}//else//
}//internalViewSynchronizeSelection()//
/**
* Gets the index (or indices) for the given item.
* @param item The item whose index is required.
* @return The index data for the item which will either be an Integer, an IntArray, or null if the item is not mapped.
*/
protected Object getItemIndexData(Object item) {
return (item != null) && (indexByValueMap.containsKey(item)) ? indexByValueMap.get(item) : null;
}//getItemIndexData()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#itemAdded(java.lang.Object, int)
*/
protected void itemAdded(Object item, int index) {
//Setup a mapping and a new index for the value.//
index = addValueToMappings(item);
//Add the value to the control.//
controlAddItem(getItemData(item), index);
//TODO: Should this be allowed? If the user sets the selection to an object not in the collection, should we prevent it? What about controls like a combobox which allow custom input?//
if((!getAllowMultiSelection()) && (getModelSelection() == item)) {
controlSetSelection(index);
}//if//
}//itemAdded()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#itemRemoved(java.lang.Object, int)
*/
protected void itemRemoved(Object item, int index) {
if(indexByValueMap.containsKey(item)) {
Object indexData = indexByValueMap.get(item);
int modelIndex;
//Determine whether the removed object occurs more than once in the collection.//
if(indexData instanceof Integer) {
modelIndex = ((Integer) indexData).intValue();
//Remove the item from the control and unregister all event handlers.//
controlRemoveItem(modelIndex);
}//if//
else {
IntArray indices = (IntArray) indexData;
//TODO: We could make things look better by removing the selected object when there are more than one possible objects to be removed.//
//Assume that we should remove the last occurance of the object.//
modelIndex = indices.get(indices.getSize() - 1);
//Remove the item from the control.//
controlRemoveItem(modelIndex);
}//else//
//Remove the object from the mappings.//
removeValueFromMappings(item, modelIndex);
}//if//
}//itemRemoved()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#itemAllRemoved()
*/
protected void itemAllRemoved() {
//Remove all index mappings so we reflect the latest collection ordering (in case the user wants the order to reflect a new collection order).//
valueByIndexMap.removeAll();
indexByValueMap.removeAll();
//Remove all existing items.//
controlRemoveAll();
}//itemAllRemoved()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#registerItem(java.lang.Object)
*/
protected void registerItem(Object item) {
internalItemAdded(item);
}//registerItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#unregisterItem(java.lang.Object)
*/
protected void unregisterItem(Object item) {
internalItemRemoved(item);
}//unregisterItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#unregisterItems()
*/
protected void unregisterItems() {
internalItemsRemoved();
}//unregisterItems()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#itemSorted(int[])
*/
protected void itemSorted(int[] mapping) {
//TODO: Re-order the indicies in the control and rebuild the mappings.//
}//itemSorted()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#selectionAdded(java.lang.Object)
*/
protected void selectionAdded(Object value) {
checkObjectSelectionCount(value);
}//selectionAdded()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#selectionRemoved(java.lang.Object)
*/
protected void selectionRemoved(Object value) {
checkObjectSelectionCount(value);
}//selectionRemoved()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#selectionAllRemoved()
*/
protected void selectionAllRemoved() {
controlRemoveAllSelections();
}//selectionAllRemoved()//
/**
* Verifies that the correct number of selections for the given value exist in the control.
* @param value The value that is being checked. It may be checked because a selection was added, or removed.
*/
protected void checkObjectSelectionCount(Object value) {
if(!getAllowMultiSelection()) {
throw new RuntimeException("Cannot call this method: 'checkObjectSelectionCount' if multiple selections are not allowed.");
}//if//
if(indexByValueMap.containsKey(value)) {
int[] controlSelectionIndices = controlGetSelections();
Object indexData = indexByValueMap.get(value);
int possibleCount = indexData == null ? 0 : indexData instanceof Integer ? 1 : ((IntArray) indexData).getSize();
int modelCount = 0;
IIterator iterator = getModelSelections().iterator();
//Count the number of times the object is in the model's selection collection. Remove impossible references.//
while(iterator.hasNext()) {
if(iterator.next() == value) {
modelCount++;
//Fix impossible selections.//
if(modelCount > possibleCount) {
modelCount = possibleCount;
iterator.remove();
}//if//
}//if//
}//while//
//Count the number of times the object is selected in the control's selections. Remove or add selections to match the model's selection collection.//
if(indexData instanceof Integer) {
int valueIndex = ((Integer) indexData).intValue();
int controlCount = 0;
for(int index = 0; index < controlSelectionIndices.length; index++) {
if(controlSelectionIndices[index] == valueIndex) {
controlCount++;
if(controlCount > modelCount) {
controlRemoveSelection(valueIndex);
}//if//
//Stop iterating since there can only be one selection for this object.//
break;
}//if//
}//for//
if(controlCount < modelCount) {
controlAddSelection(valueIndex);
}//if//
}//if//
else {
int controlCount = 0;
IntArray valueIndices = new IntArray((IntArray) indexData); //Copy the object indices so we can remove the ones we already have used.//
for(int index = 0; index < controlSelectionIndices.length; index++) {
Object controlSelectionValue = valueByIndexMap.get(controlSelectionIndices[index]);
if(controlSelectionValue == value) {
controlCount++;
if(controlCount > modelCount) {
//Remove the selection because there are too many.//
controlRemoveSelection(controlSelectionIndices[index]);
}//if//
else {
//Remove used object indexes so it is easy to add more references if they are required.//
valueIndices.remove(valueIndices.getIndexOf(controlSelectionIndices[index]));
}//else//
}//if//
}//for//
//Add selections for the object until the counts match.//
while(controlCount < modelCount) {
controlAddSelection(valueIndices.get(valueIndices.getSize()));
valueIndices.remove(valueIndices.getSize());
controlCount++;
}//while//
}//else//
}//if//
}//checkObjectCount()//
/**
* Removes a value from the mappings of values and internal indexes.
* <p>Note: The current implementation is very fast, except when removing items from a very large collection of values. This performance problem is due to the need to clean the object->index mapping after each removal.</p>
* @param removedValue The value removed from the collection being displayed.
* @param removedIndex The index of the removed value. This is necessary because a value could be in the collection more than one time.
*/
protected void removeValueFromMappings(Object removedValue, int removedIndex) {
if(indexByValueMap.containsKey(removedValue)) {
Object indexData = indexByValueMap.get(removedValue);
IIterator iterator = indexByValueMap.keyIterator();
if(indexData instanceof IntArray) {
IntArray indices = (IntArray) indexData;
//Remove the specified index from the array of indices.//
indices.remove(indices.getIndexOf(removedIndex));
//Optimize things by only using an IntArray when necessary.//
if(indices.getSize() == 1) {
indexByValueMap.put(removedValue, new Integer(indices.get(0)));
}//if//
}//if//
else {
//Since there should be no other occurances of the object in the collection we can remove the mapping altogether.//
indexByValueMap.remove(removedValue);
}//else//
valueByIndexMap.remove(removedIndex);
while(iterator.hasNext()) {
Object next = iterator.next();
indexData = indexByValueMap.get(next);
if(indexData instanceof Integer) {
if(((Integer) indexData).intValue() > removedIndex) {
indexByValueMap.put(next, new Integer(((Integer) indexData).intValue() - 1));
}//if//
}//if//
else {
IntArray indices = (IntArray) indexData;
//TODO: For large collections where items may be regularly removed we may wish to create a special collection that maintains the object to index mappings. We could use the bucket approach to maintaining the index number.//
for(int index = indices.getSize() - 1; (index >= 0) && (indices.get(index) > removedIndex); index--) {
indices.replace(index, indices.get(index) - 1);
}//for//
}//else//
}//while//
}//if//
}//removeValueFromMappings()//
/**
* Adds a value to the mappings of values and internal indexes.
* @param addedValue The value added to the collection being displayed.
* @return The internal index of the added value.
*/
protected int addValueToMappings(Object addedValue) {
int index = valueByIndexMap.getSize();
//Always add the value to the indexed mapping.//
valueByIndexMap.add(addedValue);
//Either add the index to the index by value map, or add it to a collection indexed by the object if the object is in the collection more than once.//
if(!indexByValueMap.containsKey(addedValue)) {
//Add the index to the mappings.//
indexByValueMap.put(addedValue, new Integer(index));
}//if//
else {
Object indexData = indexByValueMap.get(addedValue);
if(indexData instanceof Integer) {
IntArray indices = new IntArray(10, 30);
//Create a collection of indices for the same object.//
indices.add(((Integer) indexData).intValue());
indices.add(index);
indexByValueMap.put(addedValue, indices);
}//if//
else {
//Add the new index to the collection of indices where this same object can be found in the control's list.//
((IntArray) indexData).add(index);
}//else//
}//else//
return index;
}//addValueToMappings()//
/**
* Removes all displayed items from the control.
*/
protected abstract void controlRemoveAll();
/**
* Sets the control's displayed collection values ordered by index.
* @param items The indexed values displayed by the control.
*/
protected abstract void controlSetItems(Object[] items);
/**
* Sets an item in the control's collection display.
* @param index The index at which the item should be set.
* @param itemData The value displayed by the control.
*/
protected abstract void controlSetItem(int index, Object itemData);
/**
* Adds an item to the control's collection display.
* @param itemData The value displayed by the control.
* @param index The index at which the item should be added.
*/
protected abstract void controlAddItem(Object itemData, int index);
/**
* Adds an item to the control's collection at the end.
* @param itemData The value displayed by the control.
*/
protected abstract void controlAddItem(Object itemData);
/**
* Removes an item from the control's collection display.
* @param index The index of the item to be removed.
*/
protected abstract void controlRemoveItem(int index);
/**
* Gets the indices selected within the control.
* @return The collection of indices selected.
*/
protected abstract int[] controlGetSelections();
/**
* Gets the index selected within the control.
* @return The index currently selected.
*/
protected abstract int controlGetSelection();
/**
* Sets the selected values in the control.
* @param indices The indices of the selected values.
*/
protected abstract void controlSetSelections(int[] indices);
/**
* Sets the selected value in the control.
* @param index The index of the selected value.
*/
protected abstract void controlSetSelection(int index);
/**
* Adds a selected value in the control.
* @param index The index of the selected value.
*/
protected abstract void controlAddSelection(int index);
/**
* Deselects a value in the control.
* @param index The index of the selected value.
*/
protected abstract void controlRemoveSelection(int index);
/**
* Deselects all values in the control.
*/
protected abstract void controlRemoveAllSelections();
/**
* Checks to see if a value is selected.
* @param index The index of the checked value.
* @return Whether the value is currently selected.
*/
protected abstract boolean controlIsSelected(int index);
/**
* Gets the current text for the control.
* <p>Some controls such as comboboxes have a text which may not be one of the listed items.</p>
* @return The control's current text.
*/
protected abstract String controlGetText();
/**
* Sets the current custom selection item for the control.
* <p>Some controls such as comboboxes have a text which may not be one of the listed items.</p>
* @param item The controls custom selected item.
*/
protected abstract void controlSetCustomItem(Object item);
/**
* Forces the selection event handler to be called.
*/
protected abstract void forceSelectionEvent(); //TODO: Should call widgetSelected implemented by the subclass. This name may need to change.//
}//IndexedCollectionComponent//