Initial commit from SVN.
This commit is contained in:
@@ -0,0 +1,742 @@
|
||||
/*
|
||||
* Copyright (c) 2003,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.tcv.swt.client;
|
||||
|
||||
import com.common.util.LiteList;
|
||||
import com.foundation.tcv.swt.*;
|
||||
import com.foundation.tcv.view.*;
|
||||
|
||||
public abstract class IndexedCollectionComponent extends CollectionComponent implements IIndexedCollectionComponent {
|
||||
/** The currently selected index (on the server) if allowing only a single selection. A negative one indicates no selection. */
|
||||
private int selectedObjectIdOnServer = -1;
|
||||
/** The custom selection last sent to the server or received by the server. This will be null if there is no custom selection or there is no selection at all. */
|
||||
private String customSelectionOnServer = null;
|
||||
/** Maps the row objects given the index in the control. An object can be represented more than once in the control if the same row object exists in multiple indices. */
|
||||
private LiteList rowObjectByIndexMap = new LiteList(100, 200);
|
||||
|
||||
protected static class IndexedRowObject extends RowObject {
|
||||
public Object value = null;
|
||||
|
||||
public IndexedRowObject(int objectId, int hiddenDataCount) {
|
||||
super(objectId, hiddenDataCount);
|
||||
}//IndexedRowObject()//
|
||||
}//IndexedRowObject//
|
||||
/**
|
||||
* IndexedCollectionComponent constructor.
|
||||
*/
|
||||
public IndexedCollectionComponent() {
|
||||
super();
|
||||
}//IndexedCollectionComponent()//
|
||||
/**
|
||||
* Gets the row object for the given display collection index.
|
||||
* @param index The zero based index of the row object in the display collection.
|
||||
* @return The row object for the display index.
|
||||
*/
|
||||
protected RowObject getRowObjectAtIndex(int index) {
|
||||
return (RowObject) rowObjectByIndexMap.get(index);
|
||||
}//getRowObjectAtIndex()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.view.IViewComponent#viewInitialize()
|
||||
*/
|
||||
protected void internalViewInitialize() {
|
||||
super.internalViewInitialize();
|
||||
}//internalViewInitialize()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.view.IViewComponent#viewRelease()
|
||||
*/
|
||||
protected void internalViewRelease() {
|
||||
super.internalViewRelease();
|
||||
}//internalViewRelease()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.view.IViewComponent#viewSynchronize()
|
||||
*/
|
||||
protected void internalViewSynchronize() {
|
||||
super.internalViewSynchronize();
|
||||
internalViewSynchronizeSelection();
|
||||
}//internalViewSynchronize()//
|
||||
/**
|
||||
* Synchronizes the selection or forces the auto synchronize task to run if one is pending.
|
||||
*/
|
||||
protected void internalViewSynchronizeSelection() {
|
||||
if(!getAutoSynchronizeSelection()) {
|
||||
synchronizeSelection();
|
||||
}//if//
|
||||
else {
|
||||
synchronized(this) {
|
||||
if(autoSynchronizeSelectionTask != null) {
|
||||
removeTask(autoSynchronizeSelectionTask);
|
||||
autoSynchronizeSelectionTask.execute();
|
||||
}//if//
|
||||
}//synchronized//
|
||||
}//else//
|
||||
}//internalViewSynchronizeSelection()//
|
||||
/**
|
||||
* 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[] selectionIndices = controlGetSelections();
|
||||
|
||||
//Convert each selection index into an object id.//
|
||||
for(int index = 0; index < selectionIndices.length; index++) {
|
||||
selectionIndices[index] = getRowObjectAtIndex(selectionIndices[index]).objectId;
|
||||
}//for//
|
||||
|
||||
if(selectionIndices.length == 0) {
|
||||
selectionIndices = null;
|
||||
}//if//
|
||||
|
||||
sendMessage(MESSAGE_VIEW_SYNCHRONIZE_SELECTION, (Object) selectionIndices);
|
||||
}//if//
|
||||
else if(hasCustomSelection()) {
|
||||
String text = controlGetText();
|
||||
|
||||
if(!text.equals(customSelectionOnServer)) {
|
||||
selectedObjectIdOnServer = -1;
|
||||
customSelectionOnServer = text;
|
||||
sendMessage(MESSAGE_VIEW_SYNCHRONIZE_SELECTION, text);
|
||||
}//if//
|
||||
}//else if//
|
||||
else {
|
||||
int selectionIndex = controlGetSelection();
|
||||
|
||||
//Convert from the index to the object identifier.//
|
||||
selectionIndex = selectionIndex != -1 ? getRowObjectAtIndex(selectionIndex).objectId : -1;
|
||||
|
||||
if(selectionIndex != selectedObjectIdOnServer) {
|
||||
selectedObjectIdOnServer = selectionIndex;
|
||||
customSelectionOnServer = null;
|
||||
sendMessage(MESSAGE_VIEW_SYNCHRONIZE_SELECTION, selectionIndex != -1 ? new Integer(selectionIndex) : null);
|
||||
}//if//
|
||||
}//else//
|
||||
}//synchronizeSelection()//
|
||||
/**
|
||||
* Gets the set of selected object identifiers.
|
||||
* @return The set of selected object identifiers, or null if nothing is selected.
|
||||
*/
|
||||
protected int[] getSelectedObjectIds() {
|
||||
int[] selectionIndices = controlGetSelections();
|
||||
|
||||
//Convert each selection index into an object id.//
|
||||
for(int index = 0; index < selectionIndices.length; index++) {
|
||||
selectionIndices[index] = getRowObjectAtIndex(selectionIndices[index]).objectId;
|
||||
}//for//
|
||||
|
||||
if(selectionIndices.length == 0) {
|
||||
selectionIndices = null;
|
||||
}//if//
|
||||
|
||||
return selectionIndices;
|
||||
//sendMessage(MESSAGE_VIEW_SYNCHRONIZE_SELECTION, (Object) selectionIndices);
|
||||
}//getSelectedObjectIds()//
|
||||
/**
|
||||
* Determines whether there is a custom selection.
|
||||
* @return Whether the user has typed a value in the control that is not in the set to select from.
|
||||
*/
|
||||
protected boolean hasCustomSelection() {
|
||||
return getAllowUserItems() && (controlGetSelection() == -1) && (controlGetText() != null) && (controlGetText().length() > 0);
|
||||
}//hasCustomSelection()//
|
||||
/**
|
||||
* Gets the set of selected object identifiers.
|
||||
* @return The set of selected object identifiers, or null if nothing is selected.
|
||||
*/
|
||||
protected int getSelectedObjectId() {
|
||||
int selectionIndex = controlGetSelection();
|
||||
/*
|
||||
if((getAllowUserItems()) && (selectionIndex == -1)) {
|
||||
//TODO: Track whether the text has changed?
|
||||
//sendMessage(MESSAGE_VIEW_SYNCHRONIZE_SELECTION, controlGetText());
|
||||
currentlySelectedObjectId = -2;
|
||||
}//if//
|
||||
else {
|
||||
|
||||
//sendMessage(MESSAGE_VIEW_SYNCHRONIZE_SELECTION, selectionIndex != -1 ? new Integer(selectionIndex) : null);
|
||||
}//else//
|
||||
*/
|
||||
return selectionIndex != -1 ? getRowObjectAtIndex(selectionIndex).objectId : -1;
|
||||
}//getSelectedObjectId()//
|
||||
/**
|
||||
* Gets the currently selected object identifier on the server.
|
||||
* @return The object identifier for the selection known by the server, or -1 for no selection.
|
||||
*/
|
||||
protected int getSelectedObjectIdOnServer() {
|
||||
return selectedObjectIdOnServer;
|
||||
}//getSelectedObjectIdOnServer()//
|
||||
/**
|
||||
* Sets the currently selected object identifier on the server.
|
||||
* @param objectId The object identifier for the selection known by the server, or -1 for no selection.
|
||||
*/
|
||||
protected void setSelectedObjectIdOnServer(int objectId) {
|
||||
this.selectedObjectIdOnServer = objectId;
|
||||
}//setSelectedObjectIdOnServer()//
|
||||
/**
|
||||
* Gets the current custom selection text on the server.
|
||||
* @return The selection text, or null if there isn't a custom selection.
|
||||
*/
|
||||
protected String getCustomSelectionOnServer() {
|
||||
return customSelectionOnServer;
|
||||
}//getCustomSelectionOnServer()//
|
||||
/**
|
||||
* Sets the current custom selection text on the server.
|
||||
* @param customSelection The selection text, or null if there isn't a custom selection.
|
||||
*/
|
||||
protected void setCustomSelectionOnServer(String customSelection) {
|
||||
this.customSelectionOnServer = customSelection;
|
||||
}//setCustomSelectionOnServer()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.tcv.swt.client.CollectionComponent#updateSelectionLinks()
|
||||
*/
|
||||
protected void updateSelectionLinks() {
|
||||
super.updateSelectionLinks();
|
||||
|
||||
if(getHiddenDataCount() > 0) {
|
||||
if(getAllowMultiSelection()) {
|
||||
int[] selectedIndices = controlGetSelections();
|
||||
RowObject[] selectedObjects = selectedIndices != null && selectedIndices.length > 0 ? new RowObject[selectedIndices.length] : null;
|
||||
|
||||
if(selectedObjects != null) {
|
||||
//Collect the selected values.//
|
||||
for(int selectionIndex = 0; selectionIndex < selectedIndices.length; selectionIndex++) {
|
||||
selectedObjects[selectionIndex] = getRowObjectAtIndex(selectedIndices[selectionIndex]);
|
||||
}//for//
|
||||
}//if//
|
||||
|
||||
//Update the hidden data linkages.//
|
||||
for(int hiddenDataIndex = 0; hiddenDataIndex < getHiddenDataCount(); hiddenDataIndex++) {
|
||||
getHiddenData(hiddenDataIndex).invokeLinkage(selectedObjects);
|
||||
}//for//
|
||||
}//if//
|
||||
else {
|
||||
int selectedIndex = controlGetSelection();
|
||||
RowObject selectedObject = selectedIndex != -1 ? getRowObjectAtIndex(selectedIndex) : null;
|
||||
|
||||
//Update the hidden data linkages.//
|
||||
for(int hiddenDataIndex = 0; hiddenDataIndex < getHiddenDataCount(); hiddenDataIndex++) {
|
||||
getHiddenData(hiddenDataIndex).invokeLinkage(selectedObject);
|
||||
}//for//
|
||||
}//else//
|
||||
}//if//
|
||||
}//updateSelectionLinks()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.tcv.swt.client.CollectionComponent#createRowObject(int)
|
||||
*/
|
||||
protected RowObject createRowObject(int objectId) {
|
||||
return new IndexedRowObject(objectId, getHiddenDataCount());
|
||||
}//createRowObject()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.tcv.swt.client.AbstractComponent#internalProcessMessage(com.foundation.tcv.model.ViewMessage)
|
||||
*/
|
||||
public Object internalProcessMessage(ViewMessage viewMessage) {
|
||||
Object retVal = null;
|
||||
|
||||
switch(viewMessage.getMessageNumber()) {
|
||||
// case MESSAGE_SET_ITEMS: { //A string array and an int array. The int array is the object ID's.//
|
||||
// Object[] data = (Object[]) viewMessage.getMessageData();
|
||||
//
|
||||
// if(data == null) {
|
||||
// controlRemoveAll();
|
||||
// removeRowObjects();
|
||||
// rowObjectByIndexMap.removeAll();
|
||||
// forceSelectionEvent();
|
||||
// }//if//
|
||||
// else {
|
||||
// Object[] items = (Object[]) data[0];
|
||||
// int[] objectIds = (int[]) data[1];
|
||||
// Object[] hiddenData = (Object[]) data[2];
|
||||
//
|
||||
// if(((items == null) && (objectIds != null)) || ((items != null) && (objectIds == null)) || ((items != null) && (items.length != objectIds.length))) {
|
||||
// Debug.log("Error: Invalid parameters.");
|
||||
// }//if//
|
||||
//
|
||||
// //Remove all the mappings.//
|
||||
// removeRowObjects();
|
||||
// rowObjectByIndexMap.removeAll();
|
||||
//
|
||||
// if(objectIds != null) {
|
||||
// //Initialize the mappings between indexes and object IDs.//
|
||||
// for(int index = 0; index < objectIds.length; index++) {
|
||||
// IndexedRowObject rowObject = (IndexedRowObject) getRowObject(objectIds[index]);
|
||||
//
|
||||
// //Create a row object or increment its reference count.//
|
||||
// if(rowObject == null) {
|
||||
// rowObject = (IndexedRowObject) createRowObject(objectIds[index]);
|
||||
// rowObject.value = items[index];
|
||||
//
|
||||
// if(rowObject.hiddenData != null && hiddenData != null && hiddenData[index] instanceof Object[]) {
|
||||
// //Copy the hidden data to the row object.//
|
||||
// System.arraycopy(hiddenData[index], 0, rowObject.hiddenData, 0, rowObject.hiddenData.length);
|
||||
// }//if//
|
||||
// }//if//
|
||||
// else {
|
||||
// rowObject.referenceCount++;
|
||||
// items[index] = rowObject.value;
|
||||
// }//else//
|
||||
//
|
||||
// addRowObject(rowObject);
|
||||
// rowObjectByIndexMap.add(rowObject);
|
||||
// }//for//
|
||||
// }//if//
|
||||
//
|
||||
// //Set the items in the control.//
|
||||
// controlSetItems(items);
|
||||
// }//else//
|
||||
// break;
|
||||
// }//case//
|
||||
case MESSAGE_ADD_ITEM: { //Sends item data and object ID and an optional index.//
|
||||
Object itemData = viewMessage.getMessageData();
|
||||
Object[] hiddenData = (Object[]) viewMessage.getMessageSecondaryData();
|
||||
int objectId = viewMessage.getMessageInteger();
|
||||
IndexedRowObject rowObject = (IndexedRowObject) getRowObject(objectId);
|
||||
|
||||
//Create a row object or increment its reference count.//
|
||||
if(rowObject == null) {
|
||||
rowObject = (IndexedRowObject) createRowObject(objectId);
|
||||
rowObject.value = itemData;
|
||||
|
||||
if(hiddenData != null && rowObject.hiddenData != null) {
|
||||
//Copy the hidden data to the row object.//
|
||||
System.arraycopy(hiddenData, 0, rowObject.hiddenData, 0, rowObject.hiddenData.length);
|
||||
}//if//.
|
||||
}//if//
|
||||
else {
|
||||
rowObject.referenceCount++;
|
||||
itemData = rowObject.value;
|
||||
}//else//
|
||||
|
||||
//If an index was provided then place the item at the requested index.//
|
||||
if(viewMessage.getMessageSecondaryInteger() != -1) {
|
||||
int index = viewMessage.getMessageSecondaryInteger();
|
||||
|
||||
//A little error checking just in case.//
|
||||
if(index > rowObjectByIndexMap.getSize()) {
|
||||
index = rowObjectByIndexMap.getSize();
|
||||
}//if//
|
||||
|
||||
//Add the new value to the control.//
|
||||
controlAddItem(itemData, index);
|
||||
//Update the mappings.//
|
||||
rowObjectByIndexMap.add(index, rowObject);
|
||||
}//if//
|
||||
else {
|
||||
//Add the new value to the control.//
|
||||
controlAddItem(itemData);
|
||||
//Update the mappings.//
|
||||
rowObjectByIndexMap.add(rowObject);
|
||||
}//else//
|
||||
|
||||
//Update the mappings.//
|
||||
addRowObject(rowObject);
|
||||
break;
|
||||
}//case//
|
||||
case MESSAGE_REMOVE_ITEM: { //Note: Since removals are most often of selected items we will first try removing selected objects with the same object id.//
|
||||
int objectId = viewMessage.getMessageInteger();
|
||||
|
||||
//Handle multi-selection capable controls differently since single selection controls may not implement the controlGetSelections method.//
|
||||
if(getAllowMultiSelection()) {
|
||||
int[] selectedIndices = controlGetSelections();
|
||||
boolean isRemoved = false;
|
||||
|
||||
//First pass, remove from only selected items. (Most removals are selected.)//
|
||||
for(int index = selectedIndices.length - 1; ((!isRemoved) && (index >= 0)); index--) {
|
||||
if(getRowObjectAtIndex(selectedIndices[index]).objectId == objectId) {
|
||||
IndexedRowObject rowObject;
|
||||
|
||||
//TODO: Is this really necessary?//
|
||||
controlRemoveSelection(selectedIndices[index]);
|
||||
//Remove the item from the collection.//
|
||||
controlRemoveItem(selectedIndices[index]);
|
||||
//Remove the item from the mappings.//
|
||||
rowObject = (IndexedRowObject) rowObjectByIndexMap.remove(selectedIndices[index]);
|
||||
|
||||
//Remove the row object from the object id map if it is no longer referenced.//
|
||||
if(--rowObject.referenceCount == 0) {
|
||||
removeRowObject(rowObject.objectId);
|
||||
}//if//
|
||||
|
||||
isRemoved = true;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//Second pass, remove from all items.//
|
||||
for(int index = rowObjectByIndexMap.getSize() - 1; ((!isRemoved) && (index >= 0)); index--) {
|
||||
if(getRowObjectAtIndex(index).objectId == objectId) {
|
||||
IndexedRowObject rowObject;
|
||||
|
||||
//Remove the item from the collection.//
|
||||
controlRemoveItem(index);
|
||||
//Remove the item from the mappings.//
|
||||
rowObject = (IndexedRowObject) rowObjectByIndexMap.remove(index);
|
||||
|
||||
//Remove the row object from the object id map if it is no longer referenced.//
|
||||
if(--rowObject.referenceCount == 0) {
|
||||
removeRowObject(rowObject.objectId);
|
||||
}//if//
|
||||
|
||||
isRemoved = true;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
if(!isRemoved) {
|
||||
//TODO: Unable to remove the value! Should we notify the server?//
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
int selectedIndex = controlGetSelection();
|
||||
|
||||
if((selectedIndex != -1) && (getRowObjectAtIndex(selectedIndex).objectId == objectId)) {
|
||||
IndexedRowObject rowObject;
|
||||
|
||||
//TODO: Is this really necessary?//
|
||||
controlRemoveSelection(selectedIndex);
|
||||
//Remove the item from the collection.//
|
||||
controlRemoveItem(selectedIndex);
|
||||
//Remove the item from the mappings.//
|
||||
rowObject = (IndexedRowObject) rowObjectByIndexMap.remove(selectedIndex);
|
||||
|
||||
//Remove the row object from the object id map if it is no longer referenced.//
|
||||
if(--rowObject.referenceCount == 0) {
|
||||
removeRowObject(rowObject.objectId);
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
//Second pass, remove from all items.//
|
||||
for(int index = rowObjectByIndexMap.getSize() - 1; index >= 0; index--) {
|
||||
if(getRowObjectAtIndex(index).objectId == objectId) {
|
||||
IndexedRowObject rowObject;
|
||||
|
||||
//Remove the item from the collection.//
|
||||
controlRemoveItem(index);
|
||||
//Remove the item from the mappings.//
|
||||
rowObject = (IndexedRowObject) rowObjectByIndexMap.remove(index);
|
||||
|
||||
//Remove the row object from the object id map if it is no longer referenced.//
|
||||
if(--rowObject.referenceCount == 0) {
|
||||
removeRowObject(rowObject.objectId);
|
||||
}//if//
|
||||
|
||||
break;
|
||||
}//if//
|
||||
}//for//
|
||||
}//else//
|
||||
}//else//
|
||||
break;
|
||||
}//case//
|
||||
case MESSAGE_REMOVE_ALL: {
|
||||
controlRemoveAll();
|
||||
removeRowObjects();
|
||||
rowObjectByIndexMap.removeAll();
|
||||
//This should not be necessary since the server should send a selection event immediatly following the remove all.//
|
||||
//forceSelectionEvent();
|
||||
break;
|
||||
}//case//
|
||||
case MESSAGE_SET_ITEM: {
|
||||
Object[] data = (Object[]) viewMessage.getMessageData();
|
||||
int objectId = ((Integer) data[0]).intValue();
|
||||
Object itemData = data[1];
|
||||
IndexedRowObject rowObject = (IndexedRowObject) getRowObject(objectId);
|
||||
|
||||
//Set the row object's value.//
|
||||
rowObject.value = itemData;
|
||||
|
||||
//Find all instances of the object and apply the new display data.//
|
||||
for(int index = 0; index < rowObjectByIndexMap.getSize(); index++) {
|
||||
if(getRowObjectAtIndex(index) == rowObject) {
|
||||
//TODO: Do we need to do anything to preserve the selection?
|
||||
controlSetItem(index, itemData);
|
||||
}//if//
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case MESSAGE_SET_SELECTION: {
|
||||
Object messageData = viewMessage.getMessageData();
|
||||
|
||||
if(messageData instanceof int[]) {
|
||||
int[] selectionObjectIds = (int[]) messageData;
|
||||
|
||||
//For non-multi-selection collections, set the currently selected id.//
|
||||
if(!getAllowMultiSelection()) {
|
||||
if((selectionObjectIds != null) && (selectionObjectIds.length > 1)) {
|
||||
selectedObjectIdOnServer = -1;
|
||||
//Error: Invalid message value!//
|
||||
throw new RuntimeException("Error: Invalid message parameter! MESSAGE_SET_SELECTION");
|
||||
}//if//
|
||||
else {
|
||||
selectedObjectIdOnServer = ((selectionObjectIds == null) || (selectionObjectIds.length == 0)) ? -1 : selectionObjectIds[0];
|
||||
}//else//
|
||||
|
||||
if(selectedObjectIdOnServer != -1) {
|
||||
boolean found = false;
|
||||
int controlSelection = controlGetSelection();
|
||||
|
||||
if((controlSelection == -1) || (getRowObjectAtIndex(controlSelection).objectId != selectedObjectIdOnServer)) {
|
||||
//Locate an entry matching the selection.//
|
||||
for(int index = rowObjectByIndexMap.getSize() - 1; (!found) && (index >= 0); index--) {
|
||||
if(getRowObjectAtIndex(index).objectId == selectedObjectIdOnServer) {
|
||||
controlSetSelection(index);
|
||||
found = true;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
if(!found) {
|
||||
//Error: Could not find an object matching the server's description!//
|
||||
//TODO: Should we tell the server to deselect the value?
|
||||
}//if//
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
controlSetSelection(-1);
|
||||
}//else//
|
||||
}//if//
|
||||
else { //Allow multiple selections.//
|
||||
if((selectionObjectIds == null) || (selectionObjectIds.length == 0)) {
|
||||
//Clear all selections.//
|
||||
controlSetSelection(-1);
|
||||
}//if//
|
||||
else {
|
||||
//TODO: Creating an array of flags the size of the entire collection seems inefficient. Perhaps we can make this more efficient.//
|
||||
boolean[] selectionFlags = new boolean[rowObjectByIndexMap.getSize()];
|
||||
|
||||
//Initialize the bit field.//
|
||||
for(int index = 0; index < selectionFlags.length; index++) {
|
||||
selectionFlags[index] = false;
|
||||
}//for//
|
||||
|
||||
//Apply all selections.//
|
||||
for(int selectionIndex = 0; selectionIndex < selectionObjectIds.length; selectionIndex++) {
|
||||
boolean hasSelected = false;
|
||||
|
||||
//Since an object can occur multiple times in the control we will the one already selected.//
|
||||
for(int index = 0; (!hasSelected) && (index < selectionFlags.length); index++) {
|
||||
if((!selectionFlags[index]) && (getRowObjectAtIndex(index).objectId == selectionObjectIds[selectionIndex]) && (controlIsSelected(index))) {
|
||||
hasSelected = true;
|
||||
selectionObjectIds[selectionIndex] = index;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//TODO: Looping twice sucks... we could combine the loops with a little extra code.//
|
||||
//If an object was not already selected then pick the first one in the control.//
|
||||
for(int index = 0; (!hasSelected) && (index < selectionFlags.length); index++) {
|
||||
if((!selectionFlags[index]) && (getRowObjectAtIndex(index).objectId == selectionObjectIds[selectionIndex]) && (!controlIsSelected(index))) {
|
||||
hasSelected = true;
|
||||
selectionObjectIds[selectionIndex] = index;
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//We were not able to apply the selection since there were not enough instances of the object in the control.//
|
||||
if(!hasSelected) {
|
||||
int[] temp = new int[selectionObjectIds.length];
|
||||
|
||||
//Fix the array of selections since it now has one too many positions.//
|
||||
System.arraycopy(selectionObjectIds, 0, temp, 0, selectionIndex - 1);
|
||||
System.arraycopy(selectionObjectIds, selectionIndex - 1, temp, selectionIndex - 1, selectionObjectIds.length - selectionIndex);
|
||||
selectionObjectIds = temp;
|
||||
|
||||
//TODO: Should we notify the server that the selection is not possible? We could simply remove the selection.//
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
controlSetSelections(selectionObjectIds);
|
||||
}//else//
|
||||
}//else//
|
||||
|
||||
//Update the linkages that connect to the selection.//
|
||||
updateSelectionLinks();
|
||||
}//if//
|
||||
else {
|
||||
String selectionText = (String) messageData;
|
||||
|
||||
controlSetSelection(selectionText);
|
||||
selectedObjectIdOnServer = -1;
|
||||
customSelectionOnServer = selectionText;
|
||||
}//else//
|
||||
break;
|
||||
}//case//
|
||||
case MESSAGE_ADD_SELECTION: {
|
||||
int[] selectionObjectIds = (int[]) viewMessage.getMessageData();
|
||||
|
||||
//For each additional selection, find the first non-selected item with the given object id and select it.//
|
||||
for(int selectionIndex = 0; selectionIndex < selectionObjectIds.length; selectionIndex++) {
|
||||
boolean hasSelected = false;
|
||||
|
||||
for(int index = 0; (!hasSelected) && (index < rowObjectByIndexMap.getSize()); index++) {
|
||||
if((getRowObjectAtIndex(index).objectId == selectionObjectIds[selectionIndex]) && (!controlIsSelected(index))) {
|
||||
hasSelected = true;
|
||||
controlAddSelection(index);
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
if(!hasSelected) {
|
||||
//TODO: Should we notify the server that the selection is not possible? We could simply remove the selection.//
|
||||
}//if//
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case MESSAGE_REMOVE_SELECTION: {
|
||||
int[] selectionObjectIds = (int[]) viewMessage.getMessageData();
|
||||
|
||||
//For each additional selection, find the first non-selected item with the given object id and select it.//
|
||||
for(int selectionIndex = 0; selectionIndex < selectionObjectIds.length; selectionIndex++) {
|
||||
boolean hasDeselected = false;
|
||||
|
||||
for(int index = rowObjectByIndexMap.getSize(); (!hasDeselected) && (index >= 0); index--) {
|
||||
if((getRowObjectAtIndex(index).objectId == selectionObjectIds[selectionIndex]) && (controlIsSelected(index))) {
|
||||
hasDeselected = true;
|
||||
controlRemoveSelection(index);
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
if(!hasDeselected) {
|
||||
//I don't think any action is necessary, though this should not occur.//
|
||||
}//if//
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case MESSAGE_REMOVE_SELECTIONS: {
|
||||
selectedObjectIdOnServer = -1;
|
||||
controlRemoveAllSelections();
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
retVal = super.internalProcessMessage(viewMessage);
|
||||
}//default//
|
||||
}//switch//
|
||||
|
||||
return retVal;
|
||||
}//internalProcessMessage()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.foundation.tcv.swt.client.CollectionComponent#updateHiddenData(com.foundation.tcv.swt.client.CollectionComponent.RowObject, int, java.lang.Object)
|
||||
*/
|
||||
protected void updateHiddenData(RowObject object, int hiddenDataIndex, Object value) {
|
||||
object.hiddenData[hiddenDataIndex] = value;
|
||||
|
||||
if(getAllowMultiSelection()) {
|
||||
boolean updateSelectionLinks = false;
|
||||
int[] selectedIndices = controlGetSelections();
|
||||
RowObject[] selectedObjects = new RowObject[selectedIndices.length];
|
||||
|
||||
if((selectedIndices != null) && (selectedIndices.length > 0)) {
|
||||
//Determine whether any of the selections match with the hidden data's object to see whether we need to update any hidden data linkages.//
|
||||
for(int selectionIndex = 0; (!updateSelectionLinks) && (selectionIndex < selectedIndices.length); selectionIndex++) {
|
||||
RowObject selection = getRowObjectAtIndex(selectedIndices[selectionIndex]);
|
||||
|
||||
updateSelectionLinks = selection == object;
|
||||
selectedObjects[selectionIndex] = selection;
|
||||
}//for//
|
||||
}//if//
|
||||
|
||||
if(updateSelectionLinks) {
|
||||
getHiddenData(hiddenDataIndex).invokeLinkage(selectedObjects);
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
int selectedIndex = controlGetSelection();
|
||||
|
||||
if(selectedIndex != -1) {
|
||||
RowObject selectedObject = getRowObjectAtIndex(selectedIndex);
|
||||
|
||||
if(selectedObject == object) {
|
||||
getHiddenData(hiddenDataIndex).invokeLinkage(selectedObject);
|
||||
}//if//
|
||||
}//if//
|
||||
}//else//
|
||||
}//updateHiddenData()//
|
||||
/**
|
||||
* Removes all displayed items from the control.
|
||||
*/
|
||||
protected abstract void controlRemoveAll(); //removeAll//
|
||||
/**
|
||||
* 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); //setItems//
|
||||
/**
|
||||
* 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); //setItem//
|
||||
/**
|
||||
* Adds an item to the control's collection at a given index.
|
||||
* @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); //add//
|
||||
/**
|
||||
* 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); //add//
|
||||
/**
|
||||
* 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); //remove//
|
||||
/**
|
||||
* Gets the indices selected within the control.
|
||||
* @return The collection of indices selected.
|
||||
*/
|
||||
protected abstract int[] controlGetSelections(); //getSelectionIndices//
|
||||
/**
|
||||
* Gets the index selected within the control.
|
||||
* @return The index currently selected.
|
||||
*/
|
||||
protected abstract int controlGetSelection(); //getSelectionIndex//
|
||||
/**
|
||||
* Sets the selected values in the control.
|
||||
* @param indices The indices of the selected values.
|
||||
*/
|
||||
protected abstract void controlSetSelections(int[] indices); //setSelection//
|
||||
/**
|
||||
* Sets the selected value in the control.
|
||||
* <p>Note: Not all controls support custom selected text. Currently only combo box does. </p>
|
||||
* @param text The text of the selected value.
|
||||
*/
|
||||
protected abstract void controlSetSelection(String text); //setSelection//
|
||||
/**
|
||||
* Sets the selected value in the control.
|
||||
* @param index The index of the selected value.
|
||||
*/
|
||||
protected abstract void controlSetSelection(int index); //setSelection//
|
||||
/**
|
||||
* Adds a selected value in the control.
|
||||
* @param index The index of the selected value.
|
||||
*/
|
||||
protected abstract void controlAddSelection(int index); //select//
|
||||
/**
|
||||
* Deselects a value in the control.
|
||||
* @param index The index of the selected value.
|
||||
*/
|
||||
protected abstract void controlRemoveSelection(int index); //deselect//
|
||||
/**
|
||||
* Deselects all values in the control.
|
||||
*/
|
||||
protected abstract void controlRemoveAllSelections(); //deselectAll//
|
||||
/**
|
||||
* 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); //isSelected//
|
||||
/**
|
||||
* 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(); //getText//
|
||||
/**
|
||||
* Sets 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>
|
||||
* @param text The control's new text.
|
||||
*/
|
||||
protected abstract void controlSetText(String text); //setText//
|
||||
/**
|
||||
* 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.//
|
||||
}//IndexedCollectionComponent//
|
||||
Reference in New Issue
Block a user