298 lines
11 KiB
Java
298 lines
11 KiB
Java
|
|
/*
|
||
|
|
* 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.server;
|
||
|
|
|
||
|
|
import com.common.util.*;
|
||
|
|
import com.common.util.optimized.*;
|
||
|
|
import com.foundation.tcv.swt.*;
|
||
|
|
import com.foundation.tcv.view.*;
|
||
|
|
|
||
|
|
/*
|
||
|
|
* Extends the CollectionComponent to provide indexing of the collection items.
|
||
|
|
* This is an abstract class that is meant to reduce the end control complexity.
|
||
|
|
*/
|
||
|
|
public abstract class IndexedCollectionComponent extends CollectionComponent implements IIndexedCollectionComponent {
|
||
|
|
/**
|
||
|
|
* IndexedCollectionComponent constructor.
|
||
|
|
* @param parent The parent container.
|
||
|
|
* @param name The name of the component.
|
||
|
|
*/
|
||
|
|
public IndexedCollectionComponent(Container parent, String name, int style) {
|
||
|
|
super(parent, name, style);
|
||
|
|
}//IndexedCollectionComponent()//
|
||
|
|
/**
|
||
|
|
* Refreshes the item data.
|
||
|
|
* @param item The collection item whose data needs refreshing.
|
||
|
|
*/
|
||
|
|
protected void internalViewRefreshItem(Object item) {
|
||
|
|
RowObject rowObject = getRowObject(item);
|
||
|
|
|
||
|
|
if(rowObject != null) {
|
||
|
|
sendMessage(MESSAGE_SET_ITEM, new Object[] {new Integer(rowObject.objectId), getItemData(rowObject)});
|
||
|
|
}//if//
|
||
|
|
else {
|
||
|
|
//Do nothing. It may simply be a stray event (fired before we removed event listeners, but received after they were removed).//
|
||
|
|
}//else//
|
||
|
|
}//internalViewRefreshItem()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.swt.CollectionComponent#internalViewRefreshCollection(com.common.util.ICollection, com.common.util.ICollection)
|
||
|
|
*/
|
||
|
|
protected void internalViewRefreshCollection(ICollection newCollection, ICollection oldCollection) {
|
||
|
|
//Remove all listeners, mappings, and metadata.//
|
||
|
|
itemAllRemoved();
|
||
|
|
|
||
|
|
if((newCollection != null) && (newCollection.getSize() > 0)) {
|
||
|
|
IIterator iterator = newCollection.iterator();
|
||
|
|
// Object[] itemData = newCollection.getSize() > 0 ? new Object[newCollection.getSize()] : null;
|
||
|
|
// Object[] hiddenData = newCollection.getSize() > 0 && getHiddenDataCount() > 0 ? new Object[newCollection.getSize()][getHiddenDataCount()] : null;
|
||
|
|
// int[] objectIds = itemData != null ? new int[itemData.length] : null;
|
||
|
|
int index = 0;
|
||
|
|
|
||
|
|
//Get the array of strings representing the list contents.//
|
||
|
|
while(iterator.hasNext()) {
|
||
|
|
Object value = iterator.next();
|
||
|
|
|
||
|
|
itemAdded(value, index++, true);
|
||
|
|
// RowObject rowObject = itemAdded(value, index, false);
|
||
|
|
//
|
||
|
|
// //Add the item mappings without notifying the client.//
|
||
|
|
// if(rowObject.isFirstReference()) {
|
||
|
|
// //Add the value to the item array.//
|
||
|
|
// itemData[index] = getItemData(rowObject);
|
||
|
|
//
|
||
|
|
// if(hiddenData != null) {
|
||
|
|
// hiddenData[index] = getItemHiddenData(value);
|
||
|
|
// }//if//
|
||
|
|
// }//if//
|
||
|
|
//
|
||
|
|
// objectIds[index] = rowObject.objectId;
|
||
|
|
//
|
||
|
|
// index++;
|
||
|
|
}//while//
|
||
|
|
|
||
|
|
//Set the collection contents.//
|
||
|
|
// sendMessage(MESSAGE_SET_ITEMS, new Object[] {itemData, objectIds, hiddenData});
|
||
|
|
|
||
|
|
//If the selection was invalid previously then refresh the selection since it may no longer be invalid.//
|
||
|
|
if(isSelectionInvalid) {
|
||
|
|
internalViewRefreshSelection();
|
||
|
|
}//if//
|
||
|
|
}//if//
|
||
|
|
else {
|
||
|
|
//Remove all collection contents.//
|
||
|
|
sendMessage(MESSAGE_REMOVE_ALL, null);
|
||
|
|
}//else//
|
||
|
|
}//internalViewRefreshCollection()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.swt.CollectionComponent#internalViewRefreshSelection(java.lang.Object)
|
||
|
|
*/
|
||
|
|
protected void internalViewRefreshSelection(Object selectedItem) {
|
||
|
|
//Send selection index or indices to the remote control where it will determine whether the selection should be changed.//
|
||
|
|
//Again: What to do about impossible selections?//
|
||
|
|
Object currentSelection = getModelSelection();
|
||
|
|
int objectId;
|
||
|
|
|
||
|
|
if(currentSelection != null) {
|
||
|
|
RowObject rowObject = getRowObject(currentSelection);
|
||
|
|
|
||
|
|
objectId = rowObject == null ? INVALID_OBJECT_ID : rowObject.objectId;
|
||
|
|
|
||
|
|
if((objectId == -1) && (getAllowUserItems())) {
|
||
|
|
sendMessage(MESSAGE_SET_SELECTION, currentSelection.toString());
|
||
|
|
}//if//
|
||
|
|
else if(objectId == -1) {
|
||
|
|
isSelectionInvalid = true;
|
||
|
|
//Note: We are no longer invalidating the model selection since this may be a valid action given that the selection may be attached to an attribute that is also attached to another component.//
|
||
|
|
sendMessage(MESSAGE_SET_SELECTION, null);
|
||
|
|
}//else if//
|
||
|
|
else {
|
||
|
|
isSelectionInvalid = false;
|
||
|
|
//Send selection.//
|
||
|
|
sendMessage(MESSAGE_SET_SELECTION, new int[] {objectId});
|
||
|
|
}//else//
|
||
|
|
}//if//
|
||
|
|
else {
|
||
|
|
//No selection.//
|
||
|
|
sendMessage(MESSAGE_SET_SELECTION, 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) {
|
||
|
|
//Collect indexes and collections of indexes for each selection and send all to control. Control will then apply necessary changes.//
|
||
|
|
//How to deal with impossible selections? We could send back a deselect message?//
|
||
|
|
if(newSelections != null) {
|
||
|
|
IntArray selectionIndices = new IntArray(newSelections.getSize());
|
||
|
|
IIterator modelSelectionIterator = null;
|
||
|
|
|
||
|
|
modelSelectionIterator = newSelections.iterator();
|
||
|
|
|
||
|
|
//Apply differences between the selection collection and the control selection. Also remove all impossible selections.//
|
||
|
|
while(modelSelectionIterator.hasNext()) {
|
||
|
|
Object modelSelection = modelSelectionIterator.next();
|
||
|
|
RowObject rowObject = getRowObject(modelSelection);
|
||
|
|
|
||
|
|
if(rowObject == null) {
|
||
|
|
//An invalid selection because the selection is not in the collection of displayed values.//
|
||
|
|
modelSelectionIterator.remove();
|
||
|
|
}//if//
|
||
|
|
else {
|
||
|
|
selectionIndices.add(rowObject.objectId);
|
||
|
|
}//else//
|
||
|
|
}//while//
|
||
|
|
|
||
|
|
sendMessage(MESSAGE_SET_SELECTION, selectionIndices.toArray());
|
||
|
|
}//if//
|
||
|
|
else {
|
||
|
|
//Remove all selections.//
|
||
|
|
sendMessage(MESSAGE_REMOVE_SELECTIONS, null);
|
||
|
|
}//else//
|
||
|
|
}//internalViewRefreshSelections()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.tcv.swt.server.CollectionComponent#registerItem(com.foundation.tcv.swt.server.RowObject)
|
||
|
|
*/
|
||
|
|
protected void registerItem(RowObject rowObject) {
|
||
|
|
super.registerItem(rowObject);
|
||
|
|
}//registerItem()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.tcv.swt.server.CollectionComponent#unregisterItem(com.foundation.tcv.swt.server.RowObject)
|
||
|
|
*/
|
||
|
|
protected void unregisterItem(RowObject rowObject) {
|
||
|
|
super.unregisterItem(rowObject);
|
||
|
|
}//unregisterItem()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.tcv.swt.server.CollectionComponent#unregisterItems()
|
||
|
|
*/
|
||
|
|
protected void unregisterItems() {
|
||
|
|
super.unregisterItems();
|
||
|
|
}//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) {
|
||
|
|
RowObject rowObject = getRowObject(value);
|
||
|
|
|
||
|
|
if(rowObject != null) {
|
||
|
|
sendMessage(MESSAGE_ADD_SELECTION, new int[] {rowObject.objectId});
|
||
|
|
}//if//
|
||
|
|
}//selectionAdded()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.swt.CollectionComponent#selectionRemoved(java.lang.Object)
|
||
|
|
*/
|
||
|
|
protected void selectionRemoved(Object value) {
|
||
|
|
RowObject rowObject = getRowObject(value);
|
||
|
|
|
||
|
|
if(rowObject != null) {
|
||
|
|
sendMessage(MESSAGE_REMOVE_SELECTION, new int[] {rowObject.objectId});
|
||
|
|
}//if//
|
||
|
|
}//selectionRemoved()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.swt.CollectionComponent#selectionAllRemoved()
|
||
|
|
*/
|
||
|
|
protected void selectionAllRemoved() {
|
||
|
|
sendMessage(MESSAGE_REMOVE_SELECTIONS, null);
|
||
|
|
}//selectionAllRemoved()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.tcv.view.IViewComponent#processMessage(com.foundation.tcv.model.ViewMessage)
|
||
|
|
*/
|
||
|
|
public Object processMessage(ViewMessage viewMessage) {
|
||
|
|
Object retVal = null;
|
||
|
|
|
||
|
|
switch(viewMessage.getMessageNumber()) {
|
||
|
|
case MESSAGE_VIEW_SYNCHRONIZE_SELECTION: { //Receive the selection information from the client.//
|
||
|
|
Object messageData = viewMessage.getMessageData();
|
||
|
|
|
||
|
|
if(getAllowMultiSelection()) {
|
||
|
|
int[] selectionObjectIds = (int[]) messageData;
|
||
|
|
ICollection modelSelections = getModelSelections();
|
||
|
|
|
||
|
|
//Prevent the selection additions from causing a feedback loop.//
|
||
|
|
suspendSelectionHooks = true;
|
||
|
|
|
||
|
|
try {
|
||
|
|
if(modelSelections != null) {
|
||
|
|
Object[] controlSelectionObjects = new Object[selectionObjectIds.length];
|
||
|
|
boolean[] markedControlSelections = new boolean[controlSelectionObjects.length];
|
||
|
|
IIterator modelSelectionIterator = modelSelections.iterator();
|
||
|
|
LiteList removed = new LiteList(modelSelections.getSize());
|
||
|
|
LiteList added = new LiteList(selectionObjectIds.length);
|
||
|
|
|
||
|
|
for(int index = 0; index < selectionObjectIds.length; index++) {
|
||
|
|
controlSelectionObjects[index] = getRowObject(selectionObjectIds[index]).value;
|
||
|
|
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 selectedObjectId = (messageData != null) && !(messageData instanceof String) ? ((Integer) messageData).intValue() : -1;
|
||
|
|
|
||
|
|
if(selectedObjectId == -1) {
|
||
|
|
if((getAllowUserItems()) && (((String) messageData).length() > 0)) { //TODO: If the user wants numbers only, should the conversion occur on the server or the client?//
|
||
|
|
//Set the custom value.//
|
||
|
|
setModelSelection((String) messageData);
|
||
|
|
}//if//
|
||
|
|
else {
|
||
|
|
setModelSelection(null);
|
||
|
|
}//else//
|
||
|
|
}//if//
|
||
|
|
else {
|
||
|
|
setModelSelection(getRowObject(selectedObjectId).value);
|
||
|
|
}//else//
|
||
|
|
}//else//
|
||
|
|
|
||
|
|
if(getAutoValidate()) {
|
||
|
|
postSynchronizeValidate();
|
||
|
|
}//if//
|
||
|
|
break;
|
||
|
|
}//case//
|
||
|
|
default: {
|
||
|
|
retVal = super.processMessage(viewMessage);
|
||
|
|
}//default//
|
||
|
|
}//switch//
|
||
|
|
|
||
|
|
return retVal;
|
||
|
|
}//processMessage()//
|
||
|
|
}//IndexedCollectionComponent//
|