/* * 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 java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.FileNotFoundException; import com.common.debug.*; import com.common.util.optimized.ObjectIntHashMap; import com.foundation.view.*; import com.foundation.view.resource.AbstractResourceService; import com.foundation.controller.AbstractViewController; import com.foundation.controller.DecorationManager; import com.foundation.event.*; import com.foundation.tcv.server.controller.*; import com.foundation.tcv.view.*; public abstract class AbstractComponent implements com.foundation.tcv.swt.IAbstractComponent, IAbstractComponent, IAbstractRemoteViewComponent, IEventHandler { /** Identifies the controller for the client session that this component interacts over. */ private SessionViewController sessionViewController = null; /** The component's number. This allows lookup of components in the view by the number. */ private int number = -1; /** The handler for all requests. All requests should pass through this handler so they are handled on the proper thread in the proper order. */ private IViewRequestHandler requestHandler = null; /** Flags the component to suppress all updates to the view. This is useful for hidden components that will be explicitly refreshed. */ private boolean suppressUpdates = false; /** Whether the component has already been initialized. This is useful when setting attributes which require initialization after or durring the component's initialization. */ private boolean isInitialized = false; /** The last used decoration identifier number. */ private int lastDecorationNumber = 0; /** A mapping of decoration identifier numbers by the decoration. */ private ObjectIntHashMap decorationMap = new ObjectIntHashMap(5); /** * AbstractComponent default constructor. */ public AbstractComponent() { }//AbstractComponent()// /** * AbstractComponent constructor. * @param sessionViewController The view component's session controller. */ public AbstractComponent(SessionViewController sessionViewController) { super(); String clientClassName = getClientClassName(); this.sessionViewController = sessionViewController; requestHandler = sessionViewController.getViewRequestHandler(); //Notify the client to create the control if the control has a client side part.// if((clientClassName != null) && (clientClassName.length() > 0)) { number = sessionViewController.registerComponent(this); sessionViewController.sendMessage(new ViewMessage(0, MESSAGE_CREATE_COMPONENT, getClientClassName(), null, number, 0, true), false); }//if// else if(clientClassName == null) { Debug.log("Error: Must implement the getClientClassName() method and return a non-null value from the class: " + getClass().getName()); }//else if// }//AbstractComponent()// /** * Suspends all layouts and packing while the view is getting setup. */ public void suspendLayouts() { sendMessage(MESSAGE_SUSPEND_LAYOUTS, null, null, 1, -1); }//suspendLayouts()// /** * Resumes processing of requests to layout or pack components. */ public void resumeLayouts() { sendMessage(MESSAGE_SUSPEND_LAYOUTS, null); }//resumeLayouts()// /** * Whether the component is suspending all layouts and packing while the view is getting setup. * @return Whether the component should not layout or pack. */ public boolean isSuspendingLayouts() { return false; }//isSuspendingLayouts()// /* (non-Javadoc) * @see com.foundation.view.IView#getViewContext() */ public IViewContext getViewContext() { return getSessionViewController().getSessionController(); }//getViewContext()// /** * Gets the session view controller for the component. * @return The component's session view controller. */ public SessionViewController getSessionViewController() { return sessionViewController; }//getSessionViewController()// /** * Gets the event loop used to queue outside requests so that the internals are mostly single threaded. * @return The request handler that single threads external requests (from the application). Internal requests from the remote process will be handled on a different thread. */ protected IViewRequestHandler getEventLoop() { return requestHandler; }//getEventLoop()// /** * Sets the menu for the component. * @param menu The menu optionally used by the component. */ public void setMenu(Menu menu) { //Does nothing.// }//setMenu()// /** * Determines whether the calling thread is the view's event thread. * @return Whether the view's event thread and the calling thread are one and the same. * @link com.foundation.view.IView.isViewThread() */ public boolean isViewThread() { return getEventLoop().isRequestThread(); }//isViewThread()// /** * Verifies that the calling thread is allowed access to the view components. *

Note: This is really a debug only operation and should be turned off for production applications.

*/ public void verifyThread() { if(!isViewThread()) { Debug.log(new RuntimeException("Error: Invalid thread.")); }//if// }//verifyThread()// /** * Determines whether updates to the view should be suppressed. * @return Whether update suppression is requested. */ public boolean suppressUpdates() { return suppressUpdates; }//suppressUpdates()// /** * Determines whether updates to the view should be suppressed. * @param suppressUpdates Whether update suppression is requested. */ public void suppressUpdates(boolean suppressUpdates) { this.suppressUpdates = suppressUpdates; }//suppressUpdates()// /** * Determines whether the component has already been initialized. This is useful when setting attributes which require initialization after or during the component's initialization. * @return Whether the component's internalViewInitalize method has been or is being run. */ protected boolean isInitialized() { return isInitialized; }//isInitialized()// /** * Determines whether the component has already been initialized. * @param isInitialized Whether the component's internalViewInitalize method has been or is being run. */ protected void isInitialized(boolean isInitialized) { this.isInitialized = isInitialized; }//isInitialized()// /** * Gets the component's number which identifies this component in the view. * @return The view unique number for this component. */ public int getNumber() { return number; }//getNumber()// /** * Gets the component's set of numbers that identifies it uniquely within the session. * @return The identity of the component within the session. */ public long[] getIdentity() { return new long[] {getSessionViewController().getNumber(), (long) number}; }//getIdentity()// /** * Increments the hold count on the message queue so that messages will be queued up until the count reaches zero. */ public void addMessageHold() { //TODO: Remove this method. suspendMessages(); }//addMessageHold()// /** * Decrements the hold count on the message queue so that messages will be queued up until the count reaches zero. */ public void removeMessageHold() { //TODO: Remove this method. resumeMessages(); }//removeMessageHold()// /** * Increments the hold count on the message queue so that messages will be queued up until the count reaches zero. */ public void suspendMessages() { sessionViewController.incrementMessageHoldCount(); }//suspendMessages()// /** * Decrements the hold count on the message queue so that messages will be queued up until the count reaches zero. */ public void resumeMessages() { sessionViewController.decrementMessageHoldCount(); }//resumeMessages()// /** * Suspends all drawing on the client. */ public void suspendRedraw() { sendMessage(MESSAGE_SUSPEND_REDRAW, null); }//suspendRedraw()// /** * Resumes all drawing on the client. */ public void resumeRedraw() { sendMessage(MESSAGE_RESUME_REDRAW, null); }//resumeRedraw()// /** * Tries to load an image from the file system. * @param imageName The image name and path. If a path is not provided the application path will be used. * @return The image bytes, or null if the image was not found. */ protected byte[] loadImage(String imageName) { File file = new File(imageName); byte[] result = null; if((file.exists()) && (file.isFile())) { FileInputStream in = null; try { in = new FileInputStream(file); result = new byte[in.available()]; in.read(result); }//try// catch(FileNotFoundException e) { Debug.log(e, "Unable to load the image: " + imageName); result = null; }//catch// catch(IOException e) { Debug.log(e, "Unable to load the image: " + imageName); result = null; }//catch// finally { try { in.close(); }//try// catch(Throwable e) { Debug.handle(e); }//catch// }//finally// }//if// return result; }//loadImage()// /** * Gets the container containing this component. * @return The containing container, or null if this component is a root level window. */ public abstract IAbstractContainer getContainer(); /* (non-Javadoc) * @see com.foundation.view.IMultiResourceAssociationChangeListener#getResourceService() */ public AbstractResourceService getResourceService() { return getContainer().getResourceService(); }//getResourceService()// /** * Gets the component in the view given the component's view unique number. * @return The view component assigned the component number. */ protected AbstractComponent getComponent(int componentNumber) { return (AbstractComponent) getSessionViewController().getComponent(componentNumber); }//getComponent()// /** * Creates a new view message with the given message number and message data. * @param messageNumber The component specific number indicating the message type. * @param messageData The data specific to the message type. * @param secondaryMessageData The optional secondary message data reference. * @param messageInteger The numeric data associated with the message. * @param secondaryMessageInteger The secondary numeric data associated with the message. * @param isOneWay Whether the message doesn't require a return value. * @return The view message object representing the message. */ private ViewMessage createViewMessage(int messageNumber, Object messageData, Object secondaryMessageData, int messageInteger, int secondaryMessageInteger, boolean isOneWay) { ViewMessage result = null; if(number != -1) { result = new ViewMessage(number, messageNumber, messageData, secondaryMessageData, messageInteger, secondaryMessageInteger, !isOneWay); }//if// else { Debug.log("Error: Cannot send a message to the client from a component that has an invalid number."); }//else// return result; }//createViewMessage()// /** * Sends a message to the client component. * @param messageNumber The message number which will be used by the client component to handle the message and interperate the parameters. * @param messageData The data associated with the message. */ public void sendMessage(int messageNumber, Object messageData) { sendMessage(messageNumber, messageData, null, 0, 0); }//sendMessage()// /** * Sends a message to the client component. * @param messageNumber The message number which will be used by the client component to handle the message and interperate the parameters. * @param messageData The data associated with the message. * @param secondaryMessageData The optional secondary message data reference. * @param messageInteger The numeric data associated with the message. * @param secondaryMessageInteger The secondary numeric data associated with the message. */ public void sendMessage(int messageNumber, Object messageData, Object secondaryMessageData, int messageInteger, int secondaryMessageInteger) { sessionViewController.sendMessage(createViewMessage(messageNumber, messageData, secondaryMessageData, messageInteger, secondaryMessageInteger, true), false); }//sendMessage()// /** * Sends a round trip message to the client, waiting until the message result comes back. * @param messageNumber The control's number for the message (as defined in the control's interface shared between the client and server). * @param messageData The data specific to the message. * @return The result of the message. */ public Object sendRoundTripMessage(int messageNumber, Object messageData) { return sendRoundTripMessage(messageNumber, messageData, null, 0, 0); }//sendRoundTripMessage()// /** * Sends a round trip message to the client, waiting until the message result comes back. * @param messageNumber The control's number for the message (as defined in the control's interface shared between the client and server). * @param messageData The data specific to the message. * @param secondaryMessageData The optional secondary message data reference. * @param messageInteger The numeric data associated with the message. * @param secondaryMessageInteger The secondary numeric data associated with the message. * @return The result of the message. */ public Object sendRoundTripMessage(int messageNumber, Object messageData, Object secondaryMessageData, int messageInteger, int secondaryMessageInteger) { return sessionViewController.sendMessage(createViewMessage(messageNumber, messageData, secondaryMessageData, messageInteger, secondaryMessageInteger, false), true); }//sendRoundTripMessage()// /* (non-Javadoc) * @see com.foundation.tcv.view.IAbstractRemoteViewComponent#processMessage(com.foundation.tcv.view.ViewMessage) */ public Object processMessage(ViewMessage viewMessage) { Object result = null; switch(viewMessage.getMessageNumber()) { default: { Debug.log("Error: processMessage(ViewMessage) is not implemented."); break; }//default// }//switch// return result; }//processMessage()// /* (non-Javadoc) * @see com.foundation.event.IHandler#evaluate(int, java.lang.Object[], int) */ public final void evaluate(int eventNumber, Object[] arguments, int flags) { Debug.log("Error: evaluate(int, Object[]) should never be called."); }//evaluate()// /* (non-Javadoc) * @see com.foundation.event.IEventHandler#evaluate(com.foundation.event.IEventEmitter, int, java.lang.Object[], int) */ public final void evaluate(final IEventEmitter eventEmitter, final int eventNumber, final Object[] arguments, int flags) { if(EventSupport.isStandardEvent(flags)) { verifyThread(); internalEvaluate(eventEmitter, eventNumber, arguments); }//if// }//evaluate()// /** * A default handler for events received by the component. * @param eventEmitter The object which fired the event. * @param eventNumber The unique number for the event. * @param arguments The event arguments which may be null if there are none. */ protected void internalEvaluate(IEventEmitter eventEmitter, int eventNumber, Object[] arguments) { //Subclasses should override this and provide an implementation.// //Subclasses would only need an implementation if they had IEventAssociation or IAttributeAssociation attributes.// internalEvaluate(eventEmitter, EventSupport.getEventName(eventEmitter.getClass(), eventNumber), arguments); }//internalEvaluate()// /** * A default handler for events received by the component. * @param eventEmitter The object which fired the event. * @param eventNumber The unique name for the event. * @param arguments The event arguments which may be null if there are none. */ protected void internalEvaluate(IEventEmitter eventEmitter, String eventName, Object[] arguments) { //Subclasses should override this and provide an implementation.// //Subclasses would only need an implementation if they had IEventAssociation or IAttributeAssociation attributes.// }//internalEvaluate()// /* (non-Javadoc) * @see com.foundation.view.IAttributeAssociationChangeListener#onValueChanged(com.foundation.view.IAttributeAssociation) */ public void onValueChanged(IAttributeAssociation attributeAssociation) { verifyThread(); internalOnValueChanged(attributeAssociation); }//onValueChanged()// /* (non-Javadoc) * @see com.foundation.view.ISingleResourceAssociationChangeListener#onValueChanged(com.foundation.view.ResourceAssociation, int) */ public final void onValueChanged(ResourceAssociation resourceAssociation, int flags) { verifyThread(); if(isInitialized()) { if(resourceAssociation instanceof SingleResourceAssociation) { internalOnValueChanged((SingleResourceAssociation) resourceAssociation, flags); }//if// else if(resourceAssociation instanceof CollectingSingleResourceAssociation) { internalOnValueChanged((CollectingSingleResourceAssociation) resourceAssociation); }//else if// }//if// }//onValueChanged()// /* (non-Javadoc) * @see com.foundation.view.IMultiResourceAssociationChangeListener#onValueChanged(com.foundation.view.ResourceAssociation, java.lang.Object, java.lang.Object, boolean) */ public final void onValueChanged(ResourceAssociation resourceAssociation, Object alteredItem, Object data, boolean isUpdate) { verifyThread(); if(isInitialized()) { if(resourceAssociation instanceof MultiResourceAssociation) { internalOnValueChanged((MultiResourceAssociation) resourceAssociation, alteredItem, data, isUpdate); }//else if// else if(resourceAssociation instanceof CollectingMultiResourceAssociation) { internalOnValueChanged((CollectingMultiResourceAssociation) resourceAssociation, alteredItem, data); }//else if// }//if// }//onValueChanged()// /* (non-Javadoc) * @see com.foundation.view.ISingleResourceAssociationChangeListener#onModelExternallyChanged(com.foundation.view.ResourceAssociation, boolean, java.lang.Object) */ public void onModelExternallyChanged(ResourceAssociation resourceAssociation, boolean isCleared, Object originalValue) { verifyThread(); if(isInitialized()) { internalOnModelExternallyChanged((SingleResourceAssociation) resourceAssociation, isCleared, originalValue); }//if// }//onModelExternallyChanged()// /* (non-Javadoc) * @see com.foundation.view.IMultiResourceAssociationChangeListener#onModelExternallyChanged(com.foundation.view.ResourceAssociation, java.lang.Object, java.lang.Object, boolean, java.lang.Object) */ public void onModelExternallyChanged(ResourceAssociation resourceAssociation, Object alteredItem, Object data, boolean isCleared, Object originalValue) { verifyThread(); if(isInitialized()) { internalOnModelExternallyChanged((MultiResourceAssociation) resourceAssociation, alteredItem, data, isCleared, originalValue); }//if// }//onModelExternallyChanged()// /* (non-Javadoc) * @see com.foundation.view.IAbstractComponent#onEventFired(com.foundation.view.IEventAssociation, java.lang.Object[]) */ public void onEventFired(IEventAssociation eventAssociation, Object[] eventArguments) { verifyThread(); addMessageHold(); try { internalOnEventFired(eventAssociation, eventArguments); }//try// finally { removeMessageHold(); }//finally// }//onEventFired()// /** * Called by the value holders when a registered attribute changes value or the value containing the attribute changes. * @param attributeAssociation The attribute association used to register with the attribute. */ protected void internalOnValueChanged(IAttributeAssociation attributeAssociation) { Debug.log(new RuntimeException("Error: Unexpected (unhandled by AbstractComponent) attribute association found. AttributeName: " + attributeAssociation.getAttributeName())); }//internalOnValueChanged()// /** * Called by the resource association when a resource changes value. *

The change in value will be because the resource context altered its set of current resources and the associated resources was in the set that was altered.

* @param resourceAssociation The resource association used to register with the resource. * @param isUpdate Whether the alteration was due to the object's reflected object updating it, in which case the user might want to be warned. */ protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) { Debug.log(new RuntimeException("Error: Unexpected (unhandled by AbstractComponent) resource association found. Resource URL: " + resourceAssociation.toString())); }//internalOnValueChanged()// /** * Called by the resource association when a resource changes value. *

The change in value will be because the resource context altered its set of current resources and the associated resources was in the set that was altered.

* @param resourceAssociation The resource association used to register with the resource. * @param alteredItem The item whose value has been altered. * @param data The data passed when the item was registered with the resource association. * @param isUpdate Whether the alteration was due to the object's reflected object updating it, in which case the user might want to be warned. */ protected void internalOnValueChanged(MultiResourceAssociation resourceAssociation, Object alteredItem, Object data, boolean isUpdate) { Debug.log(new RuntimeException("Error: Unexpected (unhandled by AbstractComponent) resource association found. Resource URL: " + resourceAssociation.toString())); }//internalOnValueChanged()// /** * Called by the resource association when a resource changes value. *

The change in value will be because the resource context altered its set of current resources and the associated resources was in the set that was altered.

* @param resourceAssociation The resource association used to register with the resource. * @param alteredItem The item whose value has been altered. * @param data The data passed when the item was registered with the resource association. */ protected void internalOnValueChanged(CollectingMultiResourceAssociation resourceAssociation, Object alteredItem, Object data) { Debug.log(new RuntimeException("Error: Unexpected (unhandled by AbstractComponent) resource association found. Resource URL: " + resourceAssociation.toString())); }//internalOnValueChanged()// /** * Called by the resource association when a resource changes value. *

The change in value will be because the resource context altered its set of current resources and the associated resources was in the set that was altered.

* @param resourceAssociation The resource association used to register with the resource. */ protected void internalOnValueChanged(CollectingSingleResourceAssociation resourceAssociation) { Debug.log(new RuntimeException("Error: Unexpected (unhandled by AbstractComponent) resource association found. Resource URL: " + resourceAssociation.toString())); }//internalOnValueChanged()// /** * Called by the resource association when a resource changes value. *

The change in value will be because the resource context altered its set of current resources and the associated resources was in the set that was altered.

* @param resourceAssociation The resource association used to register with the resource. * @param isCleared Whether the original value was cleared, in which case the original value parameter should be ignored. * @param originalValue The model value unaltered by the view's user. */ protected void internalOnModelExternallyChanged(SingleResourceAssociation resourceAssociation, boolean isCleared, Object originalValue) { //Debug.log(new RuntimeException("Error: Unexpected (unhandled by AbstractComponent) resource association found. Resource URL: " + resourceAssociation.toString())); }//internalOnModelExternallyChanged()// /** * Called by the resource association when a resource changes value. *

The change in value will be because the resource context altered its set of current resources and the associated resources was in the set that was altered.

* @param resourceAssociation The resource association used to register with the resource. * @param alteredItem The item whose value has been altered. * @param data TODO * @param isCleared Whether the original value was cleared, in which case the original value parameter should be ignored. * @param originalValue The model value unaltered by the view's user. */ protected void internalOnModelExternallyChanged(MultiResourceAssociation resourceAssociation, Object alteredItem, Object data, boolean isCleared, Object originalValue) { //Debug.log(new RuntimeException("Error: Unexpected (unhandled by AbstractComponent) resource association found. Resource URL: " + resourceAssociation.toString())); }//internalOnModelExternallyChanged()// /** * Called when any event association connected with this component is notified that the event has fired. * @param eventAssociation The event association for the event that was fired. * @param eventArguments The non-null event arguments as received by the event association. */ protected void internalOnEventFired(IEventAssociation eventAssociation, Object[] eventArguments) { Debug.log(new RuntimeException("Error: Unexpected (unhandled by AbstractComponent) event association found. Event Number: " + eventAssociation.getEventNumber())); }//internalOnEventFired()// /* (non-Javadoc) * @see com.foundation.view.IView#viewInitializeAll() */ public final void viewInitializeAll() { verifyThread(); // suspendMessages(); // suspendRedraw(); try { internalViewInitializeAll(); sendMessage(MESSAGE_VIEW_INITIALIZE_ALL, null); internalViewRefreshAll(); sendMessage(MESSAGE_VIEW_INITIALIZATION_COMPLETE, null); }//try// finally { // resumeRedraw(); // resumeMessages(); }//finally// }//viewInitializeAll()// /* (non-Javadoc) * @see com.foundation.view.IView#viewReleaseAll() */ public final void viewReleaseAll() { verifyThread(); suspendMessages(); //suspendRedraw(); try { internalViewReleaseAll(); sendMessage(MESSAGE_VIEW_RELEASE_ALL, null); }//try// finally { //resumeRedraw(); resumeMessages(); }//finally// }//viewReleaseAll()// /* (non-Javadoc) * @see com.foundation.view.IView#viewRefreshAll() */ public final void viewRefreshAll() { verifyThread(); addMessageHold(); try { //Don't send any message to the client. Each control will send what ever refresh messages are necessary.// internalViewRefreshAll(); }//try// finally { removeMessageHold(); }//finally// }//viewRefreshAll()// /* (non-Javadoc) * @see com.foundation.view.IView#viewSynchronizeAll() */ public final void viewSynchronizeAll() { verifyThread(); try { internalViewSynchronizeAll(); }//try// catch(Throwable e) { Debug.handle(e); }//catch// }//viewSynchronizeAll()// /* (non-Javadoc) * @see com.foundation.view.IView#viewRefreshAll() */ public final void viewRefresh() { verifyThread(); addMessageHold(); try { //Don't send any message to the client. Each control will send what ever refresh messages are necessary.// internalViewRefresh(); }//try// finally { removeMessageHold(); }//finally// }//viewRefresh()// /* (non-Javadoc) * @see com.foundation.view.IView#viewSynchronize() */ public final void viewSynchronize() { verifyThread(); try { sendRoundTripMessage(MESSAGE_VIEW_SYNCHRONIZE, null); }//try// catch(Throwable e) { Debug.handle(e); }//catch// }//viewSynchronize()// /** * Initializes this view and all its' contained components. */ protected void internalViewInitializeAll() { try { //Initialize this component.// internalViewInitialize(); }//try// catch(Throwable e) { Debug.log(e); Debug.halt(); }//catch// }//internalViewInitializeAll()// /** * Releases this view and all its' contained components. */ protected void internalViewReleaseAll() { try { //Release this component.// internalViewRelease(); }//try// catch(Throwable e) { Debug.log(e); }//catch// }//internalViewReleaseAll()// /** * Refreshes this view and all its' contained components. */ protected void internalViewRefreshAll() { try { //Refresh this component.// internalViewRefresh(); }//try// catch(Throwable e) { Debug.log(e); }//catch// }//internalViewRefreshAll()// /** * Initializes this component only. * @see #internalViewInitializeAll() */ protected void internalViewInitialize() { this.isInitialized = true; }//internalViewInitialize()// /** * Releases this component only. * @see #internalViewReleaseAll() */ protected void internalViewRelease() { }//internalViewRelease()// /** * Refreshes this component only. * @see #internalViewRefreshAll() */ protected void internalViewRefresh() { }//internalViewRefresh()// /** * Synchronize this component only. * @see #internalViewSynchronizeAll() */ protected final void internalViewSynchronize() { sendRoundTripMessage(MESSAGE_VIEW_SYNCHRONIZE, null); }//internalViewSynchronize()// /** * Synchronizes this view and all its' contained components. */ protected void internalViewSynchronizeAll() { sendRoundTripMessage(MESSAGE_VIEW_SYNCHRONIZE_ALL, null); }//internalViewSynchronizeAll()// /** * Gets the qualified class name for the client side class that mirrors the server side component. * @return The client side class name for this component. */ protected abstract String getClientClassName(); /** * Gets the controller for the view component. * @return The view's controller. */ public AbstractViewController getController() { return getContainer().getController(); }//getController()// /** * Notifies the view controller that it should validate. */ protected void postSynchronizeValidate() { getController().validate(); }//postSynchronizeValidate()// /* (non-Javadoc) * @see com.foundation.view.ISingleResourceAssociationChangeListener#getDecorationManager() */ public DecorationManager getDecorationManager() { return getController().getDecorationManager(); }//getDecorationManager()// /* (non-Javadoc) * @see com.foundation.view.ISingleResourceAssociationChangeListener#addDecoration(com.foundation.view.AbstractDecoration) */ public void addDecoration(AbstractDecoration decoration) { decorationMap.put(decoration, ++lastDecorationNumber); sendMessage(MESSAGE_ADD_DECORATION, decoration, null, lastDecorationNumber, -1); }//addDecoration()// /* (non-Javadoc) * @see com.foundation.view.ISingleResourceAssociationChangeListener#removeDecoration(com.foundation.view.AbstractDecoration) */ public void removeDecoration(AbstractDecoration decoration) { if(decoration != null) { sendMessage(MESSAGE_REMOVE_DECORATION, null, null, decorationMap.remove(decoration), -1); }//if// }//removeDecoration()// /* (non-Javadoc) * @see com.foundation.view.IMultiResourceAssociationChangeListener#addDecoration(com.foundation.view.ResourceAssociation, java.lang.Object, java.lang.Object, com.foundation.view.AbstractDecoration) */ public void addDecoration(ResourceAssociation association, Object row, Object data, AbstractDecoration decoration) { }//addDecoration()// /* (non-Javadoc) * @see com.foundation.view.IMultiResourceAssociationChangeListener#removeDecoration(com.foundation.view.ResourceAssociation, java.lang.Object, java.lang.Object, com.foundation.view.AbstractDecoration) */ public void removeDecoration(ResourceAssociation association, Object row, Object data, AbstractDecoration decoration) { }//removeDecoration()// }//AbstractComponent//