Initial commit from SVN.

This commit is contained in:
wcrisman
2014-05-30 10:31:51 -07:00
commit b45e56b890
1968 changed files with 370949 additions and 0 deletions

View File

@@ -0,0 +1,981 @@
/*
* 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.view.swt;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.*;
import com.common.debug.*;
import com.common.thread.*;
import com.common.util.*;
import com.foundation.controller.AbstractViewController;
import com.foundation.controller.DecorationManager;
import com.foundation.event.ListenerSet;
import com.foundation.event.EventSupport;
import com.foundation.event.IEventEmitter;
import com.foundation.view.*;
import com.foundation.view.resource.AbstractResourceService;
public abstract class AbstractComponent implements com.foundation.view.IAbstractComponent, com.foundation.event.IEventHandler, IInternalAbstractComponent, IResourceHolderComponent, IDecorationContainer {
public static final int LINK_TARGET_SYNCHRONIZE_ALL = 1;
public static final int LINK_TARGET_SYNCHRONIZE = 2;
public static final int LAST_LINK_TARGET = 2;
private Widget swtWidget = null;
/** A set of listeners to this component. */
private ListenerSet listeners = null;
/** 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 parent associated with this component. Almost all components will have a parent. */
private IAbstractContainer container = null;
/** The view context retreived from the view controller. If this is null then the context should be retreived from the container. */
private IViewContext viewContext = null;
/** A mapping of decoration display objects by the decoration. */
private IHashMap decorationByDataMap = new LiteHashMap(5);
/** Suspends layouts and packing while setting up the view. */
private boolean suspendLayouts = false;
/**
* A simple task interface for the Scheduler.
*/
public abstract static class Task implements Runnable {
public Task() {
}//Task()//
public final void run() {
execute();
}//run()//
public abstract void execute();
}//Task//
public class Linkage {
/** The collection of registered links. */
private LiteList links = new LiteList(2, 8);
/**
* Linkage constructor.
*/
public Linkage() {
super();
}//Linkage()//
/**
* Adds a registered link to this linkage.
* @param link The link to be added.
*/
public void add(LinkData link) {
links.add(link);
}//add()//
/**
* Invokes the links with the given data.
* @param data The data whose type is link definition dependant.
*/
public void invoke(Object data) {
for(int index = 0; index < links.getSize(); index++) {
LinkData next = (LinkData) links.get(index);
Object value = data;
//If we were given 'fixed' data to use as the parameter then use it.//
if(next.getData() != null) {
value = next.getData();
}//if//
else if(next.isBoolean()) {
boolean booleanData;
if(value == null) {
booleanData = next.nullValue();
}//if//
else if(!(value instanceof Boolean)) {
booleanData = !next.nullValue();
}//else if//
else {
booleanData = ((Boolean) value).booleanValue();
}//else//
if(next.invertLogic()) {
booleanData = !booleanData;
}//if//
value = booleanData ? Boolean.TRUE : Boolean.FALSE;
}//else if//
((AbstractComponent) next.getComponent()).internalOnLinkInvoked(next.getTarget(), value);
}//for//
}//invoke()//
}//Linkage//
/**
* AbstractComponent default constructor.
*/
protected AbstractComponent() {
}//AbstractComponent()//
/**
* AbstractComponent constructor.
* @param parent The component's parent which should only be null for the outer most container.
* @param style The component style.
*/
protected AbstractComponent(IAbstractContainer parent, int style) {
this(parent, null, style, null);
}//AbstractComponent()//
/**
* AbstractComponent constructor.
* @param parent The component's parent which should only be null for the outer most container.
* @param viewContext The context under which this view component operates. For all but the outer most control this can be null.
* @param style The component style.
* @param data The optional data passed to the initializeControl(int, java.lang.Object) method.
*/
protected AbstractComponent(IAbstractContainer parent, IViewContext viewContext, int style, Object data) {
this.container = parent;
this.viewContext = viewContext;
initializeControl(style, data);
//If the container has already been initialized then force the parent to re-layout so that this component will appear.//
if(getContainer() instanceof Container) {
Container container = (Container) getContainer();
if(container.isInitialized()) {
container.getSwtComposite().layout(true, true);
}//if//
}//if//
}//AbstractComponent()//
/**
* Suspends all layouts and packing while the view is getting setup.
*/
public void suspendLayouts() {
Shell shell = getShell();
suspendLayouts = true;
if(shell != null) {
shell.setLayoutDeferred(true);
}//if//
}//suspendLayouts()//
/**
* Resumes processing of requests to layout or pack components.
*/
public void resumeLayouts() {
Shell shell = getShell();
suspendLayouts = false;
if(shell != null) {
shell.setLayoutDeferred(false);
}//if//
}//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() {
IAbstractContainer container = getContainer();
return !suspendLayouts && container != null ? container.isSuspendingLayouts() : suspendLayouts;
}//isSuspendingLayouts()//
/**
* Can be overloaded to provide custom packing behavior for a component.
*/
protected void internalPack() {
//Does nothing.//
}//internalPack()//
/**
* Can be overloaded to provide custom layout behavior for a component.
*/
protected void internalLayout() {
//Does nothing.//
}//internalLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IInternalAbstractComponent#getSwtWidget()
*/
public Widget getSwtWidget() {
return swtWidget;
}//getSwtWidget()//
/**
* Gets a shell since the widget reference doesn't contain a reference to the UI shell.
* @return The shell most closely associated with the component, or null if one could not be obtained.
*/
public abstract Shell getShell();
/**
* Sets the widget encapsulated by this component.
* @param swtWidget The encapsulated widget, or null if this component does not have a viewable element.
*/
protected void setSwtWidget(Widget swtWidget) {
this.swtWidget = swtWidget;
}//setSwtWidget()//
/**
* Sets the menu for the component.
* @param menu The menu optionally used by the component.
*/
public void setMenu(Menu menu) {
//Does nothing.//
}//setMenu()//
/**
* Creates or reuses an image given the image data.
* <p>Warning: A single call must be made to destroyImage(..) for each call to this method.</p>
* @param image The data from which the image will be derived.
* @return The swt image resource.
*/
public Image createImage(JefImage image) {
Image result = null;
if(image != null) {
Widget widget = getSwtWidget() != null ? getSwtWidget() : ((IAbstractSwtContainer) getContainer()).getSwtWidget();
result = SwtResourceManager.getSingleton().createImage(widget.getDisplay(), image);
}//if//
return result;
}//createImage()//
/**
* Creates or reuses an image given the image data.
* <p>Warning: A single call must be made to destroyImage(..) for each call to this method.</p>
* @param images The data from which the image will be derived.
* @return The swt images.
*/
public Image[] createImages(JefImage[] images) {
Image[] result = null;
if(images != null) {
Widget widget = getSwtWidget() != null ? getSwtWidget() : ((IAbstractSwtContainer) getContainer()).getSwtWidget();
result = SwtResourceManager.getSingleton().createImages(widget.getDisplay(), images);
}//if//
return result;
}//createImages()//
/**
* Destroys an image resource, or decrements the useage count.
* @param image The image to destroy.
*/
public void destroyImage(Image image) {
if(image != null) {
SwtResourceManager.getSingleton().destroyImage(image);
}//if//
}//destroyImage()//
/**
* Destroys an image resource, or decrements the useage count.
* @param image The image to destroy.
*/
protected void destroyImage(JefImage image) {
if(image != null) {
SwtResourceManager.getSingleton().destroyImage(image);
}//if//
}//destroyImage()//
/**
* Destroys an images resource, or decrements the useage count.
* @param images The images to destroy.
*/
public void destroyImages(Image[] images) {
if(images != null) {
SwtResourceManager.getSingleton().destroyImages(images);
}//if//
}//destroyImages()//
/**
* Destroys an image resource, or decrements the useage count.
* @param images The images to destroy.
*/
protected void destroyImages(JefImage[] images) {
if(images != null) {
SwtResourceManager.getSingleton().destroyImages(images);
}//if//
}//destroyImages()//
/**
* Creates or reuses an color given the color data.
* <p>Warning: A single call must be made to destroyColor(..) for each call to this method.</p>
* @param colorData The data from which the color will be derrived.
* @return The swt color resource.
*/
protected Color createColor(JefColor color) {
Color result = null;
if(color != null) {
Widget widget = getSwtWidget() != null ? getSwtWidget() : ((IAbstractSwtContainer) getContainer()).getSwtWidget();
result = SwtResourceManager.getSingleton().createColor(widget.getDisplay(), color);
}//if//
return result;
}//createColor()//
/**
* Destroys an color resource, or decrements the useage count.
* @param color The color to destroy.
*/
protected void destroyColor(Color color) {
if(color != null) {
SwtResourceManager.getSingleton().destroyColor(color);
}//if//
}//destroyColor()//
/**
* Destroys an color resource, or decrements the useage count.
* @param color The color to destroy.
*/
protected void destroyColor(JefColor color) {
if(color != null) {
SwtResourceManager.getSingleton().destroyColor(color);
}//if//
}//destroyColor()//
/**
* Creates or reuses an font given the font data.
* <p>Warning: A single call must be made to destroyFont(..) for each call to this method.</p>
* @param fontData The data from which the font will be derrived.
* @return The swt font resource.
*/
protected Font createFont(JefFont[] font) {
Font result = null;
if(font != null) {
Widget widget = getSwtWidget() != null ? getSwtWidget() : ((IAbstractSwtContainer) getContainer()).getSwtWidget();
result = SwtResourceManager.getSingleton().createFont(widget.getDisplay(), font);
}//if//
return result;
}//createFont()//
/**
* Destroys an font resource, or decrements the useage count.
* @param font The font to destroy.
*/
protected void destroyFont(Font font) {
if(font != null) {
SwtResourceManager.getSingleton().destroyFont(font);
}//if//
}//destroyFont()//
/**
* Destroys an font resource, or decrements the useage count.
* @param font The font to destroy.
*/
protected void destroyFont(JefFont[] font) {
if(font != null) {
SwtResourceManager.getSingleton().destroyFont(font);
}//if//
}//destroyFont()//
/**
* Notifies the view controller that it should validate.
*/
protected void postSynchronizeValidate() {
getController().validate();
}//postSynchronizeValidate()//
/**
* Registers a listener that would like to receive component events.
* <p>Warning: Each registration should also result in exactly one unregistration.</p>
* @param listener The listener to be registered.
*/
public void registerListener(Object listener) {
if(listeners == null) {
listeners = new ListenerSet(10);
}//if//
listeners.add(listener);
}//registerListener()//
/**
* Unregisters a listener that was previously registered to receive component events.
* @param listener The listener to be unregistered.
*/
public void unregisterListener(Object listener) {
if(listeners != null) {
listeners.remove(listener);
}//if//
}//unregisterListener()//
/**
* Gets an iterator over the listeners conforming to the given super class/interface.
* @param listenerClass The class or interface which the listeners must implement/extend.
* @return The non-null iterator over the listeners.
*/
protected IIterator getListeners(Class listenerClass) {
return listeners != null ? listeners.iterator(listenerClass) : EmptyIterator.getSingleton();
}//getListeners()//
/* (non-Javadoc)
* @see com.common.event.IEventHandler#evaluate(com.common.event.IEventEmitter, int, java.lang.Object[], int)
*/
public final void evaluate(IEventEmitter eventEmitter, int eventNumber, Object[] arguments, int flags) {
if(EventSupport.isStandardEvent(flags)) {
verifyThread();
internalEvaluate(eventEmitter, eventNumber, arguments);
}//if//
}//evaluate()//
/* (non-Javadoc)
* @see com.common.event.IHandler#evaluate(int, Object[], int)
*/
public final void evaluate(int eventNumber, Object[] arguments, int flags) {
Debug.log("Error: evaluate(int, Object[]) should never be called.");
}//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()//
/**
* Verifies that the calling thread is allowed access to the view components.
* <p>Note: This is really a debug only operation and should be turned off for production applications.</p>
*/
public void verifyThread() {
if(!getEventLoop().isRequestThread()) {
Debug.log(new RuntimeException("Error: Invalid thread."));
}//if//
}//verifyThread()//
/**
* 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()//
/**
* 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 event loop for this component.
* @return The object that should be notified when a request is made. All requests must be routed through the handler so that they are handled by the event thread.
*/
protected IViewRequestHandler getEventLoop() {
return getViewContext().getRequestHandler();
}//getEventLoop()//
/**
* Gets the display associated with the view system.
* @return The SWT view system's display object.
*/
protected Display getDisplay() {
return ((ISwtViewRequestHandler) getViewContext().getRequestHandler()).getDisplay();
}//getDisplay()//
/* (non-Javadoc)
* @see com.foundation.view.IView#getViewContext()
*/
public IViewContext getViewContext() {
return internalGetViewContext();
}//getViewContext()//
/**
* Gets the view context for the control.
* @return The component's view context.
*/
protected IViewContext internalGetViewContext() {
return viewContext == null ? ((AbstractComponent) getContainer()).internalGetViewContext() : viewContext;
}//internalGetViewContext()//
/* (non-Javadoc)
* @see com.foundation.view.IView#viewInitializeAll()
*/
public void viewInitializeAll() {
verifyThread();
internalViewInitializeAll();
internalViewRefreshAll();
internalInitializationComplete();
}//viewInitializeAll()//
/* (non-Javadoc)
* @see com.foundation.view.IView#viewRefreshAll()
*/
public void viewRefreshAll() {
verifyThread();
internalViewRefreshAll();
}//viewRefreshAll()//
/* (non-Javadoc)
* @see com.foundation.view.IView#viewSynchronizeAll()
*/
public void viewSynchronizeAll() {
verifyThread();
internalViewSynchronizeAll();
}//viewSynchronizeAll()//
/* (non-Javadoc)
* @see com.foundation.view.IView#viewReleaseAll()
*/
public void viewReleaseAll() {
// Shell shell;
verifyThread();
// shell = getShell();
// if(shell != null) {
// shell.setLayoutDeferred(true);
// }//if//
try {
if(getSwtWidget() != null && !getSwtWidget().isDisposed()) {
getSwtWidget().dispose();
setSwtWidget(null);
internalViewReleaseAll();
}//if//
}//try//
finally {
// if(shell != null && !shell.isDisposed()) {
// shell.setLayoutDeferred(false);
// }//if//
}//finally//
}//viewReleaseAll()//
/* (non-Javadoc)
* @see com.foundation.view.IViewComponent#viewRefresh()
*/
public void viewRefresh() {
verifyThread();
internalViewRefresh();
}//viewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.IViewComponent#viewSynchronize()
*/
public void viewSynchronize() {
verifyThread();
internalViewSynchronize();
}//viewSynchronize()//
/**
* Initializes this view and all its' contained components.
*/
public 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.
*/
public void internalViewReleaseAll() {
try {
//Release this component.//
internalViewRelease();
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}//internalViewReleaseAll()//
/**
* Refreshes this view and all its' contained components.
*/
public void internalViewRefreshAll() {
try {
//Refresh this component.//
internalViewRefresh();
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}//internalViewRefreshAll()//
/**
* Synchronizes this view and all its' contained components.
*/
public void internalViewSynchronizeAll() {
try {
//Synchronize this component.//
internalViewSynchronize();
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}//internalViewSynchronizeAll()//
/**
* 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 void internalViewSynchronize() {
}//internalViewSynchronize()//
/**
* Called after initializing and refreshing the view.
* Note that this will only be called on the parent component for the view or partial view.
*/
protected void internalInitializationComplete() {
//Does nothing.//
}//internalInitializationComplete()//
/**
* Initializes the SWT control. This must be performed on the view system thread. Additional data required for initializing the control must be saved as attributes of the class so that this method can access them.
* @param style The control's styles.
* @param data The optional data passed via the constructor.
*/
protected abstract void initializeControl(int style, Object data);
/**
* Gets the controller for the view component.
* @return The view's controller.
*/
public AbstractViewController getController() {
return getContainer().getController();
}//getController()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractComponent#getContainer()
*/
public IAbstractContainer getContainer() {
return container;
}//getContainer()//
/**
* Gets the abstract swt container.
* @return The container for this component.
*/
public IAbstractSwtContainer getSwtContainer() {
return (IAbstractSwtContainer) container;
}//getSwtContainer()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractComponent#getResourceService()
*/
public AbstractResourceService getResourceService() {
return getContainer().getResourceService();
}//getResourceService()//
/* (non-Javadoc)
* @see com.foundation.view.IAttributeAssociationChangeListener#onValueChanged(com.foundation.view.IAttributeAssociation)
*/
public final void onValueChanged(IAttributeAssociation attributeAssociation) {
verifyThread();
internalOnValueChanged(attributeAssociation);
}//onValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.IMultiResourceAssociationChangeListener#onValueChanged(com.foundation.view.ResourceAssociation, java.lang.Object, java.lang.Object, boolean)
*/
public 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#onValueChanged(com.foundation.view.ResourceAssociation, int)
*/
public 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.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.IResourceHolderComponent#resourceHolderChanged(com.foundation.view.ResourceHolder, java.lang.Object, java.lang.Object, int)
*/
public void resourceHolderChanged(com.foundation.view.AbstractResourceHolder resourceHolder, Object oldValue, Object newValue, int flags) {
verifyThread();
internalResourceHolderChanged((ResourceHolder) resourceHolder, oldValue, newValue, flags);
}//resourceHolderChanged()//
/* (non-Javadoc)
* @see com.foundation.view.IResourceHolderComponent#resourceHolderChanged(com.foundation.view.AbstractMultiResourceHolder, com.common.util.IHashSet, java.lang.Object, java.lang.Object)
*/
public void resourceHolderChanged(AbstractMultiResourceHolder resourceHolder, IHashSet rows, Object oldValue, Object newValue) {
verifyThread();
internalResourceHolderChanged((MultiResourceHolder) resourceHolder, (IHashSet) rows, oldValue, newValue);
}//resourceHolderChanged()//
/* (non-Javadoc)
* @see com.foundation.view.IResourceHolderComponent#resourceHolderChanged(com.foundation.view.AbstractMultiResourceHolder, java.lang.Object, java.lang.Object, java.lang.Object)
*/
public void resourceHolderChanged(AbstractMultiResourceHolder resourceHolder, Object row, Object oldValue, Object newValue) {
verifyThread();
internalResourceHolderChanged((MultiResourceHolder) resourceHolder, (Object) row, oldValue, newValue);
}//resourceHolderChanged()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractComponent#onEventFired(com.foundation.view.IEventAssociation, java.lang.Object[])
*/
public void onEventFired(IEventAssociation eventAssociation, Object[] eventArguments) {
verifyThread();
internalOnEventFired(eventAssociation, eventArguments);
}//onEventFired()//
/**
* Called when a resource holder's value has been altered.
* Subclasses must override this to handle change to resource holders they define.
* @param resourceHolder The resource holder whose value changed.
* @param oldValue The old value.
* @param newValue The new value.
*/
protected void internalResourceHolderChanged(ResourceHolder resourceHolder, Object oldValue, Object newValue, int flags) {
Debug.log(new RuntimeException("Error: Unhandled resource holder change event found. ResourceHolder: " + resourceHolder));
}//internalResourceHolderChanged()//
/**
* Called by a resource holder when the held value changes either due to a new value being set, or due to a resource being changed.
* @param resourceHolder The resource holder that is sending the notification.
* @param row The row whose value has changed.
* @param oldValue The old value for the resource.
* @param newValue The new value for the resource.
*/
protected void internalResourceHolderChanged(MultiResourceHolder resourceHolder, Object row, Object oldValue, Object newValue) {
Debug.log(new RuntimeException("Error: Unhandled resource holder change event found. ResourceHolder: " + resourceHolder));
}//internalResourceHolderChanged()//
/**
* Called by a resource holder when the held value changes either due to a new value being set, or due to a resource being changed.
* @param resourceHolder The resource holder that is sending the notification.
* @param rows The rows whose values have changed.
* @param oldValue The old value for the resource.
* @param newValue The new value for the resource.
*/
protected void internalResourceHolderChanged(MultiResourceHolder resourceHolder, IHashSet rows, Object oldValue, Object newValue) {
Debug.log(new RuntimeException("Error: Unhandled resource holder change event found. ResourceHolder: " + resourceHolder));
}//internalResourceHolderChanged()//
/**
* 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.
* <p>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.</p>
* @param resourceAssociation The resource association used to register with the resource.
* @param isUpdate TODO
*/
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.
* <p>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.</p>
* @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 association.
* @param isUpdate TODO
*/
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.
* <p>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.</p>
* @param resourceAssociation The resource association used to register with the resource.
* @param alteredItem The item whose value has been altered.
* @param data TODO
*/
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.
* <p>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.</p>
* @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.
* <p>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.</p>
* @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.
* <p>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.</p>
* @param resourceAssociation The resource association used to register with the resource.
* @param alteredItem The item whose value has been altered.
* @param data The data value passed when the item was registered with the resource association.
* @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()//
/**
* Called on the view thread when another component has linked to this component and invoked the link.
* @param linkTarget The link target number which identifies the appropriate action.
* @param data The data associated with the invocation of the linkage.
*/
protected void internalOnLinkInvoked(int linkTarget, Object data) {
switch(linkTarget) {
case LINK_TARGET_SYNCHRONIZE: {
internalViewSynchronize();
break;
}//case//
case LINK_TARGET_SYNCHRONIZE_ALL: {
internalViewSynchronizeAll();
break;
}//case//
default: {
Debug.log("Error: Unexpected (unhandled) link found. Link Number: " + linkTarget + " in component type: " + getClass().getName());
break;
}//case//
}//switch//
}//internalOnLinkInvoked()//
/**
* Removes a task from the task scheduler so that it is not run.
* @param task The task to be removed.
*/
protected void removeTask(Task task) {
ActiveScheduler.getSingleton().remove(task);
}//removeTask()//
/**
* Adds a task to the task scheduler so that it will run after a short delay.
* @param task The task to be run.
* @param delay The delay in milliseconds to wait before running the task.
*/
protected void addTask(Task task, long delay) {
ActiveScheduler.getSingleton().add(task, delay);
}//addTask()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#addMessageHold()
*/
public void addMessageHold() {
}//addMessageHold()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#removeMessageHold()
*/
public void removeMessageHold() {
}//removeMessageHold()//
/* (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) {
//Overridden by subclasses that use MultiResourceHolder's.//
}//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) {
//Overridden by subclasses that use MultiResourceHolder's.//
}//removeDecoration()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#addDecoration(com.foundation.view.AbstractDecoration)
*/
public void addDecoration(AbstractDecoration decoration) {
if(decoration instanceof ControlDecoration) {
addDecoration((ControlDecoration) decoration);
}//if//
}//addDecoration()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#removeDecoration(com.foundation.view.AbstractDecoration)
*/
public void removeDecoration(AbstractDecoration decoration) {
if(decoration instanceof ControlDecoration) {
removeDecoration((ControlDecoration) decoration);
}//if//
}//removeDecoration()//
/**
* Adds a decoration to the component.
* @param decoration The decoration data.
* @return The control for the decoration.
*/
public Control addDecoration(ControlDecoration decoration) {
Control decorationControl = null;
if(decoration != null) {
decorationControl = createDecorationControl((ControlDecoration) decoration);
decorationByDataMap.put(decoration, decorationControl);
decorationControl.moveAbove((Control) getSwtWidget());
((Control) getSwtWidget()).getParent().layout(true, true);
}//if//
return decorationControl;
}//addDecoration()//
/**
* Removes a decoration from the component.
* @param decoration The decoration data.
*/
public void removeDecoration(ControlDecoration decoration) {
Control decorationControl = (Control) decorationByDataMap.remove(decoration);
if(decorationControl != null) {
decorationControl.dispose();
}//if//
}//removeDecoration()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#getDecorationManager()
*/
public DecorationManager getDecorationManager() {
return getController().getDecorationManager();
}//getDecorationManager()//
/**
* Creates the decoration for the given metadata.
* @param decorationMetadata The decoration metadata.
* @return The decoration.
*/
protected Control createDecorationControl(ControlDecoration decorationMetadata) {
return new Decoration(this, decorationMetadata);
}//createDecorationControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IDecorationContainer#getDecorationParent()
*/
public Composite getDecorationParent() {
return ((Control) getSwtWidget()).getParent();
//return ((Container) getContainer()).getSwtComposite();
}//getDecorationParent()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IDecorationContainer#getDecorationPeer()
*/
public Control getDecorationPeer() {
return (Control) getSwtWidget();
}//getDecorationPeer()//
}//AbstractComponent//

View File

@@ -0,0 +1,529 @@
/*
* 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.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import com.common.comparison.Comparator;
import com.common.debug.*;
import com.common.thread.IRunnable;
import com.foundation.view.*;
import com.foundation.view.resource.ResourceReference;
import com.foundation.view.swt.util.SwtUtilities;
public class Button extends Component implements SelectionListener {
public static final int STYLE_ARROW = SWT.ARROW;
public static final int STYLE_CHECK = SWT.CHECK;
public static final int STYLE_PUSH = SWT.PUSH;
public static final int STYLE_RADIO = SWT.RADIO;
public static final int STYLE_TOGGLE = SWT.TOGGLE;
public static final int STYLE_FLAT = SWT.FLAT;
public static final int STYLE_LEFT = SWT.LEFT;
public static final int STYLE_RIGHT = SWT.RIGHT;
public static final int STYLE_CENTER = SWT.CENTER;
public static final int STYLE_UP = SWT.UP;
public static final int STYLE_DOWN = SWT.DOWN;
public static final int LINK_TARGET_SELECTION = Component.LAST_LINK_TARGET + 1;
public static final int LINK_TARGET_IMAGE = Component.LAST_LINK_TARGET + 2;
public static final int LINK_TARGET_TEXT = Component.LAST_LINK_TARGET + 3;
public static final int LAST_LINK_TARGET = Component.LAST_LINK_TARGET + 3;
/** Called when the button is pressed (only used for push buttons). */
private IMethodAssociation selectionMethod = null;
/** The button's selection state resource. */
private SingleResourceAssociation selection = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_OBJECT, true, Boolean.FALSE);
/** The button's text resource. */
private SingleResourceAssociation text = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_TEXT, false, "");
/** The button's image resource. */
private SingleResourceAssociation image = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_IMAGE, false, null);
/** The linkage for the selection. */
private Linkage selectionLinkage = new Linkage();
/** The optional object that represents a selection of this button. Used for radio buttons only - to allow them to work on the same attribute. Never used for the linkages. */
private Object selectionData = null;
/** Whether the selection state is auto synchronized. */
private boolean autoSynchronizeSelection = false;
/** The delay to be used when auto synchronizing changes to the text. */
private long autoSynchronizeSelectionDelay = 500;
/** The task that auto synchronizes the selection after a short delay. */
private Task autoSynchronizeSelectionTask = null;
/** Whether this is a stateful button. */
private final boolean isStateful;
/** Whether this is a radio button. */
private final boolean isRadio;
/** A holder for the value of the text. */
private ResourceHolder textHolder = new ResourceHolder(this);
/** A holder for the value of the image. */
private ResourceHolder imageHolder = new ResourceHolder(this);
/** Whether the validation code in the view controller should be executed after synchronizing the state. */
private boolean autoValidate = false;
/**
* Button constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_ARROW
* @see #STYLE_CHECK
* @see #STYLE_PUSH
* @see #STYLE_RADIO
* @see #STYLE_TOGGLE
* @see #STYLE_FLAT
* @see #STYLE_LEFT
* @see #STYLE_RIGHT
* @see #STYLE_CENTER
* @see #STYLE_UP
* @see #STYLE_DOWN
*/
public Button(Container parent, String name, int style) {
super(parent, name, style);
isRadio = (style & STYLE_RADIO) > 0;
isStateful = isRadio || ((style & STYLE_TOGGLE) > 0) || ((style & STYLE_CHECK) > 0);
}//Button()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.Button(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT button that represents this button.
* @return The SWT button providing visualization for this button.
*/
public org.eclipse.swt.widgets.Button getSwtButton() {
return (org.eclipse.swt.widgets.Button) getSwtControl();
}//getSwtButton()//
/**
* Gets the optional selection data for the radio button (radio only).
* @return The data to use to determine whether this button is selected (within the group of radio buttons) and to pass to the model when selected.
*/
public Object getSelectionData() {
verifyThread();
return selectionData;
}//getSelectionData()//
/**
* Sets the optional selection data for the radio button (radio only).
* @param selectionData The data to use to determine whether this button is selected (within the group of radio buttons) and to pass to the model when selected.
*/
public void setSelectionData(Object selectionData) {
verifyThread();
if(isRadio && !isInitialized()) {
this.selectionData = selectionData;
}//if//
}//setSelectionData()//
/**
* Gets the component selection state.
* @return Whether the component is in the selected state.
*/
public Boolean getIsSelected() {
verifyThread();
return (Boolean) selection.getValue();
}//getIsSelected()//
/**
* Sets the component default selection state.
* @param isSelected Whether the component is in the selected state.
*/
public void setIsSelected(Boolean isSelected) {
verifyThread();
if(isStateful) {
selection.setDefaultValue(isSelected);
}//if//
}//setIsSelected()//
/**
* Sets an association container used to access the text.
* @param container The text association metadata.
*/
public void setTextAssociation(SingleAssociationContainer container) {
verifyThread();
this.text.setAssociations(container);
}//setTextAssociation()//
/**
* Sets an association container used to access the image.
* @param container The image association metadata.
*/
public void setImageAssociation(SingleAssociationContainer container) {
verifyThread();
this.image.setAssociations(container);
}//setImageAssociation()//
/**
* Sets an association container used to access the selection.
* @param container The selection association metadata.
*/
public void setSelectionAssociation(SingleAssociationContainer container) {
verifyThread();
this.selection.setAssociations(container);
}//setSelectionAssociation()//
/**
* Adds a link for the selection.
* @param link The local linkage for the selection.
*/
public void addSelectionLink(LinkData link) {
selectionLinkage.add(link);
}//addSelectionLink()//
/**
* Sets the selection method called when the button is pressed (intended only for push buttons).
* @param selectionMethod The method called when the button is pressed.
*/
public void setSelectionMethod(IMethodAssociation selectionMethod) {
verifyThread();
if(!isStateful) {
this.selectionMethod = selectionMethod;
}//if//
}//setSelectionMethod()//
/**
* Sets the component text.
* @param text The text that will appear in the component.
*/
public void setText(String text) {
verifyThread();
this.text.setDefaultValue(text);
}//setText()//
/**
* Sets the component's default text resource.
* @param text The text to be displayed by this component.
*/
public void setText(ResourceReference text) {
verifyThread();
this.text.setDefaultValue(text);
}//setText()//
/**
* Sets the component image.
* @param image The image to be displayed by the component.
*/
public void setImage(JefImage image) {
verifyThread();
this.image.setDefaultValue(image);
}//setImage()//
/**
* Sets the component's default image resource.
* @param image The image to be displayed by this component.
*/
public void setImage(ResourceReference image) {
verifyThread();
this.image.setDefaultValue(image);
}//setImage()//
/**
* Sets whether validate routine is called after a synchronize.
* @param autoValidate Whether the validation code in the view controller will be called after synchronizing the state.
*/
public void setAutoValidate(boolean autoValidate) {
this.autoValidate = autoValidate;
}//setAutoValidate()//
/**
* Sets whether the control auto synchronizes the selected state of the button.
* @param autoSynchronizeSelection Whether the button state is automatically synchronized.
*/
public void setAutoSynchronizeSelection(boolean autoSynchronizeSelection) {
verifyThread();
if(isStateful) {
this.autoSynchronizeSelection = autoSynchronizeSelection;
}//if//
}//setAutoSynchronizeSelection()//
/**
* Sets the delay for the auto synchronize selection.
* @param autoSynchronizeSelectionDelay The delay in terms of milliseconds between the value of zero and ten thousand. A zero value has no delay.
*/
public void setAutoSynchronizeSelectionDelay(long autoSynchronizeSelectionDelay) {
verifyThread();
if(autoSynchronizeSelectionDelay < 0) {
autoSynchronizeSelectionDelay = 0;
}//if//
else if(autoSynchronizeSelectionDelay > 10000) {
autoSynchronizeSelectionDelay = 10000;
}//else if//
this.autoSynchronizeSelectionDelay = autoSynchronizeSelectionDelay;
}//setAutoSynchronizeSelectionDelay()//
/**
* Sets whether the client views should be disabled while a selection event is processed.
* @param blockOnSelection Whether push style buttons stop user input while processing the selection event.
*/
public void setBlockOnSelection(boolean blockOnSelection) {
verifyThread();
//Does nothing. For thick clients this is always true.//
}//setBlockOnSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
getSwtButton().addSelectionListener(this);
text.initialize();
image.initialize();
selection.initialize();
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
destroyImage((JefImage) imageHolder.getValue());
if(!getSwtButton().isDisposed()) {
getSwtButton().removeSelectionListener(this);
}//if//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
autoSynchronizeSelectionTask = null;
}//if//
}//synchronized//
text.release();
image.release();
selection.release();
textHolder.release();
imageHolder.release();
super.internalViewRelease();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalViewRefreshSelection();
internalViewRefreshText();
internalViewRefreshImage();
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
super.internalViewSynchronize();
if(isStateful) {
if(!autoSynchronizeSelection) {
boolean isSelected = getSwtButton().getSelection();
if(isRadio && isSelected) {
//Only positive values are sent for radio buttons.//
selection.setValue(selectionData != null ? selectionData : Boolean.TRUE);
}//if//
else if(!isRadio) {
selection.setValue(isSelected ? Boolean.TRUE : Boolean.FALSE);
}//else if//
}//if//
else {
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
autoSynchronizeSelectionTask.execute();
}//if//
}//synchronized//
}//else//
}//if//
}//internalViewSynchronize()//
/**
* Refreshes the button selection.
*/
protected void internalViewRefreshSelection() {
if((isStateful) && (selection.refresh())) {
Object value = selection.getValue();
Boolean isSelected;
if(value instanceof Boolean) {
isSelected = (Boolean) value;
}//if//
else if(selectionData != null) {
isSelected = Comparator.equals(selectionData, value) ? Boolean.TRUE : Boolean.FALSE;
}//else if//
else {
isSelected = value != null ? Boolean.TRUE : Boolean.FALSE;
}//else//
if(getSwtButton().getSelection() != isSelected.booleanValue()) {
getSwtButton().setSelection(isSelected.booleanValue());
selectionLinkage.invoke(isSelected);
}//if//
}//if//
}//internalViewRefreshSelection()//
/**
* Refreshes the button image.
*/
protected void internalViewRefreshImage() {
if(image.refresh()) {
imageHolder.setValue(image.getValue());
}//if//
}//internalViewRefreshImage()//
/**
* Refreshes the button text.
*/
protected void internalViewRefreshText() {
if(text.refresh()) {
textHolder.setValue(text.getValue());
}//if//
}//internalViewRefreshText()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent e) {
//TODO: When is this called?//
Debug.log("Default Selected Called <Why?>");
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent e) {
selectionChanged(getSwtButton().getSelection());
}//widgetSelected()//
/**
* Called when the selection is changed in the view control.
* @param isSelected Whether the control is selected (stateful controls only).
*/
protected void selectionChanged(final boolean isSelected) {
try {
if((selectionMethod != null) || (autoSynchronizeSelection)) {
if((selectionMethod == null) && (autoSynchronizeSelectionDelay > 0)) {
//Ignore not-selected radio buttons - only selections count in radio buttons.//
if(!isRadio || isSelected) {
//Start a task to send the text to the server after a short delay. This will reduce the overhead of auto synchronizing the selection.//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
}//if//
autoSynchronizeSelectionTask = new Task() {
public void execute() {
//Make sure that this task is still valid and is not being superceeded.//
synchronized(Button.this) {
if(autoSynchronizeSelectionTask == this) {
//Cleanup after the task.//
autoSynchronizeSelectionTask = null;
getEventLoop().executeAsync(new IRunnable() {
public Object run() {
if(isRadio) {
//Only positive values are sent for radio buttons.//
selection.setValue(selectionData != null ? selectionData : Boolean.TRUE);
}//if//
else {
selection.setValue(isSelected ? Boolean.TRUE : Boolean.FALSE);
}//else//
if(autoValidate) {
postSynchronizeValidate();
}//if//
return null;
}//run()//
});
}//if//
}//synchronized//
}//run()//
};
addTask(autoSynchronizeSelectionTask, autoSynchronizeSelectionDelay);
}//synchronized//
}//if//
}//if//
else {
if(selectionMethod != null) {
selectionMethod.invoke(null, true);
}//if//
else {
if(isRadio && isSelected) {
//Only positive values are sent for radio buttons.//
selection.setValue(selectionData != null ? selectionData : Boolean.TRUE);
}//if//
else if(!isRadio) {
selection.setValue(isSelected ? Boolean.TRUE : Boolean.FALSE);
}//else if//
}//else//
if(autoValidate) {
postSynchronizeValidate();
}//if//
}//else//
}//if//
selectionLinkage.invoke(isStateful ? isSelected ? Boolean.TRUE : Boolean.FALSE : null);
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}//selectionChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalResourceHolderChanged(com.foundation.view.swt.ResourceHolder, java.lang.Object, java.lang.Object)
*/
protected void internalResourceHolderChanged(ResourceHolder resource, Object oldValue, Object newValue, int flags) {
if(resource == textHolder) {
getSwtButton().setText((String) newValue);
resize();
}//if//
else if(resource == imageHolder) {
destroyImage(getSwtButton().getImage());
getSwtButton().setImage(createImage((JefImage) image.getValue()));
resize();
}//else if//
else {
super.internalResourceHolderChanged(resource, oldValue, newValue, flags);
}//else//
}//internalOnAssociationChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == text) {
internalViewRefreshText();
}//if//
else if(resourceAssociation == image) {
internalViewRefreshImage();
}//else if//
else if(resourceAssociation == selection) {
internalViewRefreshSelection();
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnLinkInvoked(int, java.lang.Object)
*/
protected void internalOnLinkInvoked(int linkTarget, Object data) {
switch(linkTarget) {
case LINK_TARGET_SELECTION: {
boolean isSelected = data instanceof Boolean ? ((Boolean) data).booleanValue() : false;
if((isStateful) && (isSelected != getSwtButton().getSelection())) {
getSwtButton().setSelection(isSelected);
selectionChanged(isSelected);
}//if//
else {
selectionChanged(true);
}//else//
break;
}//case//
case LINK_TARGET_IMAGE: {
if(getSwtButton().getImage() != null) {
getSwtButton().getImage().dispose();
}//if//
getSwtButton().setImage(data instanceof JefImage ? SwtUtilities.getImage(getSwtButton().getDisplay(), (JefImage) data) : null);
resize();
break;
}//case//
case LINK_TARGET_TEXT: {
getSwtButton().setText(data instanceof String ? (String) data : "");
resize();
break;
}//case//
default: {
super.internalOnLinkInvoked(linkTarget, data);
break;
}//default//
}//switch//
}//internalOnLinkInvoked()//
}//Button//

View File

@@ -0,0 +1,150 @@
/*
* Copyright (c) 2007,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.foundation.view.MultiResourceAssociation;
import com.foundation.view.ResourceAssociation;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
import com.foundation.view.VariableResourceAssociation;
public class CardLayout extends Layout {
/** The layout's top index resource. */
private VariableResourceAssociation topIndex = new VariableResourceAssociation(getContainer(), this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, false, new Integer(0));
/** The top and bottom margins. */
public int marginHeight = 0;
/** The left and right margins. */
public int marginWidth = 0;
/**
* CardLayout constructor.
* @param container The container that is using the layout.
*/
public CardLayout(IAbstractSwtContainer container) {
super(container);
}//CardLayout()//
/**
* CardLayout constructor.
* @param container The container that is using the layout.
*/
public CardLayout(ICellContainer container) {
super(container);
}//CardLayout()//
/**
* Changes the top index for an optional row object.
* @param rowObject The optional row object.
* @param index The new top index.
*/
protected void changeTopIndex(Object rowObject, final int index) {
applyChanges(null, new IChangeHandler() {
public void applyChanges(org.eclipse.swt.widgets.Composite composite) {
org.eclipse.swt.widgets.Layout layout = composite.getLayout();
if(layout instanceof com.foundation.view.swt.layout.CardLayout) {
((com.foundation.view.swt.layout.CardLayout) layout).topIndex = index;
composite.layout(true, false);
}//if//
}//applyChanges()//
});
}//changeTopIndex()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#createLayout(java.lang.Object)
*/
public org.eclipse.swt.widgets.Layout createLayout(Object rowObject) {
com.foundation.view.swt.layout.CardLayout result = new com.foundation.view.swt.layout.CardLayout();
result.marginHeight = marginHeight;
result.marginWidth = marginWidth;
if(isInitialized()) {
changeTopIndex(null, topIndex.getValue(rowObject) == null ? 0 : ((Integer) topIndex.getValue(rowObject)).intValue());
}//if//
return result;
}//createLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#initialize()
*/
public void initialize() {
topIndex.initialize();
}//initialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#refresh()
*/
public void refresh() {
refreshTopIndex();
}//refresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#synchronize()
*/
public void synchronize() {
}//synchronize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#release()
*/
public void release() {
topIndex.release();
}//release()//
/**
* Refreshes the top index assocation.
*/
protected void refreshTopIndex() {
if(topIndex.refresh(null)) {
changeTopIndex(null, topIndex.getValue(null) == null ? 0 : ((Integer) topIndex.getValue(null)).intValue());
//layoutContainer(null, true, false);
}//if//
}//refreshTopIndex()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#onValueChanged(com.foundation.view.ResourceAssociation, boolean)
*/
public void onValueChanged(ResourceAssociation resourceAssociation, int flags) {
if(topIndex.hasAssociation((SingleResourceAssociation) resourceAssociation)) {
if(topIndex.refresh(null)) {
changeTopIndex(null, topIndex.getValue(null) == null ? 0 : ((Integer) topIndex.getValue(null)).intValue());
//layoutContainer(null, true, false);
}//if//
}//if//
else {
super.onValueChanged(resourceAssociation, flags);
}//else//
}//onValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#onValueChanged(com.foundation.view.ResourceAssociation, java.lang.Object, boolean)
*/
public void onValueChanged(ResourceAssociation resourceAssociation, Object alteredItem, Object data, boolean isUpdate) {
if(topIndex.hasAssociation((MultiResourceAssociation) resourceAssociation)) {
if(topIndex.refresh(alteredItem)) {
changeTopIndex(null, topIndex.getValue(alteredItem) == null ? 0 : ((Integer) topIndex.getValue(alteredItem)).intValue());
//layoutContainer(null, true, false);
}//if//
}//if//
else {
super.onValueChanged(resourceAssociation, alteredItem, data, isUpdate);
}//else//
}//onValueChanged()//
/**
* Sets the layout margin width.
* @param marginWidth The layout margin width.
*/
public void setMarginWidth(int marginWidth) {
this.marginWidth = marginWidth;
}//setMarginWidth()//
/**
* Sets the layout margin height.
* @param marginHeight The layout margin height.
*/
public void setMarginHeight(int marginHeight) {
this.marginHeight = marginHeight;
}//setMarginHeight()//
/**
* Sets an association container used to access the text.
* @param container The text association metadata.
*/
public void setTopIndexAssociation(SingleAssociationContainer container) {
this.topIndex.setAssociations(container);
}//setTextAssociation()//
}//CardLayout//

View File

@@ -0,0 +1,44 @@
package com.foundation.view.swt;
public class CenterLayout extends Layout {
/**
* CenterLayout constructor.
* @param container The container that is using the layout.
*/
public CenterLayout(IAbstractSwtContainer container) {
super(container);
}//CenterLayout()//
/**
* CenterLayout constructor.
* @param cellContainer The container that is using the layout.
*/
public CenterLayout(ICellContainer cellContainer) {
super(cellContainer);
}//CenterLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#createLayout(java.lang.Object)
*/
public org.eclipse.swt.widgets.Layout createLayout(Object rowObject) {
return new com.foundation.view.swt.layout.CenterLayout();
}//createLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#initialize()
*/
public void initialize() {
}//initialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#refresh()
*/
public void refresh() {
}//refresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#release()
*/
public void release() {
}//release()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#synchronize()
*/
public void synchronize() {
}//synchronize()//
}//CenterLayout//

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,494 @@
/*
* 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.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import com.common.thread.IRunnable;
import com.common.util.optimized.IntArray;
import com.foundation.event.*;
import com.foundation.view.JefImage;
import com.foundation.view.MultiAssociationContainer;
import com.foundation.view.MultiResourceAssociation;
import com.foundation.view.ResourceAssociation;
/**
* Very similar to the list box control except that only one value can be selected at a time and the list only appears when the user requests to change the value.
* The combo may also allow for custom user selections that are not in the list.
*/
public class ComboBox extends IndexedCollectionComponent implements IEventListener, SelectionListener, ModifyListener {
//Styles//
public static final int STYLE_DROP_DOWN = SWT.DROP_DOWN;
public static final int STYLE_READ_ONLY = SWT.READ_ONLY;
public static final int STYLE_SIMPLE = SWT.SIMPLE;
/** Converts the collection item to a string used to show the item to the user. */
protected MultiResourceAssociation itemText = new MultiResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_TEXT, false, null);
/** Converts the collection item to an image used to show the item to the user. */
protected MultiResourceAssociation itemImage = new MultiResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_IMAGE, false, null);
/** Used to stop selection events from being handled while the items are being changed. */
private boolean suspendSelectionEvents = false;
/**
* ComboBox constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_DROP_DOWN
* @see #STYLE_READ_ONLY
* @see #STYLE_SIMPLE
*/
public ComboBox(Container parent, String name, int style) {
super(parent, name, style);
setAllowUserItems(!((style & STYLE_READ_ONLY) > 0));
}//ComboBox()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.Combo(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT combo that represents this combo box.
* @return The SWT combo providing visualization for this combo box.
*/
public org.eclipse.swt.widgets.Combo getSwtCombo() {
return (org.eclipse.swt.widgets.Combo) getSwtControl();
}//getSwtCombo()//
/**
* Sets the association container used to access the item text.
* @param container The item text association metadata.
*/
public void setItemTextAssociation(MultiAssociationContainer container) {
verifyThread();
this.itemText.setAssociations(container);
}//setItemTextAssociation()//
/**
* Sets the association container used to access the item image.
* @param container The item image association metadata.
*/
public void setItemImageAssociation(MultiAssociationContainer container) {
verifyThread();
this.itemImage.setAssociations(container);
}//setItemImageAssociation()//
/**
* Gets the component text size limit.
* @return The maximum number of characters allowed in the text.
*/
public Integer getTextLimit() {
verifyThread();
return new Integer(getSwtCombo().getTextLimit());
}//getTextLimit()//
/**
* Sets the component text size limit.
* @param textLimit The maximum number of characters allowed in the text.
*/
public void setTextLimit(Integer textLimit) {
verifyThread();
getSwtCombo().setTextLimit(textLimit.intValue());
}//setTextLimit()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
getSwtCombo().addSelectionListener(this);
getSwtCombo().addModifyListener(this);
itemText.initialize();
itemImage.initialize();
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
if((getSwtCombo() != null) && (!getSwtCombo().isDisposed())) {
getSwtCombo().removeSelectionListener(this);
getSwtCombo().removeModifyListener(this);
}//if//
super.internalViewRelease();
itemText.release();
itemImage.release();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.MultiResourceAssociation, java.lang.Object)
*/
protected void internalOnValueChanged(MultiResourceAssociation resourceAssociation, Object alteredItem, Object data, boolean isUpdate) {
if(resourceAssociation == itemText) {
Object indexData = getItemIndexData(alteredItem);
//Set the new item text.//
if(indexData instanceof Integer) {
controlSetItem(((Integer) indexData).intValue(), itemToString(alteredItem));
}//if//
else if(indexData instanceof IntArray) {
IntArray array = (IntArray) indexData;
for(int index = 0; index < array.getSize(); index++) {
controlSetItem(array.get(index), itemToString(alteredItem));
}//for//
}//if//
}//if//
else if(resourceAssociation == itemImage) {
//TODO: Set the item image.
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, alteredItem, data, isUpdate);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IndexedCollectionComponent#getItemData(java.lang.Object)
*/
protected Object getItemData(Object item) {
return itemToString(item);
}//getItemData()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#itemAdded(java.lang.Object, int)
*/
protected void itemAdded(Object item, int index) {
registerItem(item);
super.itemAdded(item, index);
}//itemAdded()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#itemRemoved(java.lang.Object, int)
*/
protected void itemRemoved(Object item, int index) {
unregisterItem(item);
super.itemRemoved(item, index);
}//itemRemoved()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#itemAllRemoved()
*/
protected void itemAllRemoved() {
unregisterItems();
super.itemAllRemoved();
}//itemAllRemoved()//
/**
* Converts an item in the collection to a string that can be displayed.
* @param item The collection item to convert.
* @return The string that can be displayed.
*/
protected String itemToString(Object item) {
String result = null;
if(item instanceof JefImage) {
return "";
}//if//
else {
itemText.refresh(item);
result = (String) itemText.getValue(item);
if(result == null) {
result = item != null ? item.toString() : "";
}//if//
}//if//
return result;
}//itemToString()//
/**
* Converts an item in the collection to an image that can be displayed.
* @param item The collection item to convert.
* @return The image that can be displayed.
*/
protected JefImage itemToImage(Object item) {
JefImage result = null;
if(item instanceof JefImage) {
result = (JefImage) item;
}//if//
else {
itemImage.refresh(item);
result = (JefImage) itemImage.getValue(item);
}//else//
return result;
}//itemToImage()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#registerItem(java.lang.Object)
*/
protected void registerItem(Object item) {
itemText.registerItem(item, null);
itemImage.registerItem(item, null);
super.registerItem(item);
}//registerItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#unregisterItem(java.lang.Object)
*/
protected void unregisterItem(Object item) {
itemText.unregisterItem(item);
itemImage.unregisterItem(item);
super.unregisterItem(item);
}//unregisterItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#unregisterItems()
*/
protected void unregisterItems() {
itemText.unregisterAllItems();
itemImage.unregisterAllItems();
super.unregisterItems();
}//unregisterItems()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent e) {
updateSelectionLinks();
if(getAutoSynchronizeSelection()) {
if(getAutoSynchronizeSelectionDelay() > 0) {
//Start a task to send the selection to the server after a short delay. This will reduce the overhead of auto synchronizing the selection.//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
}//if//
autoSynchronizeSelectionTask = new Task() {
public void execute() {
//Make sure that this task is still valid and is not being superceeded.//
synchronized(ComboBox.this) {
if(autoSynchronizeSelectionTask == this) {
//Cleanup after the task.//
autoSynchronizeSelectionTask = null;
getEventLoop().executeAsync(new IRunnable() {
public Object run() {
synchronizeSelection();
if(getAutoValidate()) {
postSynchronizeValidate();
}//if//
return null;
}//run()//
});
}//if//
}//synchronized//
}//run()//
};
addTask(autoSynchronizeSelectionTask, getAutoSynchronizeSelectionDelay());
}//synchronized//
}//if//
else {
synchronizeSelection();
if(getAutoValidate()) {
postSynchronizeValidate();
}//if//
}//else//
}//if//
}//widgetSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent)
*/
public void modifyText(ModifyEvent event) {
if(!suspendSelectionEvents) {
if(controlGetSelection() == -1) {
widgetSelected(null);
}//if//
}//if//
}//modifyText()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlRemoveAll()
*/
protected void controlRemoveAll() {
getSwtCombo().removeAll();
}//controlRemoveAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlSetItems(String[])
*/
protected void controlSetItems(Object[] items) {
String[] itemTexts = new String[items.length];
for(int index = 0; index < itemTexts.length; index++) {
itemTexts[index] = items[index] == null ? "" : items[index].toString();
}//for//
suspendSelectionEvents = true;
try {
getSwtCombo().setItems(itemTexts);
}//try//
finally {
suspendSelectionEvents = false;
}//finally//
}//controlSetItems()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlSetItem(int, String)
*/
protected void controlSetItem(int index, Object itemData) {
suspendSelectionEvents = true;
try {
getSwtCombo().setItem(index, (String) itemData);
}//try//
finally {
suspendSelectionEvents = false;
}//finally//
}//controlSetItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlAddItem(String, int)
*/
protected void controlAddItem(Object itemData, int index) {
suspendSelectionEvents = true;
try {
getSwtCombo().add((String) itemData, index);
}//try//
finally {
suspendSelectionEvents = false;
}//finally//
}//controlAddItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlAddItem(String)
*/
protected void controlAddItem(Object itemData) {
suspendSelectionEvents = true;
try {
getSwtCombo().add((String) itemData);
}//try//
finally {
suspendSelectionEvents = false;
}//finally//
}//controlAddItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlRemoveItem(int)
*/
protected void controlRemoveItem(int index) {
suspendSelectionEvents = true;
try {
getSwtCombo().remove(index);
}//try//
finally {
suspendSelectionEvents = false;
}//finally//
}//controlRemoveItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlGetSelections()
*/
protected int[] controlGetSelections() {
//return getSwtCombo().getSelectionIndices();
throw new RuntimeException("Method not supported - controlGetSelections");
}//controlGetSelections()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlGetSelection()
*/
protected int controlGetSelection() {
return getSwtCombo().getSelectionIndex();
}//controlGetSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlSetSelections()
*/
protected void controlSetSelections(int[] indices) {
//getSwtCombo().setSelection(indices);
throw new RuntimeException("Method not supported - controlSetSelections");
}//controlSetSelections()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlSetSelection()
*/
protected void controlSetSelection(int index) {
if(getSwtCombo().getSelectionIndex() != index) {
suspendSelectionEvents = true;
try {
if(index == -1) {
getSwtCombo().deselectAll();
}//if//
else {
getSwtCombo().select(index);
}//else//
}//try//
finally {
suspendSelectionEvents = false;
}//finally//
}//if//
}//controlSetSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlAddSelection()
*/
protected void controlAddSelection(int index) {
//getSwtCombo().select(index);
throw new RuntimeException("Method not supported - controlAddSelection");
}//controlAddSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlRemoveSelection()
*/
protected void controlRemoveSelection(int index) {
suspendSelectionEvents = true;
try {
getSwtCombo().deselect(index);
}//try//
finally {
suspendSelectionEvents = false;
}//finally//
}//controlRemoveSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlRemoveAllSelections()
*/
protected void controlRemoveAllSelections() {
suspendSelectionEvents = true;
try {
getSwtCombo().deselectAll();
}//try//
finally {
suspendSelectionEvents = false;
}//finally//
}//controlRemoveAllSelections()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlIsSelected()
*/
protected boolean controlIsSelected(int index) {
return getSwtCombo().getSelectionIndex() == index;
}//controlIsSelected()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlGetText()
*/
protected String controlGetText() {
return getSwtCombo().getText();
}//controlGetText()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlSetCustomItem(Object)
*/
protected void controlSetCustomItem(Object item) {
suspendSelectionEvents = true;
try {
if(item == null) {
getSwtCombo().deselectAll();
}//if//
else {
getSwtCombo().deselectAll();
getSwtCombo().setText(item.toString());
}//else//
}//try//
finally {
suspendSelectionEvents = false;
}//finally//
}//controlSetCustomItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlGetSelectionCount()
*/
protected int controlGetSelectionCount() {
return getSwtCombo().getText().length() > 0 ? 1 : 0;
}//controlGetSelectionCount()//
/**
* Forces the selection event handler to be called.
*/
protected void forceSelectionEvent() { //Should call widgetSelected implemented by the subclass. This name may need to change.//
widgetSelected(null);
}//forceSelectionEvent()//
}//ComboBox//

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,512 @@
/*
* 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.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Composite;
import com.common.util.*;
import com.common.debug.*;
import com.common.thread.IRunnable;
import com.foundation.view.*;
import com.foundation.view.resource.AbstractResourceService;
import com.foundation.event.IRequestHandler;
import com.foundation.controller.AbstractViewController;
/*
* An SWT container which is a component which may contain other components.
*/
public abstract class Container extends ScrollableComponent implements IAbstractSwtContainer {
public static final int STYLE_NO_BACKGROUND = SWT.NO_BACKGROUND;
public static final int STYLE_NO_FOCUS = SWT.NO_FOCUS;
public static final int STYLE_NO_MERGE_PAINTS = SWT.NO_MERGE_PAINTS;
public static final int STYLE_NO_REDRAW_RESIZE = SWT.NO_REDRAW_RESIZE;
public static final int STYLE_NO_RADIO_GROUP = SWT.NO_RADIO_GROUP;
public static final int STYLE_EMBEDDED = SWT.EMBEDDED;
public static final int STYLE_DOUBLE_BUFFERED = SWT.DOUBLE_BUFFERED;
public static final int INHERIT_NONE = 0;
public static final int INHERIT_DEFAULT = 1;
public static final int INHERIT_FORCE = 2;
public static final int LAST_LINK_TARGET = ScrollableComponent.LAST_LINK_TARGET + 0;
/** A collection of components contained by this container. */
private IList components = new LiteList(10, 30);
/** The component's controller. */
private AbstractViewController controller;
/** The container's layout. */
private Layout layout = null;
/**
* Container default constructor.
* <p>Warning: This is only for use by the framework. This should never be called to create a useable instance.</p>
*/
public Container() {
}//Container()//
/**
* Container constructor.
* @param parent The parent container for this container.
* @param name The unique component name.
* @param style The style for the control.
*/
public Container(IAbstractContainer parent, String name, int style) {
super(parent, name, style);
}//Container()//
/**
* Container constructor.
* @param parent The parent container for this container.
* @param name The unique component name.
* @param viewContext The context under which this view component operates. For all but the outer most control this can be null.
* @param style The style for the control.
* @param data The optional data passed to the initializeControl(int, java.lang.Object) method.
*/
public Container(IAbstractContainer parent, String name, IViewContext viewContext, int style, Object data) {
super(parent, name, viewContext, style, data);
}//Container()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractComponent#getResourceService()
*/
public AbstractResourceService getResourceService() {
return getController().getApplication().getResourceService();
}//getResourceService()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IAbstractSwtContainer#getSwtComposite()
*/
public Composite getSwtComposite() {
return (Composite) getSwtControl();
}//getSwtComposite()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IAbstractSwtContainer#getSwtParent()
*/
public Composite getSwtParent() {
return (Composite) getSwtControl();
}//getSwtParent()//
/**
* Sets the container layout.
* @param layout The layout for the container.
*/
public void setLayout(Layout layout) {
verifyThread();
if(this.layout != null) {
throw new RuntimeException("Cannot change the layout once set.");
}//if//
else if(isInitialized()) {
throw new RuntimeException("Cannot set the layout once the view is initialized.");
}//else if//
this.layout = layout;
}//setLayout()//
/**
* Gets the frame's default button.
* @return The default button in this container.
*/
public Button getDefaultButton() {
Component container = (Component) getContainer();
verifyThread();
while(!((container instanceof Frame) || (container instanceof SwtWrapperContainer))) {
container = (Component) container.getContainer();
}//while//
//TODO: It would be nice to abstract this to an interface.
if(container instanceof Frame) {
return ((Frame) container).getDefaultButton();
}//if//
else {
return (Button) ((SwtWrapperContainer) container).getShell().getDefaultButton().getData();
}//else//
}//getDefaultButton()//
/**
* Sets the frame's default button.
* @param defaultButton The default button in this container.
*/
public void setDefaultButton(Button defaultButton) {
Component container = (Component) getContainer();
verifyThread();
while(!((container instanceof Frame) || (container instanceof SwtWrapperContainer))) {
container = (Component) container.getContainer();
}//while//
//TODO: It would be nice to abstract this to an interface.
if(container instanceof Frame) {
((Frame) container).setDefaultButton(defaultButton);
}//if//
else {
((SwtWrapperContainer) container).getShell().setDefaultButton(defaultButton.getSwtButton());
}//else//
}//setDefaultButton()//
/**
* Sets the background inheritance for all children.
* @param inherit Whether the background of this composite should be inherited by all child controls. The default value will cause children that don't specify otherwise to inherit the background.
* @see #INHERIT_NONE
* @see #INHERIT_DEFAULT
* @see #INHERIT_FORCE
*/
public void setInheritBackground(int inheritType) {
int mode = inheritType == INHERIT_FORCE ? SWT.INHERIT_FORCE : inheritType == INHERIT_DEFAULT ? SWT.INHERIT_DEFAULT : SWT.INHERIT_NONE;
getSwtComposite().setBackgroundMode(mode);
//TODO: Why is this here? I don't think it should be.
// if(getSwtParent() != getSwtComposite()) {
// getSwtParent().setBackgroundMode(mode);
// }//if//
}//setInheritBackground()//
/**
* Tells the container to layout the components contained within it.
*/
public final void layout() {
verifyThread();
getSwtParent().layout();
internalLayout();
}//layout()//
/**
* Sets the tabbing order for the controls in the container.
* @param controls The collection of controls in the order they are to be tabbed over.
*/
public void setTabOrder(IList controls) {
Control[] array = new Control[controls.getSize()];
for(int index = 0; index < controls.getSize(); index++) {
array[index] = ((Component) controls.get(index)).getSwtControl();
}//for//
getSwtParent().setTabList(array);
}//setTabOrder()//
/**
* Adds a component as a child of this container.
* @param component The component to be contained by this container.
*/
public void addComponent(IAbstractComponent component) {
components.add(component);
}//addComponent()//
/**
* Removes a component that was child of this container.
* @param component The component to no longer be contained by this container.
*/
public void removeComponent(IAbstractComponent component) {
components.remove(component);
}//removeComponent()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractContainer#getComponents()
*/
public IList getComponents() {
return components;
}//getComponents()//
/* (non-Javadoc)
* @see com.foundation.view.IView#maximize()
*/
public void maximize() {
IAbstractContainer container = getContainer();
if(container != null) {
container.maximize();
}//if//
}//maximize()//
/* (non-Javadoc)
* @see com.foundation.view.IView#minimize()
*/
public void minimize() {
IAbstractContainer container = getContainer();
if(container != null) {
container.minimize();
}//if//
}//minimize()//
/* (non-Javadoc)
* @see com.foundation.view.IView#show()
*/
public void show() {
IAbstractContainer container = getContainer();
if(container != null) {
container.show();
}//if//
}//show()//
/* (non-Javadoc)
* @see com.foundation.view.IView#pack()
*/
public void pack() {
getSwtParent().pack();
internalPack();
}//pack()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalPack()
*/
protected void internalPack() {
//Call internalPack on all sub-components.//
for(int index = 0; index < getComponents().getSize(); index++) {
((AbstractComponent) getComponents().get(index)).internalPack();
}//for//
}//internalPack()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalLayout()
*/
protected void internalLayout() {
//Call internalLayout on all sub-components.//
for(int index = 0; index < getComponents().getSize(); index++) {
((AbstractComponent) getComponents().get(index)).internalLayout();
}//for//
}//internalLayout()//
/**
* Called after a child resizes.
* This allows the opportunity for the container to appropriately handle the resize of children.
*/
public void postResize() {
if(getContainer() != null && getContainer() instanceof Container) {
((Container) getContainer()).postResize();
}//if//
}//postResize()//
/* (non-Javadoc)
* @see com.foundation.view.IView#center()
*/
public void center() {
//Does nothing. This should be overloaded for subclasses which are capable of standalone behavior (window, frame, etc).//
}//center()//
/* (non-Javadoc)
* @see com.foundation.view.IView#center(com.foundation.view.IView)
*/
public void center(IView view) {
//Does nothing. This should be overloaded for subclasses which are capable of standalone behavior (window, frame, etc).//
}//center()//
/* (non-Javadoc)
* @see com.foundation.view.IView#getController()
*/
public AbstractViewController getController() {
if(controller == null) {
Container parent = (Container) getContainer();
while((parent != null) && (!(parent instanceof IView))) {
parent = (Container) parent.getContainer();
}//while//
controller = parent != null ? parent.getController() : null;
}//if//
return controller;
}//getController()//
/**
* Sets the container's associated controller.
* @param controller The controller for this container.
*/
public void setController(AbstractViewController controller) {
this.controller = controller;
}//setController()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
if(layout != null) {
layout.initialize();
getSwtParent().setLayout(layout.createLayout(null));
}//if//
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitializeAll()
*/
public void internalViewInitializeAll() {
//Initialize this component.//
super.internalViewInitializeAll();
//Initialize the contained components.//
initializeContainedComponents();
}//internalViewInitializeAll()//
/**
* Initializes the components contained in this container.
* <p>This is separated into a separate method from internalViewInitializeAll() so that subclasses that are very specialized containers can easily override it.</p>
*/
protected void initializeContainedComponents() {
try {
IIterator iterator = components.iterator();
//Initialize contained value holders first.//
while(iterator.hasNext()) {
AbstractComponent component = (AbstractComponent) iterator.next();
if(component instanceof ValueHolder) {
component.internalViewInitializeAll();
}//if//
}//for//
iterator.resetToFront();
//Initialize all contained components that are not value holders.//
while(iterator.hasNext()) {
AbstractComponent component = (AbstractComponent) iterator.next();
if(!(component instanceof ValueHolder)) {
component.internalViewInitializeAll();
}//if//
}//for//
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
}//catch//
}//initializeContainedComponents()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
if(layout != null) {
layout.release();
}//if//
super.internalViewRelease();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewReleaseAll()
*/
public void internalViewReleaseAll() {
try {
IIterator iterator = new LiteList(getComponents()).iterator();
//Release sub-components.//
while(iterator.hasNext()) {
AbstractComponent component = (AbstractComponent) iterator.next();
component.internalViewReleaseAll();
}//for//
//Release this component.//
super.internalViewReleaseAll();
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}//internalViewReleaseAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
super.internalViewSynchronize();
if(layout != null) {
layout.synchronize();
}//if//
}//internalViewSynchronize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
if(layout != null) {
layout.refresh();
}//if//
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefreshAll()
*/
public void internalViewRefreshAll() {
try {
IIterator iterator = components.iterator();
//Refresh value holders.//
while(iterator.hasNext()) {
AbstractComponent component = (AbstractComponent) iterator.next();
if(component instanceof ValueHolder) {
component.internalViewRefreshAll();
}//if//
}//for//
iterator = components.iterator();
//Refresh non-value holders.//
while(iterator.hasNext()) {
AbstractComponent component = (AbstractComponent) iterator.next();
if(!(component instanceof ValueHolder)) {
component.internalViewRefreshAll();
}//if//
}//for//
//Refresh this component.//
super.internalViewRefreshAll();
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
}//catch//
}//internalViewRefreshAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronizeAll()
*/
public void internalViewSynchronizeAll() {
try {
IIterator iterator = null;
//Synchronize this component.//
super.internalViewSynchronizeAll();
//Synchronized the contained components.//
iterator = components.iterator();
//Synchronize sub-components.//
while(iterator.hasNext()) {
AbstractComponent component = (AbstractComponent) iterator.next();
component.internalViewSynchronizeAll();
}//for//
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}//internalViewSynchronizeAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#internalSetEnabledState(boolean, boolean)
*/
protected void internalSetEnabledState(boolean isEnabled, boolean isLocal) {
IIterator iterator = getComponents().iterator();
if(isLocal) {
isLocallyEnabled = isEnabled;
}//if//
else {
isParentEnabled = isEnabled;
}//else//
if(getSwtControl().getEnabled() != isLocallyEnabled && isParentEnabled) {
//Update the control's state.//
getSwtControl().setEnabled(isLocallyEnabled && isParentEnabled);
//Enable or disable all the contained components.//
while(iterator.hasNext()) {
AbstractComponent next = (AbstractComponent) iterator.next();
if(next instanceof Component) {
((Component) next).internalSetEnabledState(isEnabled, false);
}//if//
}//while//
}//if//
}//internalSetEnabledState()//
/* (non-Javadoc)
* @see com.foundation.view.IView#execute(com.common.thread.IRunnable)
*/
public Object execute(IRunnable runnable) {
return getEventLoop().execute(runnable, true);
}//execute()//
/* (non-Javadoc)
* @see com.foundation.view.IView#executeAsynch(com.common.thread.IRunnable)
*/
public void executeAsync(IRunnable runnable) {
getEventLoop().execute(runnable, false);
}//executeAsynch()//
/* (non-Javadoc)
* @see com.foundation.view.IView#getRequestHandler()
*/
public IRequestHandler getRequestHandler() {
return getEventLoop();
}//getRequestHandler()//
}//Container//

View File

@@ -0,0 +1,435 @@
/*
* Copyright (c) 2006,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import com.common.util.LiteList;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
public class CoolBar extends Container {
public static final int STYLE_FLAT = SWT.FLAT;
/** The collection of CoolItem instances contained by the cool bar. */
private LiteList coolItems = new LiteList(10, 20);
/** The collection of Menu instances associated with cool items. */
private LiteList menus = new LiteList(10, 20);
/**
* Encapsulates an item in the bar.
*/
public static class CoolItem extends AbstractComponent implements SelectionListener {
public static final int STYLE_DROP_DOWN = SWT.DROP_DOWN;
public static final int LINK_TARGET_IS_VISIBLE = AbstractComponent.LAST_LINK_TARGET + 1;
public static final int LAST_LINK_TARGET = AbstractComponent.LAST_LINK_TARGET + 1;
/** The control displayed by the cool item. */
private Component control = null;
/** The style used by the item. */
private int style;
/** Whether a custom size is used for the item. */
private boolean customSize = false;
/** The custom width for the item. */
private int customWidth = 0;
/** The custom height for the item. */
private int customHeight = 0;
/** Whether a custom preferred size is used for the item. */
private boolean customPreferredSize = false;
/** The custom preferred width for the item. */
private int customPreferredWidth = 0;
/** The custom preferred height for the item. */
private int customPreferredHeight = 0;
/** Whether a custom minimum size is used for the item. */
private boolean customMinimumSize = false;
/** The custom minimum width for the item. */
private int customMinimumWidth = 0;
/** The custom minimum height for the item. */
private int customMinimumHeight = 0;
/** Whether the item is currently visible. */
private boolean visible = true;
/** The resource defining the visible state for the item. */
private SingleResourceAssociation isVisible = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_BOOLEAN, false, Boolean.TRUE);
/**
* CoolItem constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_DROP_DOWN
*/
public CoolItem(Container parent, String name, int style) {
super(parent, style);
this.style = style;
((CoolBar) parent).addCoolItem(this);
}//CoolItem()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractComponent#getName()
*/
public String getName() {
return "__CoolBarItem__";
}//getName()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IInternalAbstractComponent#getShell()
*/
public Shell getShell() {
return ((Container) getContainer()).getShell();
}//getShell()//
/**
* Sets the association container used to access the visibility.
* @param container The visibility association metadata.
*/
public void setIsVisibleAssociation(SingleAssociationContainer container) {
verifyThread();
this.isVisible.setAssociations(container);
}//setIsVisibleAssociation()//
/**
* Sets whether the component is visible (by default if an attribute is bound to this value).
* @param isVisible Whether the user can see the component.
*/
public void setIsVisible(boolean isVisible) {
verifyThread();
this.isVisible.setDefaultValue(isVisible ? Boolean.TRUE : Boolean.FALSE);
}//setIsVisible()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.CoolItem(((CoolBar) getContainer()).getSwtCoolBar(), style));
getSwtWidget().setData(this);
if(customSize) {
getSwtCoolItem().setSize(customWidth, customHeight);
}//if//
if(customPreferredSize) {
getSwtCoolItem().setPreferredSize(customPreferredWidth, customPreferredHeight);
}//if//
if(customMinimumSize) {
getSwtCoolItem().setMinimumSize(customMinimumWidth, customMinimumHeight);
}//if//
}//initializeControl()//
/**
* Gets the swt cool item for this cool item.
* @return The SWT cool item providing visualization for this cool item.
*/
public org.eclipse.swt.widgets.CoolItem getSwtCoolItem() {
return (org.eclipse.swt.widgets.CoolItem) getSwtWidget();
}//getSwtCoolItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
getSwtCoolItem().addSelectionListener(this);
isVisible.initialize();
getSwtCoolItem().setControl(control.getSwtControl());
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
if(!getSwtCoolItem().isDisposed()) {
getSwtCoolItem().setControl(null);
getSwtCoolItem().dispose();
}//if//
isVisible.release();
super.internalViewRelease();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalViewRefreshIsVisible();
if(!customPreferredSize && !customSize) {
Point size;
//control.getSwtControl().pack();
size = control.getSwtControl().computeSize(SWT.DEFAULT, SWT.DEFAULT);
if(!customMinimumSize) {
getSwtCoolItem().setMinimumSize(size);
}//if//
size = getSwtCoolItem().computeSize(size.x, size.y);
size.x = Math.max(size.x, getSwtCoolItem().getMinimumSize().x);
size.y = Math.max(size.y, getSwtCoolItem().getMinimumSize().y);
getSwtCoolItem().setPreferredSize(size);
getSwtCoolItem().setSize(size);
}//if//
}//internalViewRefresh()//
/**
* Refreshes whether the component is visible based on the attribute value or if null the default flag value.
*/
protected void internalViewRefreshIsVisible() {
if(isVisible.refresh()) {
controlSetIsVisible(isVisible.getValue() == null ? true : ((Boolean) isVisible.getValue()).booleanValue());
}//if//
}//internalViewRefreshIsVisible()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnLinkInvoked(int, java.lang.Object)
*/
protected void internalOnLinkInvoked(int linkTarget, Object data) {
switch(linkTarget) {
case LINK_TARGET_IS_VISIBLE: {
controlSetIsVisible(data != null && data instanceof Boolean ? ((Boolean) data).booleanValue() : false);
break;
}//case//
default: {
super.internalOnLinkInvoked(linkTarget, data);
break;
}//default//
}//switch//
}//internalOnLinkInvoked()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == isVisible) {
internalViewRefreshIsVisible();
}//if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/**
* Sets whether the control is visible.
* @param visible Whether the control is visible to the user.
*/
protected void controlSetIsVisible(boolean visible) {
if(this.visible != visible) {
this.visible = visible;
//Destroy or create the cool item.//
if(!visible) {
if(getSwtCoolItem() != null && !getSwtCoolItem().isDisposed()) {
getSwtCoolItem().dispose();
}//if//
setSwtWidget(null);
}//if//
else {
initializeControl(style, null);
}//else//
}//if//
}//controlSetIsVisible()//
/**
* Sets the cool item initial size.
* @param width
* @param height
*/
public void setSize(int width, int height) {
customSize = true;
customWidth = width;
customHeight = height;
if(getSwtCoolItem() != null) {
getSwtCoolItem().setSize(width, height);
}//if//
}//setSize()//
/**
* Sets the cool item minimum size.
* @param width
* @param height
*/
public void setMinimumSize(int width, int height) {
customMinimumSize = true;
customMinimumWidth = width;
customMinimumHeight = height;
if(getSwtCoolItem() != null) {
getSwtCoolItem().setMinimumSize(width, height);
}//if//
}//setMinimumSize()//
/**
* Sets the cool item preferred size.
* @param width
* @param height
*/
public void setPreferredSize(int width, int height) {
customPreferredSize = true;
customPreferredWidth = width;
customPreferredHeight = height;
if(getSwtCoolItem() != null) {
getSwtCoolItem().setPreferredSize(width, height);
}//if//
}//setPreferredSize()//
/**
* Sets the control used by the cool item.
* @param control The cool item's control.
*/
public void setControl(Component control) {
this.control = control;
}//setControl()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent event) {
widgetSelected(event);
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent event) {
/* TODO: Enable the drop down cheveron. Display a menu of items not visible on the menu bar associated with the cool item.
if((menu != null) && (event.detail == SWT.ARROW)) {
Rectangle rect = getSwtCoolItem().getBounds();
Point point = new Point(rect.x, rect.y + rect.height);
//Show the drop down menu.//
point = getSwtCoolItem().getParent().toDisplay(point);
if(menu != null) {
menu.getSwtMenu().setLocation(point.x, point.y);
menu.getSwtMenu().setVisible(true);
}//if//
}//if//
*/
}//widgetSelected()//
}//CoolItem//
/**
* CoolBar constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_FLAT
*/
public CoolBar(Container parent, String name, int style) {
super(parent, name, style);
}//CoolBar()//
/**
* Adds a cool item to the bar.
* @param coolItem The item to be added.
*/
protected void addCoolItem(CoolItem coolItem) {
coolItems.add(coolItem);
if(isInitialized()) {
//TODO: Initialize the cool item.
//Will the cool item's component already be initilialized?
//Would this ever occur?
}//if//
}//addCoolItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.CoolBar(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT cool bar that represents this cool bar.
* @return The SWT cool bar providing visualization for this cool bar.
*/
public org.eclipse.swt.widgets.CoolBar getSwtCoolBar() {
return (org.eclipse.swt.widgets.CoolBar) getSwtControl();
}//getSwtCoolBar()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
//Add a listener to force the view to re-layout when the coolbar changes sizes (expands or contracts).//
getSwtCoolBar().addListener(SWT.Resize, new Listener() {
public void handleEvent(Event event) {
getSwtCoolBar().getParent().layout(true, true);
getSwtCoolBar().getParent().redraw();
}//handleEvent()//
});
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitializeAll()
*/
public void internalViewInitializeAll() {
super.internalViewInitializeAll();
//Initialize all the cool items.//
for(int index = 0; index < coolItems.getSize(); index++) {
((CoolItem) coolItems.get(index)).internalViewInitialize();
}//for//
//Initialize all the menus.//
for(int index = 0; index < menus.getSize(); index++) {
((Menu) menus.get(index)).internalViewInitializeAll();
}//for//
}//internalViewInitializeAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewReleaseAll()
*/
public void internalViewReleaseAll() {
//Release all the cool items.//
for(int index = 0; index < coolItems.getSize(); index++) {
((CoolItem) coolItems.get(index)).internalViewRelease();
}//for//
//Release all the menus.//
for(int index = 0; index < menus.getSize(); index++) {
((Menu) menus.get(index)).internalViewReleaseAll();
}//for//
super.internalViewReleaseAll();
}//internalViewReleaseAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefreshAll()
*/
public void internalViewRefreshAll() {
super.internalViewRefreshAll();
//Refresh all the cool items.//
for(int index = 0; index < coolItems.getSize(); index++) {
((CoolItem) coolItems.get(index)).internalViewRefresh();
}//for//
//Refresh all the menus.//
for(int index = 0; index < menus.getSize(); index++) {
((Menu) menus.get(index)).internalViewRefreshAll();
}//for//
}//internalViewRefreshAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronizeAll()
*/
public void internalViewSynchronizeAll() {
//Synchronize all the tool items.//
for(int index = 0; index < coolItems.getSize(); index++) {
((CoolItem) coolItems.get(index)).internalViewSynchronize();
}//for//
//Synchronize all the menus.//
for(int index = 0; index < menus.getSize(); index++) {
((Menu) menus.get(index)).internalViewSynchronizeAll();
}//for//
super.internalViewSynchronizeAll();
}//internalViewSynchronizeAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#setMenu(com.foundation.view.swt.Menu)
*/
public void setMenu(Menu menu) {
verifyThread();
menus.add(menu);
//A tool bar can have multiple menus associated with it. Each menu is tied to a drop down tool item. Since the tool item is not a control, the menu is linked to the bar instead.//
if((isInitialized()) && (menu != null)) {
menu.internalViewInitializeAll();
}//if//
}//setMenu()//
}//CoolBar//

View File

@@ -0,0 +1,361 @@
/*
* Copyright (c) 2007,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 java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import com.common.debug.Debug;
import com.common.thread.IRunnable;
import com.common.util.ICollection;
import com.foundation.view.IAbstractContainer;
import com.foundation.view.IMethodAssociation;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
public class DateTime extends Component implements SelectionListener {
public static final int STYLE_DATE = SWT.DATE;
public static final int STYLE_TIME = SWT.TIME;
public static final int STYLE_CALENDAR = SWT.CALENDAR;
public static final int STYLE_SHORT = SWT.SHORT;
public static final int STYLE_MEDIUM = SWT.MEDIUM;
public static final int STYLE_LONG = SWT.LONG;
public static final int STYLE_DROP_DOWN = SWT.DROP_DOWN;
/** The date/time selection. */
private SingleResourceAssociation selection = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_DATE, true, null);
/** Called when the user double clicks on a collection item. */
private IMethodAssociation doubleClickMethod = null;
/** Whether the selection state is auto synchronized. */
private boolean autoSynchronizeSelection = false;
/** The delay to be used when auto synchronizing changes to the text. */
private long autoSynchronizeSelectionDelay = 500;
/** The task that auto synchronizes the selection after a short delay. */
private Task autoSynchronizeSelectionTask = null;
/** Whether the year should be transfered to/from the view/model. */
private boolean includeYear = false;
/** Whether the month should be transfered to/from the view/model. */
private boolean includeMonth = false;
/** Whether the day should be transfered to/from the view/model. */
private boolean includeDay = false;
/** Whether the hour should be transfered to/from the view/model. */
private boolean includeHour = false;
/** Whether the minutes should be transfered to/from the view/model. */
private boolean includeMinute = false;
/** Whether the seconds should be transfered to/from the view/model. */
private boolean includeSecond = false;
/** The calendar used to transfer the date/time data to/from the model. */
private Calendar calendar = GregorianCalendar.getInstance();
/**
* DateTime constructor.
* <p>Warning: This is only for use by the framework. This should never be called to create a useable instance.</p>
*/
public DateTime() {
super();
}//DateTime()//
/**
* DateTime constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_DATE
* @see #STYLE_TIME
* @see #STYLE_CALENDAR
* @see #STYLE_SHORT
* @see #STYLE_MEDIUM
* @see #STYLE_LONG
*/
public DateTime(IAbstractContainer parent, String name, int style) {
super(parent, name, style);
includeYear = (((style & STYLE_DATE) > 0) || ((style & STYLE_CALENDAR) > 0));
includeMonth = (((style & STYLE_DATE) > 0) || ((style & STYLE_CALENDAR) > 0));
includeDay = ((((style & STYLE_DATE) > 0) && ((style & STYLE_SHORT) == 0)) || ((style & STYLE_CALENDAR) > 0));
includeHour = ((style & STYLE_TIME) > 0);
includeMinute = ((style & STYLE_TIME) > 0);
includeSecond = (((style & STYLE_TIME) > 0) && ((style & STYLE_SHORT) == 0));
}//DateTime()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.DateTime(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT button that represents this button.
* @return The SWT button providing visualization for this button.
*/
public org.eclipse.swt.widgets.DateTime getSwtDateTime() {
return (org.eclipse.swt.widgets.DateTime) getSwtControl();
}//getSwtDateTime()//
/**
* Sets an association container used to access the selection.
* @param container The selection association metadata.
*/
public void setSelectionAssociation(SingleAssociationContainer container) {
verifyThread();
this.selection.setAssociations(container);
}//setSelectionAssociation()//
/**
* Sets whether the control auto synchronizes the selected state of the button.
* @param autoSynchronizeSelection Whether the button state is automatically synchronized.
*/
public void setAutoSynchronizeSelection(boolean autoSynchronizeSelection) {
verifyThread();
this.autoSynchronizeSelection = autoSynchronizeSelection;
}//setAutoSynchronizeSelection()//
/**
* Sets the delay for the auto synchronize selection.
* @param autoSynchronizeSelectionDelay The delay in terms of milliseconds between the value of zero and ten thousand. A zero value has no delay.
*/
public void setAutoSynchronizeSelectionDelay(long autoSynchronizeSelectionDelay) {
verifyThread();
if(autoSynchronizeSelectionDelay < 0) {
autoSynchronizeSelectionDelay = 0;
}//if//
else if(autoSynchronizeSelectionDelay > 10000) {
autoSynchronizeSelectionDelay = 10000;
}//else if//
this.autoSynchronizeSelectionDelay = autoSynchronizeSelectionDelay;
}//setAutoSynchronizeSelectionDelay()//
/**
* Gets the method called to handle a double click.
* @return The method called when a calendar date is double clicked.
*/
protected IMethodAssociation getDoubleClickMethod() {
return doubleClickMethod;
}//getDoubleClickMethod()//
/**
* Sets the method called to handle a double click.
* @param doubleClickMethod The method called when a calendar date is double clicked.
*/
public void setDoubleClickMethod(IMethodAssociation doubleClickMethod) {
verifyThread();
this.doubleClickMethod = doubleClickMethod;
}//setDoubleClickMethod()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
getSwtDateTime().addSelectionListener(this);
selection.initialize();
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
if(!getSwtDateTime().isDisposed()) {
getSwtDateTime().removeSelectionListener(this);
}//if//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
autoSynchronizeSelectionTask = null;
}//if//
}//synchronized//
selection.release();
super.internalViewRelease();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalViewRefreshSelection();
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
super.internalViewSynchronize();
if(!autoSynchronizeSelection) {
if(includeYear) {
calendar.set(Calendar.YEAR, getSwtDateTime().getYear());
}//if//
if(includeMonth) {
calendar.set(Calendar.MONTH, getSwtDateTime().getMonth());
}//if//
if(includeDay) {
calendar.set(Calendar.DAY_OF_MONTH, getSwtDateTime().getDay());
}//if//
if(includeHour) {
calendar.set(Calendar.HOUR_OF_DAY, getSwtDateTime().getHours());
}//if//
if(includeMinute) {
calendar.set(Calendar.MINUTE, getSwtDateTime().getMinutes());
}//if//
if(includeSecond) {
calendar.set(Calendar.SECOND, getSwtDateTime().getSeconds());
}//if//
selection.setValue(calendar.getTime());
}//if//
}//internalViewSynchronize()//
/**
* Refreshes the button selection.
*/
protected void internalViewRefreshSelection() {
if(selection.refresh()) {
Date date = (Date) selection.getValue();
date = date == null ? new Date() : date;
calendar.setTime(date);
if(includeYear) {
getSwtDateTime().setYear(calendar.get(Calendar.YEAR));
}//if//
if(includeMonth) {
getSwtDateTime().setMonth(calendar.get(Calendar.MONTH));
}//if//
if(includeDay) {
getSwtDateTime().setDay(calendar.get(Calendar.DAY_OF_MONTH));
}//if//
if(includeHour) {
getSwtDateTime().setHours(calendar.get(Calendar.HOUR_OF_DAY));
}//if//
if(includeMinute) {
getSwtDateTime().setMinutes(calendar.get(Calendar.MINUTE));
}//if//
if(includeSecond) {
getSwtDateTime().setSeconds(calendar.get(Calendar.SECOND));
}//if//
}//if//
}//internalViewRefreshSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == selection) {
internalViewRefreshSelection();
}//if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent event) {
//This method is called when using the calendar widget and the user double clicks a date.//
if(getDoubleClickMethod() != null) {
long oldAutoSynchronizeSelectionDelay = autoSynchronizeSelectionDelay;
try {
//Set the synchronize delay to zero so the synchronize occurs immediatly.//
autoSynchronizeSelectionDelay = 0L;
//Force any selection task to complete prior to sending the double click.//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
autoSynchronizeSelectionTask.run();
}//if//
else if(!autoSynchronizeSelection) {
selectionChanged(calendar.getTime());
}//else if//
}//synchronized//
//Send the double click message.//
getDoubleClickMethod().invoke(null, new Object[] {selection.getValue()}, true);
}//try//
finally {
//Reset the delay and send the messages.//
autoSynchronizeSelectionDelay = oldAutoSynchronizeSelectionDelay;
}//finally//
}//if//
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent event) {
if(includeYear) {
calendar.set(Calendar.YEAR, getSwtDateTime().getYear());
}//if//
if(includeMonth) {
calendar.set(Calendar.MONTH, getSwtDateTime().getMonth());
}//if//
if(includeDay) {
calendar.set(Calendar.DAY_OF_MONTH, getSwtDateTime().getDay());
}//if//
if(includeHour) {
calendar.set(Calendar.HOUR_OF_DAY, getSwtDateTime().getHours());
}//if//
if(includeMinute) {
calendar.set(Calendar.MINUTE, getSwtDateTime().getMinutes());
}//if//
if(includeSecond) {
calendar.set(Calendar.SECOND, getSwtDateTime().getSeconds());
}//if//
selectionChanged(calendar.getTime());
}//widgetSelected()//
/**
* Called when the selection is changed in the view control.
* @param date The selected value.
*/
protected void selectionChanged(final Date date) {
if(autoSynchronizeSelection) {
if(autoSynchronizeSelectionDelay > 0) {
//Start a task to send the text to the server after a short delay. This will reduce the overhead of auto synchronizing the selection.//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
}//if//
autoSynchronizeSelectionTask = new Task() {
public void execute() {
//Make sure that this task is still valid and is not being superceeded.//
synchronized(DateTime.this) {
if(autoSynchronizeSelectionTask == this) {
//Cleanup after the task.//
autoSynchronizeSelectionTask = null;
getEventLoop().executeAsync(new IRunnable() {
public Object run() {
selection.setValue(date);
return null;
}//run()//
});
}//if//
}//synchronized//
}//run()//
};
addTask(autoSynchronizeSelectionTask, autoSynchronizeSelectionDelay);
}//synchronized//
}//if//
else {
selection.setValue(date);
}//else//
}//if//
}//selectionChanged()//
}//DateTime//

View File

@@ -0,0 +1,207 @@
/*
* Copyright (c) 2007,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
import com.common.util.IHashSet;
import com.foundation.view.ControlDecoration;
import com.foundation.view.AbstractMultiResourceHolder;
import com.foundation.view.AbstractResourceHolder;
import com.foundation.view.IResourceHolderComponent;
import com.foundation.view.JefImage;
import com.foundation.view.resource.AbstractResourceService;
/*
* The decoration control used to display a ControlDecoration on another control.
* This uses a peer system where this decoration control exists in the same container as its decorated control.
* The layout of the container recognizes this decoration as an implementation of IOverlay and it therefore places it so it overlaps the decorated control in the correct corner.
*/
public class Decoration extends Canvas implements IOverlay, IResourceHolderComponent, MouseMoveListener, MouseTrackListener, DisposeListener {
private IDecorationContainer decorationContainer;
private Point size = new Point(10, 10);
private ControlDecoration decoration;
private ResourceHolder imageHolder = new ResourceHolder(this);
private ResourceHolder toolTipTextHolder = new ResourceHolder(this);
private Image image = null;
private ToolTip toolTip;
/**
* Decoration constructor.
* @param decorationContainer The decoration container used to access the peer and parent, as well as certain system resources.
* @param decoration The control decoration data.
*/
public Decoration(IDecorationContainer decorationContainer, ControlDecoration decoration) {
super(decorationContainer.getDecorationParent(), SWT.NO_FOCUS);
if(decoration == null) {
throw new IllegalArgumentException("Must provide a decoration.");
}//if//
this.decorationContainer = decorationContainer;
this.decoration = decoration;
getPeerControl().addDisposeListener(this);
imageHolder.setValue(decoration.getImage());
toolTipTextHolder.setValue(decoration.getToolTip());
//setBackgroundMode(SWT.INHERIT_FORCE);
addListener(SWT.Paint, new Listener() {
public void handleEvent(Event event) {
if(Decoration.this.image != null) {
event.gc.drawImage(Decoration.this.image, 0, 0);
}//if//
}//handleEvent()//
});
addMouseTrackListener(this);
addMouseMoveListener(this);
}//Decoration()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
*/
public void widgetDisposed(DisposeEvent event) {
if(!isDisposed()) {
dispose();
}//if//
}//widgetDisposed()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Widget#dispose()
*/
public void dispose() {
getPeerControl().removeDisposeListener(this);
if(image != null) {
decorationContainer.destroyImage(image);
}//if//
imageHolder.release();
toolTipTextHolder.release();
super.dispose();
decorationContainer = null;
}//dispose()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)
*/
public Point computeSize(int wHint, int hHint, boolean changed) {
return size;
}//computeSize()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Control#getSize()
*/
public Point getSize() {
return size;
}//getSize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IOverlay#getPeerControl()
*/
public Control getPeerControl() {
return decorationContainer.getDecorationPeer();
}//getPeerControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IOverlay#getHorizontalOffset()
*/
public int getHorizontalOffset() {
return -2;
}//getWidthOffset()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IOverlay#getVerticalOffset()
*/
public int getVerticalOffset() {
return -2;
}//getHeightOffset()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IOverlay#getCorner()
*/
public int getPosition() {
return decoration.getPosition();
}//getCorner()//
/* (non-Javadoc)
* @see com.foundation.view.IResourceHolderComponent#getResourceService()
*/
public AbstractResourceService getResourceService() {
return decorationContainer.getResourceService();
}//getResourceService()//
/* (non-Javadoc)
* @see com.foundation.view.IResourceHolderComponent#resourceHolderChanged(com.foundation.view.AbstractMultiResourceHolder, com.common.util.IHashSet, java.lang.Object, java.lang.Object)
*/
public void resourceHolderChanged(AbstractMultiResourceHolder resourceHolder, IHashSet rows, Object oldValue, Object newValue) {
}//resourceHolderChanged()//
/* (non-Javadoc)
* @see com.foundation.view.IResourceHolderComponent#resourceHolderChanged(com.foundation.view.AbstractMultiResourceHolder, java.lang.Object, java.lang.Object, java.lang.Object)
*/
public void resourceHolderChanged(AbstractMultiResourceHolder resourceHolder, Object row, Object oldValue, Object newValue) {
}//resourceHolderChanged()//
/* (non-Javadoc)
* @see com.foundation.view.IResourceHolderComponent#resourceHolderChanged(com.foundation.view.AbstractResourceHolder, java.lang.Object, java.lang.Object)
*/
public void resourceHolderChanged(AbstractResourceHolder resourceHolder, Object oldValue, Object newValue, int flags) {
if(resourceHolder == imageHolder) {
if(image != null) {
decorationContainer.destroyImage(image);
}//if//
image = decorationContainer.createImage((JefImage) imageHolder.getValue());
//TODO: If the size changes, do we need to call layout?
if(image != null) {
Rectangle bounds = image.getBounds();
size.x = bounds.width;
size.y = bounds.height;
}//if//
redraw();
}//if//
else if(resourceHolder == toolTipTextHolder) {
if(oldValue == null) {
toolTip = new ToolTip(getShell(), SWT.BALLOON); //SWT.BALLOON | SWT.ICON_INFORMATION
//The text is bold and on top.//
//toolTip.setText((String) newValue);
//The message is normal text and shows below the text.//
toolTip.setMessage((String) newValue);
//If false, the user must click the tooltip to make it disappear.//
toolTip.setAutoHide(true);
}//if//
else if(newValue == null) {
toolTip.dispose();
toolTip = null;
}//else if//
else {
toolTip.setText((String) newValue);
}//else//
}//else if//
}//resourceHolderChanged()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
*/
public void mouseMove(MouseEvent event) {
if((toolTip != null) && (toolTip.getVisible())) {
toolTip.setVisible(false);
}//if//
}//mouseMove()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseTrackListener#mouseEnter(org.eclipse.swt.events.MouseEvent)
*/
public void mouseEnter(MouseEvent event) {
}//mouseEnter()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseTrackListener#mouseExit(org.eclipse.swt.events.MouseEvent)
*/
public void mouseExit(MouseEvent event) {
}//mouseExit()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseTrackListener#mouseHover(org.eclipse.swt.events.MouseEvent)
*/
public void mouseHover(MouseEvent event) {
if((toolTip != null) && (!toolTip.getVisible())) {
toolTip.setLocation(toDisplay(event.x, event.y));
toolTip.setVisible(true);
}//if//
}//mouseHover()//
}//Decoration//

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2003,2006 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;
public abstract class Dialog {
private org.eclipse.swt.widgets.Dialog dialog = null;
/**
* Dialog constructor.
*/
public Dialog() {
super();
}//Dialog()//
/**
* Gets the SWT dialog instance.
* @return The SWT dialog.
*/
protected org.eclipse.swt.widgets.Dialog getSwtDialog() {
return dialog;
}//getSwtDialog()//
/**
* Sets the SWT dialog instance.
* @return The SWT dialog.
*/
protected void setSwtDialog(org.eclipse.swt.widgets.Dialog dialog) {
this.dialog = dialog;
}//setSwtDialog()//
/**
* Gets the text displayed by the dialog.
* @return The dialog text.
*/
public String getText() {
return getSwtDialog().getText();
}//getText()//
/**
* Sets the dialog text.
* @param text The text to be displayed in the dialog.
*/
public void setText(String text) {
getSwtDialog().setText(text);
}//setText()//
}//Dialog//

View File

@@ -0,0 +1,86 @@
/*
* 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.view.swt;
import com.common.debug.*;
import com.foundation.view.*;
public class DirectoryDialog extends Dialog {
public static final String fileSeparator = System.getProperty("file.separator");
/**
* DirectoryDialog constructor.
* @param parent The parent view which is required for this dialog.
*/
public DirectoryDialog(IView parent) {
super();
if(parent instanceof Container) {
setSwtDialog(new org.eclipse.swt.widgets.DirectoryDialog(((Container) parent).getSwtControl().getShell()));
}//if//
else {
Debug.log("Error: Cannot create a dialog without a valid SWT parent control.");
}//else//
}//DirectoryDialog()//
/**
* DirectoryDialog constructor.
* @param parent The parent view which is required for this dialog.
* @param style No styles are currently permissable.
*/
public DirectoryDialog(IView parent, int style) {
super();
if(parent instanceof Container) {
setSwtDialog(new org.eclipse.swt.widgets.DirectoryDialog(((Container) parent).getSwtControl().getShell(), style));
}//if//
else {
Debug.log("Error: Cannot create a dialog without a valid SWT parent control.");
}//else//
}//DirectoryDialog()//
/**
* Gets the SWT directory dialog instance.
* @return The SWT directory dialog.
*/
private org.eclipse.swt.widgets.DirectoryDialog getSwtDirectoryDialog() {
return (org.eclipse.swt.widgets.DirectoryDialog) getSwtDialog();
}//getSwtDirectoryDialog()//
/**
* Gets the dialog message.
* @return The message to be displayed to the user.
*/
public String getMessage() {
return getSwtDirectoryDialog().getMessage();
}//getMessage()//
/**
* Sets the dialog message.
* @param message The message to be displayed to the user.
*/
public void setMessage(String message) {
getSwtDirectoryDialog().setMessage(message);
}//setMessage()//
/**
* Gets the directory path the user will see.
* @return The directory seen by the user.
*/
public String getFilterPath() {
return getSwtDirectoryDialog().getFilterPath();
}//getFilterPath()//
/**
* Sets the directory path the user will see.
* @param filterPath The directory seen by the user.
*/
public void setFilterPath(String filterPath) {
getSwtDirectoryDialog().setFilterPath(filterPath);
}//setFilterPath()//
/**
* Opens the dialog making it visible to the user.
* @return The directory of the first selected file. This will be null if an error occured.
*/
public String open() {
return getSwtDirectoryDialog().open();
}//open()//
}//DirectoryDialog//

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,774 @@
/*
* Copyright (c) 2007,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import com.common.debug.Debug;
import com.common.util.*;
import com.foundation.view.*;
import com.foundation.view.resource.ResourceReference;
import com.foundation.view.swt.util.SwtUtilities;
/**
* A simple list of strings in a box with an optional vertical and horizontal scroll bar and allowing single or multiple selections.
*/
public class EnhancedList extends TableComponent implements SelectionListener {
public static final int STYLE_SINGLE = SWT.SINGLE;
public static final int STYLE_MULTI = SWT.MULTI;
/** Converts the collection item to a string used to show the item to the user. */
protected MultiResourceAssociation itemText = new MultiResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_TEXT, false, null);
/** Converts the collection item to an image used to show the item to the user. */
protected MultiResourceAssociation itemImage = new MultiResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_IMAGE, false, null);
/** The only column used by the table. */
private TableColumn column;
/** Fixes a bug in the table where by a double click event gets fired twice. */
private int lastDoubleClickTime = 0;
/** A flag to temporarily disable the delay when synchronizing the selection before sending the double click message. */
private boolean disableAutoSynchronizeDelay = false;
/** A flag indicating whether the control's selection events should be ignored temporarily. */
protected boolean suspendSelectionEvents = false;
/**
* The data stored by the table item under the data reference, describes the row being rendered.
*/
protected class ListRowObject extends TableRowObject {
public int width = -1;
public int height = -1;
/** A holder for the value of the container image. */
private ResourceHolder imageHolder = null;
/**
* ListRowObject constructor.
* @param value The value being represented.
*/
public ListRowObject(Object value) {
super(value);
}//ListRowObject()//
/* (non-Javadoc)
* @see com.foundation.view.IResourceHolderComponent#resourceHolderChanged(com.foundation.view.AbstractResourceHolder, java.lang.Object, java.lang.Object)
*/
public void resourceHolderChanged(AbstractResourceHolder resourceHolder, Object oldValue, Object newValue, int flags) {
verifyThread();
if(resourceHolder == imageHolder) {
if(controlItems != null) {
IIterator itemIterator = controlItems.iterator();
while(itemIterator.hasNext()) {
TableItem next = (TableItem) itemIterator.next();
destroyImage(next.getImage());
next.setImage(0, createImage((JefImage) newValue));
}//while//
}//if//
else if(controlItem != null) {
destroyImage(((TableItem) controlItem).getImage());
((TableItem) controlItem).setImage(0, createImage((JefImage) newValue));
}//else if//
}//if//
else {
super.resourceHolderChanged(resourceHolder, oldValue, newValue, flags);
}//else//
}//resourceHolderChanged()//
/**
* Releases any resources held by the row object.
*/
public void dispose() {
if(imageHolder != null) imageHolder.release();
super.dispose();
}//dispose()//
}//ListRowObject//
/**
* EnhancedList constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_MULTI
* @see #STYLE_SINGLE
*/
public EnhancedList(Container parent, String name, int style) {
super(parent, name, style);
setAllowMultiSelection(((style & STYLE_MULTI) > 0));
}//EnhancedList()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.Table(((Container) getContainer()).getSwtParent(), style | SWT.FULL_SELECTION));
getSwtWidget().setData(this);
getSwtTable().setHeaderVisible(false);
getSwtTable().setLinesVisible(false);
column = new TableColumn(getSwtTable(), 0);
column.setWidth(10);
}//initializeControl()//
/**
* Sets the association container used to access the item text.
* @param container The item text association metadata.
*/
public void setItemTextAssociation(MultiAssociationContainer container) {
verifyThread();
this.itemText.setAssociations(container);
}//setItemTextAssociation()//
/**
* Sets the association container used to access the item text.
* @param container The item text association metadata.
*/
public void setItemImageAssociation(MultiAssociationContainer container) {
verifyThread();
this.itemImage.setAssociations(container);
}//setItemImageAssociation()//
/**
* Sets the row image resource.
* @param image The image to be displayed for each row.
*/
public void setDefaultItemImage(JefImage image) {
verifyThread();
this.itemImage.setDefaultValue(image);
}//setDefaultItemImage()//
/**
* Sets the row image resource.
* @param image The image to be displayed for each row.
*/
public void setDefaultItemImage(ResourceReference image) {
verifyThread();
this.itemImage.setDefaultValue(image);
}//setDefaultItemImage()//
/**
* Adjusts the visible range of items to show some or all of the selections.
*/
public void showSelection() {
verifyThread();
getSwtTable().showSelection();
}//showSelection()//
/**
* Gets the index of the top most visible item.
* @return The top most visible item's index.
*/
public Integer getTopIndex() {
verifyThread();
return new Integer(getSwtTable().getTopIndex());
}//getTopIndex()//
/**
* Sets the index of the top most visible item.
* @parma topIndex The top most visible item's index.
*/
public void setTopIndex(Integer topIndex) {
verifyThread();
getSwtTable().setTopIndex(topIndex.intValue());
}//setTopIndex()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.MultiResourceAssociation, java.lang.Object)
*/
protected void internalOnValueChanged(MultiResourceAssociation resourceAssociation, Object alteredItem, Object data, boolean isUpdate) {
ListRowObject rowObject = (ListRowObject) data;
if(resourceAssociation == itemText) {
if(itemText.refresh(alteredItem)) {
String text = (String) itemText.getValue(alteredItem);
if(rowObject.controlItems != null) {
IIterator itemIterator = rowObject.controlItems.iterator();
while(itemIterator.hasNext()) {
((TableItem) itemIterator.next()).setText(0, text == null ? "" : text);
}//while//
}//if//
else if(rowObject.controlItem != null) {
((TableItem) rowObject.controlItem).setText(0, text == null ? "" : text);
}//else if//
}//if//
}//if//
else if(resourceAssociation == itemImage) {
if(itemImage.refresh(alteredItem)) {
Object value = itemImage.getValue(alteredItem);
if(rowObject.imageHolder == null && value != null) {
rowObject.imageHolder = new ResourceHolder(rowObject);
}//if//
rowObject.imageHolder.setValue(value);
if(rowObject.imageHolder != null && value == null) {
rowObject.imageHolder.release();
rowObject.imageHolder = null;
}//if//
}//if//
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, alteredItem, data, isUpdate);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#internalViewRefreshCollection(com.common.util.ICollection, com.common.util.ICollection)
*/
protected void internalViewRefreshCollection(ICollection newCollection, ICollection oldCollection) {
if(newCollection != null) {
IIterator itemIterator = newCollection.iterator();
//Remove all existing rows of data.//
controlRemoveAll();
//Get the array of strings representing the list contents.//
while(itemIterator.hasNext()) {
Object item = itemIterator.next();
TableRowObject rowObject = getRowObject(item);
Object controlItem;
//Add the row to the control and then track the item it generates.//
controlItem = controlAddRow(rowObject, -1);
rowObject.addControlItem(controlItem);
}//while//
}//if//
else {
//Remove all existing rows of data.//
controlRemoveAll();
forceSelectionEvent();
}//else//
//If the selection was invalid previously then refresh the selection since it may no longer be invalid.//
if(isSelectionInvalid()) {
internalViewRefreshSelection();
}//if//
}//internalViewRefreshCollection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
getSwtTable().addSelectionListener(this);
getSwtTable().addListener(SWT.Resize, new Listener() {
public void handleEvent(Event event) {
Rectangle area = getSwtTable().getClientArea();
int requiredWidth = 0;
for(int index = 0; index < getSwtTable().getItemCount(); index++) {
ListRowObject itemData = (ListRowObject) getSwtTable().getItem(index).getData();
if(itemData != null) {
requiredWidth = Math.max(requiredWidth, itemData.width);
}//if//
}//for//
if(requiredWidth < area.width) {
column.setWidth(area.width);
}//if//
else {
column.setWidth(requiredWidth);
}//else//
}//handleEvent()//
});
itemText.initialize(true);
itemImage.initialize(true);
super.internalViewInitialize();
}//internalViewInitialize()//
/**
* Initializes the measure item listener.
*/
protected void initializeMeasureItemListener() {
getSwtTable().addListener(SWT.MeasureItem, new Listener() {
public void handleEvent(Event event) {
TableItem item = (TableItem) event.item;
ListRowObject itemData = (ListRowObject) item.getData();
//TODO: This should never be null, but for some reason it is happening occasionally.
if(itemData != null) {
if(itemData.width == -1 || itemData.height == -1) {
String text = item.getText(event.index);
Image image = item.getImage(event.index);
event.width = 0;
event.height = 0;
if(text != null && text.length() > 0) {
Point size = event.gc.textExtent(text);
event.width += size.x;
event.height = size.y;
}//if//
if(image != null) {
Rectangle size = image.getBounds();
event.width += size.x;
event.height = Math.max(size.y, event.height);
}//if//
itemData.width = event.width;
itemData.height = event.height;
}//if//
else {
event.width = itemData.width;
event.height = itemData.height;
}//else//
}//if//
//Debug.log("Measured: " + event.width);
}//handleEvent()//
});
}//initializeMeasureItemListener()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
if((getSwtTable() != null) && (!getSwtTable().isDisposed())) {
getSwtTable().removeSelectionListener(this);
controlRemoveAll();
}//if//
else {
//Debug.log(new RuntimeException("ERROR: Failed to call controlRemoveAll() which is required to clean up any font/color/image resources."));
}//else//
super.internalViewRelease();
itemText.release();
itemImage.release();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#createRowObject(java.lang.Object)
*/
protected TableRowObject createRowObject(Object value) {
return new ListRowObject(value);
}//createRowObject()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#registerItem(java.lang.Object, com.foundation.view.swt.TableComponent.TableRowObject)
*/
protected void registerItem(Object item, TableRowObject rowObject) {
ListRowObject listRowObject = (ListRowObject) rowObject;
//TODO: Need to pass in the ListRowObject
itemText.registerItem(item, rowObject);
itemText.refresh(item);
itemImage.registerItem(item, rowObject);
if(itemImage.refresh(item)) {
if(listRowObject.imageHolder == null) {
listRowObject.imageHolder = new ResourceHolder(listRowObject);
}//if//
listRowObject.imageHolder.setValue(itemImage.getValue(item), false);
}//if//
super.registerItem(item, rowObject);
}//registerItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#unregisterItem(java.lang.Object)
*/
protected void unregisterItem(Object item) {
itemText.unregisterItem(item);
itemImage.unregisterItem(item);
super.unregisterItem(item);
}//unregisterItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#unregisterItems()
*/
protected void unregisterItems() {
itemText.unregisterAllItems();
itemImage.unregisterAllItems();
super.unregisterItems();
}//unregisterItems()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#getAllowUserItems()
*/
protected boolean getAllowUserItems() {
return false;
}//getAllowUserItems()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#getAutoSynchronizeSelectionDelay()
*/
protected long getAutoSynchronizeSelectionDelay() {
return disableAutoSynchronizeDelay ? 0 : super.getAutoSynchronizeSelectionDelay();
}//getAutoSynchronizeSelectionDelay()//
/**
* Processes a double click on a table item.
*/
protected void doDoubleClick() {
if(getDoubleClickMethod() != null) {
if(getDoubleClickMethod().getIsValueHolderAssociated()) {
getDoubleClickMethod().invoke(null, true); //For now we will assume no parameters. It would be nice to pass the selection perhaps.//
}//if//
else {
Object selection = null;
//Determine which selection to invoke the method on.//
if(getAllowMultiSelection()) {
ICollection selections = getModelSelections();
if((selections != null) && (selections.getSize() > 0)) {
selection = selections.iterator().next();
}//if//
}//if//
else {
selection = getModelSelection();
}//else//
if(selection != null) {
//Invoke the method on the selection object if there is one.//
getDoubleClickMethod().invoke(selection, null, true);
}//if//
}//else//
}//if//
}//doDoubleClick()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent event) {
if(event.widget == getSwtTable()) {
//Fix a bug in the table where a double click event is fired twice.//
if(lastDoubleClickTime != event.time) {
if(getDoubleClickMethod() != null) {
//Set the synchronize delay to zero so the synchronize occurs immediatly.//
disableAutoSynchronizeDelay = true;
try {
//Synchronize the selection.//
synchronizeSelection();
//Force any selection task to complete prior to sending the double click.//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
autoSynchronizeSelectionTask.run();
}//if//
}//synchronized//
//Send the double click message.//
doDoubleClick();
}//try//
finally {
//Reset the delay and send the messages.//
disableAutoSynchronizeDelay = false;
}//finally//
lastDoubleClickTime = event.time;
}//if//
else {
widgetSelected(event);
}//else//
}//if//
}//if//
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent event) {
if((!suspendSelectionEvents) && ((event == null) || (event.widget == getSwtTable()))) {
synchronizeSelection();
}//if//
}//widgetSelected()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#controlAddColumn(com.foundation.view.swt.TableComponent.AbstractColumn, int)
*/
protected void controlAddColumn(AbstractColumn columnData, int columnIndex) {
}//controlAddColumn()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#controlAddColumn(com.foundation.view.swt.TableComponent.AbstractColumn)
*/
protected void controlAddColumn(AbstractColumn columnData) {
}//controlAddColumn()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#controlRemoveColumn(int)
*/
protected void controlRemoveColumn(int columnIndex) {
}//controlRemoveColumn()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#controlAddRow(com.foundation.view.swt.TableComponent.TableRowObject, java.lang.Object[], int)
*/
protected Object controlAddRow(TableRowObject rowObject, int index) {
TableItem tableItem = null;
Table table = getSwtTable();
Object item = rowObject.getValue();
String cellText = (String) itemText.getValue(item);
tableItem = index == -1 ? new TableItem(table, 0, index = table.getItemCount()) : new TableItem(table, 0, index);
try {
JefColor rowForegroundColor = rowObject.rowForegroundColorCustomHolder != null ? (JefColor) rowObject.rowForegroundColorCustomHolder.getValue() : null;
JefColor rowBackgroundColor = rowObject.rowBackgroundColorCustomHolder != null ? (JefColor) rowObject.rowBackgroundColorCustomHolder.getValue() : null;
tableItem.setText(0, cellText == null ? "" : cellText);
tableItem.setImage(0, createImage(((ListRowObject) rowObject).imageHolder != null ? (JefImage) ((ListRowObject) rowObject).imageHolder.getValue() : null));
//Determine the correct foreground color.//
if(rowForegroundColor == null) {
//If odd use the alt color if available, otherwise the primary, otherwise null.//
if((index % 2) == 1) {
if(rowForegroundColorAltHolder != null) {
rowForegroundColor = (JefColor) rowForegroundColorAltHolder.getValue();
}//if//
else if(rowForegroundColorHolder != null) {
rowForegroundColor = (JefColor) rowForegroundColorHolder.getValue();
}//else if//
}//if//
else if(rowForegroundColorHolder != null) {
rowForegroundColor = (JefColor) rowForegroundColorHolder.getValue();
}//else if//
}//if//
//Determine the correct background color.//
if(rowBackgroundColor == null) {
//If odd use the alt color if available, otherwise the primary, otherwise null.//
if((index % 2) == 1) {
if(rowBackgroundColorAltHolder != null) {
rowBackgroundColor = (JefColor) rowBackgroundColorAltHolder.getValue();
}//if//
else if(rowBackgroundColorHolder != null) {
rowBackgroundColor = (JefColor) rowBackgroundColorHolder.getValue();
}//else if//
}//if//
else if(rowBackgroundColorHolder != null) {
rowBackgroundColor = (JefColor) rowBackgroundColorHolder.getValue();
}//else if//
}//if//
//Set the row coloring.//
tableItem.setBackground(createColor(rowBackgroundColor));
tableItem.setForeground(createColor(rowForegroundColor));
//Set the row font.//
if(rowObject.rowFontHolder != null) {
tableItem.setFont(createFont((JefFont[]) rowObject.rowFontHolder.getValue()));
}//if//
//If this wasn't the last row and alternate colors are provided then we must update the coloring of the subsiquent rows.//
if((rowBackgroundColorAltHolder != null || rowForegroundColorAltHolder != null) && index < table.getItemCount() + 1) {
updateRowColors(index + 1);
}//if//
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
tableItem.setData(rowObject);
return tableItem;
}//controlAddRow()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#controlRemoveRow(java.lang.Object)
*/
protected void controlRemoveRow(Object itemData) {
TableItem tableItem = (TableItem) itemData;
//Dispose of any color, font, or image resources used.//
destroyImage(tableItem.getImage());
destroyColor(tableItem.getBackground());
destroyColor(tableItem.getForeground());
destroyFont(tableItem.getFont());
for(int columnIndex = 0; columnIndex < getSwtTable().getColumnCount(); columnIndex++) {
destroyImage(tableItem.getImage(columnIndex));
destroyColor(tableItem.getBackground(columnIndex));
destroyColor(tableItem.getForeground(columnIndex));
destroyFont(tableItem.getFont(columnIndex));
}//for//
tableItem.dispose();
updateRowColors(0); //TODO: Is it easier to update all, or figure out what the index of the item was?
}//controlRemoveRow()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#controlAddSelection(java.lang.Object)
*/
protected void controlAddSelection(Object itemData) {
if(!getSwtTable().isDisposed()) {
TableItem tableItem = (TableItem) itemData;
int count = getSwtTable().getSelectionCount();
getSwtTable().select(getSwtTable().indexOf(tableItem));
if(count == 0) {
getSwtTable().showItem(tableItem);
}//if//
}//if//
}//controlAddSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#controlIsSelected(java.lang.Object)
*/
protected boolean controlIsSelected(Object itemData) {
TableItem tableItem = (TableItem) itemData;
return getSwtTable().isSelected(getSwtTable().indexOf(tableItem));
}//controlIsSelected()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#controlOrderRows(int[])
*/
protected void controlOrderRows(int[] mapping) {
int columnCount = getSwtTable().getColumnCount();
TableItem[] tableItems = getSwtTable().getItems();
int tableItemCount = tableItems.length;
IList newTableItems = new LiteList(tableItemCount + 100);
int selectionIndex = getAllowMultiSelection() ? 0 : getSwtTable().getSelectionIndex();
int[] selectionIndices = getAllowMultiSelection() ? getSwtTable().getSelectionIndices() : null;
stopRendering();
suspendSelectionEvents = true;
try {
//Order the rows.//
for(int index = 0; index < tableItemCount; index++) {
TableItem tableItem = (TableItem) tableItems[mapping[index]];
TableItem newTableItem = new TableItem(getSwtTable(), tableItem.getStyle(), index);
newTableItem.setChecked(tableItem.getChecked());
newTableItem.setGrayed(tableItem.getGrayed());
newTableItem.setText(tableItem.getText());
newTableItem.setImage(tableItem.getImage());
newTableItem.setBackground(tableItem.getBackground());
newTableItem.setForeground(tableItem.getForeground());
newTableItem.setFont(tableItem.getFont());
newTableItem.setData(tableItem.getData());
for(int column = 0; column < columnCount; column++) {
newTableItem.setText(column, tableItem.getText(column));
newTableItem.setImage(column, tableItem.getImage(column));
newTableItem.setBackground(column, tableItem.getBackground(column));
newTableItem.setForeground(column, tableItem.getForeground(column));
newTableItem.setFont(column, tableItem.getFont(column));
}//for//
newTableItems.add(newTableItem);
((ListRowObject) tableItem.getData()).replaceControlItem(tableItem, newTableItem);
tableItem.dispose();
}//for//
//Refresh the selection.//
if(getAllowMultiSelection()) {
if(selectionIndices != null && selectionIndices.length > 0) {
for(int index = 0; index < selectionIndices.length; index++) {
selectionIndices[index] = mapping[selectionIndices[index]];
}//for//
getSwtTable().setSelection(selectionIndices);
}//if//
}//if//
else {
if(selectionIndex >= 0) {
selectionIndex = mapping[selectionIndex];
getSwtTable().setSelection(selectionIndex);
}//if//
}//else//
}//try//
finally {
startRendering();
suspendSelectionEvents = false;
}//finally//
}//controlOrderRows()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#controlRemoveSelection(java.lang.Object)
*/
protected void controlRemoveSelection(Object itemData) {
if(!getSwtTable().isDisposed()) {
TableItem tableItem = (TableItem) itemData;
getSwtTable().deselect(getSwtTable().indexOf(tableItem));
}//if//
}//controlRemoveSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#controlSetColumnHeaderData(int, java.lang.Object)
*/
protected void controlSetColumnHeaderData(int columnIndex, Object data) {
}//controlSetColumnHeaderData()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#controlSetSelection(java.lang.Object)
*/
protected void controlSetSelection(Object itemData) {
if(!getSwtTable().isDisposed()) {
TableItem tableItem = (TableItem) itemData;
getSwtTable().setSelection(getSwtTable().indexOf(tableItem));
getSwtTable().showItem(tableItem);
}//if//
}//controlSetSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#controlSetSelections(com.common.util.IList)
*/
protected void controlSetSelections(IList itemData) {
if(!getSwtTable().isDisposed()) {
TableItem[] tableItems = new TableItem[itemData.getSize()];
//Collect the table items for the selected rows.//
for(int index = 0; index < tableItems.length; index++) {
tableItems[index] = (TableItem) itemData.get(index);
}//for//
getSwtTable().setSelection(tableItems);
if(tableItems.length > 0) {
getSwtTable().showItem(tableItems[0]);
}//if//
}//if//
}//controlSetSelections()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#controlRemoveAll()
*/
protected void controlRemoveAll() {
TableItem[] items = getSwtTable().getItems();
for(int index = 0; index < items.length; index++) {
destroyImage(items[index].getImage());
}//for//
getSwtTable().removeAll();
}//controlRemoveAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#controlGetSelections()
*/
protected TableRowObject[] controlGetSelections() {
TableRowObject[] results = null;
if(getSwtTable().getSelectionCount() > 0) {
TableItem[] tableItems = getSwtTable().getSelection();
results = new TableRowObject[tableItems.length];
for(int index = 0; index < tableItems.length; index++) {
results[index] = (TableRowObject) tableItems[index].getData();
}//for//
}//if//
return results;
}//controlGetSelections()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlGetSelection()
*/
protected TableRowObject controlGetSelection() {
int selectionIndex = getSwtTable().getSelectionIndex();
return selectionIndex == -1 ? null : (TableRowObject) getSwtTable().getItem(selectionIndex).getData();
}//controlGetSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TableComponent#controlRemoveAllSelections()
*/
protected void controlRemoveAllSelections() {
if(!getSwtTable().isDisposed()) {
getSwtTable().deselectAll();
}//if//
}//controlRemoveAllSelections()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlGetSelectionCount()
*/
protected int controlGetSelectionCount() {
return (!getSwtTable().isDisposed()) ? getSwtTable().getSelectionCount() : 0;
}//controlGetSelectionCount()//
/**
* Forces the selection event handler to be called.
*/
protected void forceSelectionEvent() { //Should call widgetSelected implemented by the subclass. This name may need to change.//
widgetSelected(null);
}//forceSelectionEvent()//
}//EnhancedList//

View File

@@ -0,0 +1,262 @@
/*
* Copyright (c) 2005,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import com.common.debug.*;
import com.common.thread.*;
import org.eclipse.swt.widgets.Display;
/**
* An event loop runnable to handle window events.
* Because SWT requires that the thread creating the display be the thread doing the event handling, we must create the display and return it to the frame.
* <p><b>This is the THICK client event loop for SWT.</b></p>
*/
public class EventLoop implements Runnable, ISwtViewRequestHandler, ISingleThreadedContext {
/** The one and only event loop runnable. */
private static final EventLoop singleton = new EventLoop();
/** Whether the event thread has initialized. */
private boolean isInitialized = false;
/** Work around for Sun's profiling bug: If you start the thread in either the constructor or the static initializer it doesn't actually start when profiling. */
private volatile boolean isStarted = false;
/** Whether a thread has requested the event thread stop. */
private volatile boolean stop = false;
/** Whether the event thread has stopped. */
private volatile boolean isStopped = false;
/** Whether this event loop is wrappering a pre-existing event loop thread. */
private volatile boolean isWrapper = false;
/** The display being supported. */
private Display display = null;
/**
* EventLoop constructor.
*/
private EventLoop() {
}//EventLoop()//
/**
* Gets the one and only event loop runnable.
* @return The one and only message pump for SWT.
*/
public static EventLoop getSingleton() {
return singleton;
}//getSingleton()//
/**
* Starts the event loop on the calling thread and then executes the runnable on a separate thread.
* @param runnable The runnable to execute once this thread is actively in the event loop.
*/
public void startOnThisThread(final Runnable runnable) {
startOnThisThread(null, runnable);
}//startOnThisThread()//
/**
* Starts the event loop on the calling thread and then executes the runnable on a separate thread.
* @param display The optional display to be used.
* @param runnable The runnable to execute once this thread is actively in the event loop.
*/
public void startOnThisThread(final Display display, final Runnable runnable) {
isStarted = true;
ThreadService.run(new Runnable() {
public void run() {
synchronized(singleton) {
while(!singleton.isInitialized) {
try {
singleton.wait(0);
}//try//
catch(Throwable e) {
Debug.handle(e);
}//catch//
}//while//
}//synchronized//
runnable.run();
}//run()//
});
run(display);
}//startOnThisThread()//
/**
* Starts the event loop.
* <p>Work around for Sun's profiling bug: If you start the thread in either the constructor or the static initializer it doesn't actually start when profiling.</p>
*/
private void start() {
new Thread(singleton, "SWT Event Loop").start();
synchronized(singleton) {
while(!singleton.isInitialized) {
try {
singleton.wait(0);
}//try//
catch(Throwable e) {
Debug.handle(e);
}//catch//
}//while//
}//synchronized//
}//start()//
/**
* Creates the frame component, and then processes events and requests until told to stop.
*/
public void run() {
run(null);
}//run()//
/**
* Creates the frame component, and then processes events and requests until told to stop.
* @param display The optional display to be used. This should be non null if swt is already started.
*/
public void run(Display display) {
ThreadService.setIsInSingleThreadedContext(this);
this.display = display == null ? new Display() : display;
synchronized(this) {
isInitialized = true;
notifyAll();
}//synchronized//
if(display == null) {
enterEventLoop();
//Notify other threads that we have successfully stopped.//
synchronized(this) {
isStopped = true;
notifyAll();
}//synchronized//
ThreadService.setIsInSingleThreadedContext(null);
//Dispose of the display so that this thread can once again be an event handler (for a different view).//
this.display.dispose();
}//if//
else {
isWrapper = true;
}//else//
}//run()//
/**
* Enters a new event loop.
*/
protected void enterEventLoop() {
//Keep handling events until the shell is disposed or the stop flag is raised.//
while(!isStopping()) {
//Handle the next event, or sleep until an event is available.//
if(!display.readAndDispatch()) {
display.sleep();
}//if//
}//while//
}//enterEventLoop()//
/* (non-Javadoc)
* @see com.foundation.view.swt.ISwtViewRequestHandler#getDisplay()
*/
public Display getDisplay() {
return display;
}//getDisplay()//
/**
* Stops the event loop and disposes of the display object (not the shell).
*/
public synchronized void stop() {
if(isStarted) {
//If this event loop just wrappers a thread then nothing really needs stopping, otherwise notify the thread to stop and wait for it to finish.//
if(isWrapper) {
isStopped = true;
isStarted = false;
ThreadService.setIsInSingleThreadedContext(null);
}//if//
else {
stop = true;
while(!isStopped) {
display.wake();
try {
wait(100);
}//try//
catch(Throwable e) {
Debug.handle(e);
}//catch//
}//while//
}//else//
}//if//
}//stop()//
/**
* Determines whether the event loop is in the process of stopping.
* @return Whether a request to stop the event loop has been made.
*/
public synchronized boolean isStopping() {
return stop;
}//isStopping()//
/**
* Determines whether the event loop has completly stopped.
* @return Whether events are no longer being processed.
*/
public synchronized boolean isStopped() {
return isStopped;
}//isStopped()//
/**
* Processes a request through the event thread. This is required to access any SWT method due to the design of SWT.
* @param request The object that will be run when the request is processed.
* @param synchronous Whether the thread should block until the request has been processed (should be true if a result is desired).
*/
public void processRequest(Runnable request, boolean synchronous) {
//Note: This is slopy threading code, but 1) It is necessitated by bugs in the Sun JDK (see the comment in isStarted); and 2) It shouldn't matter since this will be called by only one thread the first time around - the main thread that starts the initial view and must run it on the event loop thread.//
if(!isStarted) {
isStarted = true;
start();
}//if//
if(synchronous) {
display.syncExec(request);
}//if//
else {
display.asyncExec(request);
}//else//
}//processRequest()//
/* (non-Javadoc)
* @see com.foundation.event.IRequestHandler#isRunning()
*/
public boolean isRunning() {
//Note: We are playing fast and loose with the threading rules here. Both of these are volatile meaning we should get timely notification if this boat is stopping, but it is possible that an runnable could be queued for processing and there isn't a thread to process it, but only during a shutdown of the application.//
return (!stop) && (!isStopped);
}//isRunning()//
/* (non-Javadoc)
* @see com.foundation.event.IRequestHandler#isRequestThread()
*/
public boolean isRequestThread() {
return display != null && Thread.currentThread() == display.getThread();
}//isRequestThread()//
/* (non-Javadoc)
* @see com.foundation.event.IRequestHandler#execute(com.common.thread.IRunnable, boolean)
*/
public Object execute(IRunnable runnable, boolean synchronous) {
Object result = null;
if(isRunning()) {
//Make sure we don't have the event thread creating requests since it would deadlock the system.//
if(!isRequestThread() || !synchronous) {
Request request = new Request(runnable);
processRequest(request, synchronous);
if(synchronous) {
result = request.getReturnValue();
}//if//
}//if//
else {
//The calling thread is the event thread, so there is no need to pass the request through the event thread!.//
result = runnable.run();
}//else//
}//if//
return result;
}//execute()//
/* (non-Javadoc)
* @see com.foundation.event.IRequestHandler#execute(com.common.thread.IRunnable)
*/
public Object execute(IRunnable runnable) {
return execute(runnable, true);
}//execute()//
/* (non-Javadoc)
* @see com.foundation.event.IRequestHandler#executeAsync(com.common.thread.IRunnable)
*/
public void executeAsync(IRunnable runnable) {
execute(runnable, false);
}//executeAsync()//
}//EventLoopRunnable//

View File

@@ -0,0 +1,845 @@
/*
* Copyright (c) 2006,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.ExpandItem;
import com.common.debug.Debug;
import com.common.util.ICollection;
import com.common.util.IIterator;
import com.common.util.IList;
import com.common.util.LiteHashMap;
import com.common.util.LiteList;
import com.foundation.controller.DecorationManager;
import com.foundation.controller.ViewController;
import com.foundation.util.IInlineCollectionObservable;
import com.foundation.util.IInlineCollectionObserver;
import com.foundation.util.IInlineIndexedCollectionObservable;
import com.foundation.util.IInlineIndexedCollectionObserver;
import com.foundation.view.AbstractDecoration;
import com.foundation.view.IAbstractComponent;
import com.foundation.view.ISingleResourceAssociationChangeListener;
import com.foundation.view.ResourceAssociation;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
import com.foundation.view.resource.AbstractResourceService;
public class ExpandBar extends Container implements ControlListener, Component.IComponentListener {
public static final int STYLE_VERTICAL_SCROLL = SWT.V_SCROLL;
/** A collection of Component and ItemsHolder instances which define the parts of this expand bar. */
private IList items = new LiteList(10, 50);
/** A mapping of ExpandItem's indexed by the related component. */
private LiteHashMap expandItemsByComponentMap = new LiteHashMap(15);
/** A flag to suspend the customized behavior when adding a control. This lets the item holder add and remove items without the expand bar attempting to add and remove items also. */
private boolean suspendCustomComponentBehavior = false;
/** The spacing used by the bar. */
private SingleResourceAssociation spacing = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, false, null);
/**
* The public interface for interacting with the items holder.
*/
public interface IItemsHolder {
/**
* Sets the association container used to access the items.
* @param container The items association metadata.
*/
public void setItemsAssociation(SingleAssociationContainer container);
}//IItemsHolder//
/**
* A place holder for zero or more items which are set based on a resource association which can return a view controller or a list of view controllers, one for each item.
*/
private class ItemsHolder implements IItemsHolder, ISingleResourceAssociationChangeListener, IInlineCollectionObserver, IInlineIndexedCollectionObserver, Component.IComponentListener {
/** Allows one association to return either a collection of controllers, or one controller which will be turned into a tab page. */
private SingleResourceAssociation items = new SingleResourceAssociation(ExpandBar.this, this, getViewContext(), SingleResourceAssociation.TYPE_OBJECT, false, null);
/** The PagesHolder or Component which the pages in this PagesHolder follow in the tab order. */
private Object followsComponent = null;
/** The previous collection of view controllers. */
private IList viewControllers = new LiteList(1, 15);
/** ExpandItem instances mapped by their corresponding view controllers. */
private LiteHashMap expandItemsByViewControllerMap = new LiteHashMap(15);
/** A two way (one to one) mapping between the Component instances and their ViewController instances. */
private LiteHashMap componentControllerMapping = new LiteHashMap(30);
/** Temporarily suspends processing of events fired by registered collections. */
private boolean suspendCollectionEvents = false;
public ItemsHolder(Object followsComponent) {
this.followsComponent = followsComponent;
}//ItemsHolder()//
/* (non-Javadoc)
* @see com.foundation.view.swt.ExpandBar.IItemsHolder#setItemsAssociation(com.foundation.view.SingleAssociationContainer)
*/
public void setItemsAssociation(SingleAssociationContainer container) {
verifyThread();
this.items.setAssociations(container);
}//setItemsAssociation()//
public void initialize() {
items.initialize();
refreshItems();
}//initialize()//
public void release() {
IIterator iterator = viewControllers.iterator();
items.release();
//Release the tab resources and cleanup the mappings and listeners.//
while(iterator.hasNext()) {
internalRemoveItem((ViewController) iterator.next());
}//while//
componentControllerMapping.removeAll();
componentControllerMapping = null;
expandItemsByViewControllerMap.removeAll();
expandItemsByViewControllerMap = null;
viewControllers.removeAll();
viewControllers = null;
followsComponent = null;
items = null;
}//release()//
/**
* Gets the ExpandItem that the items of this holder follow.
* @return The expand item that the expand items related to this holder follow in the expand item ordering.
*/
public ExpandItem getPreviousExpandItem() {
ExpandItem result = null;
if(followsComponent instanceof ItemsHolder) {
result = ((ItemsHolder) followsComponent).getLastExpandItem();
}//if//
else if(followsComponent instanceof Component) {
result = (ExpandItem) expandItemsByComponentMap.get(followsComponent);
}//else if//
return result;
}//getPreviousExpandItem()//
/**
* Gets the last expand item for this holder.
* @return The last ExpandItem instance which can be used as the previous ExpandItem for the component that follows this holder. This will only be null if there are no items in this holder and there are no items in front of this holder.
*/
public ExpandItem getLastExpandItem() {
ExpandItem result = null;
if(viewControllers.getSize() > 0) {
result = (ExpandItem) expandItemsByViewControllerMap.get(viewControllers.getLast());
}//if//
else {
result = getPreviousExpandItem();
}//else//
return result;
}//getLastExpandItem()//
/**
* Refreshes the expand items represented by this holder.
*/
protected void refreshItems() {
Object oldValue = items.getValue();
if(items.refresh()) {
Object newValue = items.getValue();
ExpandItem previous = getPreviousExpandItem();
int previousIndex = previous != null ? getSwtExpandBar().indexOf(previous) + 1 : 0;
//Remove listeners from the old value.//
if(oldValue instanceof IInlineIndexedCollectionObservable) {
((IInlineIndexedCollectionObservable) oldValue).removeCollectionObserver(this);
}//if//
else if(oldValue instanceof IInlineCollectionObservable) {
((IInlineCollectionObservable) oldValue).removeCollectionObserver(this);
}//else if//
//If the new value is a collection or object then add and remove pages as required, and add listeners as required.//
if(newValue instanceof ICollection) {
IIterator iterator = ((ICollection) newValue).iterator();
//Add tabs for all the view controllers.//
while(iterator.hasNext()) {
Object next = iterator.next();
//Ignore non-view controller objects.//
if(next instanceof ViewController) {
ViewController controller = (ViewController) next;
int index = viewControllers != null ? viewControllers.getIndexOf(controller) : -1;
if(index != -1) {
ExpandItem newExpandItem = internalRecreateItem(controller, previousIndex);
viewControllers.remove(index);
//Note we don't just increment the index since they could get moved by the changes made by updating the tabs.//
if(newExpandItem != null) {
previousIndex = getSwtExpandBar().indexOf(newExpandItem) + 1;
}//if//
}//if//
else {
ExpandItem newExpandItem = internalAddItem(controller, previousIndex);
//Note we don't just increment the index since they could get moved by the changes made by updating the tabs.//
if(newExpandItem != null) {
previousIndex = getSwtExpandBar().indexOf(newExpandItem) + 1;
}//if//
}//else//
}//if//
}//while//
//Remove the previous view controller(s).//
removeOldItems(viewControllers);
//Add the controllers to the list of view controllers.//
viewControllers.addAll((ICollection) newValue);
//Prevent collection events from notifying us of existing items in the collection.//
suspendCollectionEvents = true;
//Add a listener to the collection so we get change events.//
if(newValue instanceof IInlineIndexedCollectionObservable) {
((IInlineIndexedCollectionObservable) newValue).addCollectionObserver(this);
}//if//
else if(newValue instanceof IInlineCollectionObservable) {
((IInlineCollectionObservable) newValue).addCollectionObserver(this);
}//else if//
//Re-enable the collection events.//
suspendCollectionEvents = false;
}//if//
else if(newValue instanceof ViewController) {
ViewController controller = (ViewController) newValue;
//Add the controller's page.//
internalAddItem(controller, previousIndex);
//Remove the previous view controller(s).//
removeOldItems(viewControllers);
//Add the one controller to the list of view controllers.//
viewControllers.add(controller);
}//else if//
}//if//
}//refreshItems()//
/**
* Removes the old expand item from the expand bar.
* @param viewControllers The collection of view controllers no longer in the expand bar.
* @param oldValue The previous value
*/
private void removeOldItems(IList viewControllers) {
while(viewControllers.getSize() > 0) {
ViewController controller = (ViewController) viewControllers.remove(viewControllers.getSize() - 1);
//Remove each controller's item and close the controller.//
internalRemoveItem(controller);
controller.close();
}//while//
}//removeOldPages()//
/**
* Adds a expand item to the panel for the given view controller.
* @param viewController The view controller whose view component will be displayed in the expand item.
* @param index The index of this expand item, which will be used to set the expand item ordering.
* @return The new expand item.
*/
protected ExpandItem internalAddItem(ViewController viewController, int index) {
ExpandItem expandItem = null;
suspendCustomComponentBehavior = true;
try {
if(viewController != null) {
Component component;
viewController.openPartial(ExpandBar.this, getViewContext());
component = (Component) viewController.getView();
expandItem = new org.eclipse.swt.widgets.ExpandItem(getSwtExpandBar(), 0, index);
if(component instanceof Container) {
Image image = component.getContainerImage();
expandItem.setText(component.getContainerTitle() == null ? "" : component.getContainerTitle());
expandItem.setImage(image);
}//if//
else {
expandItem.setText("");
}//else//
//Swt does not yet support tool tip text for expand items.//
//expandItem.setToolTipText(component.getToolTipText());
expandItem.setControl(component.getSwtControl());
expandItem.setData(component);
component.registerListener(this);
expandItemsByViewControllerMap.put(viewController, expandItem);
componentControllerMapping.put(viewController, component);
componentControllerMapping.put(component, viewController);
component.getSwtControl().addControlListener(ExpandBar.this);
expandItemsByComponentMap.put(component, expandItem);
}//if//
else {
Debug.log("Error: Invalid component. Unable to add the component as a tab in the expand bar.");
}//else//
}//try//
finally {
suspendCustomComponentBehavior = false;
}//finally//
return expandItem;
}//internalAddItem()//
/**
* Removes a expand item from the panel for the given related view component.
* @param viewController The view controller whose view component's expand item will be removed.
*/
protected void internalRemoveItem(ViewController viewController) {
suspendCustomComponentBehavior = true;
try {
ExpandItem expandItem = (ExpandItem) expandItemsByViewControllerMap.remove(viewController);
Component component = (Component) viewController.getView();
if(component == null) {
component = (Component) componentControllerMapping.get(viewController);
}//if//
//Unregister the component data listener.//
if(component != null) {
component.unregisterListener(this);
componentControllerMapping.remove(component);
}//if//
//Dispose of the old expand item and its image.//
if(expandItem != null) {
//Note: Don't dispose of the image because it comes from the component's container-image property whose lifecycle is managed by the component.//
expandItem.dispose();
}//if//
if((component.getSwtControl() != null) && (!component.getSwtControl().isDisposed())) {
component.getSwtControl().removeControlListener(ExpandBar.this);
}//if//
componentControllerMapping.remove(viewController);
expandItemsByComponentMap.remove(component);
}//try//
finally {
suspendCustomComponentBehavior = false;
}//finally//
}//internalRemoveItem()//
/**
* Recreates the view controller's expand item by removing the old expand item and adding a new one at the given index.
* @param viewController The view controller whose view component's expand item will be removed and re-added.
* @param index The index of the recreated expand item.
* @return The new expand item.
*/
protected ExpandItem internalRecreateItem(ViewController viewController, int index) {
ExpandItem oldExpandItem = (ExpandItem) expandItemsByViewControllerMap.remove(viewController);
ExpandItem expandItem = null;
if((oldExpandItem != null) && (viewController != null) && (((Component) viewController.getView()).getSwtControl() != null)) {
expandItem = new org.eclipse.swt.widgets.ExpandItem(getSwtExpandBar(), 0, index);
expandItem.setText(oldExpandItem.getText());
expandItem.setImage(oldExpandItem.getImage());
//Not supported by SWT yet.//
//expandItem.setToolTipText(oldExpandItem.getToolTipText());
expandItem.setControl(oldExpandItem.getControl());
expandItem.setHeight(oldExpandItem.getHeight());
expandItem.setData(oldExpandItem.getData());
//Replace the tab item in the mapping by view controller.//
expandItemsByViewControllerMap.put(viewController, expandItem);
}//if//
else {
Debug.log("Error: Invalid component. Unable to recreate the component as a tab in the expand bar.");
//Attempt to cleanup after the controller.//
if(oldExpandItem != null) {
internalRemoveItem(viewController);
}//if//
}//else//
//Dispose of the old expand item.//
oldExpandItem.dispose();
return expandItem;
}//internalRecreateItem()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#onValueChanged(com.foundation.view.ResourceAssociation, int)
*/
public void onValueChanged(ResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == items) {
refreshItems();
}//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) {
}//onModelExternallyChanged()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#addMessageHold()
*/
public void addMessageHold() {
}//addMessageHold()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#removeMessageHold()
*/
public void removeMessageHold() {
}//removeMessageHold()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#startChanges(int)
*/
public void startChanges(int changeCount) {
//TabPanel.this.addMessageHold();
}//startChanges()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#stopChanges()
*/
public void stopChanges() {
//TabPanel.this.removeMessageHold();
}//stopChanges()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineCollectionObserver#valueAdded(java.lang.Object)
*/
public void valueAdded(Object value) {
if((!suspendCollectionEvents) && (value instanceof ViewController)) {
ExpandItem last = getLastExpandItem();
int tabIndex = last == null ? 0 : getSwtExpandBar().indexOf(last) + 1;
internalAddItem((ViewController) value, tabIndex);
}//if//
}//valueAdded()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#valueAdded(java.lang.Object, int)
*/
public void valueAdded(Object value, int index) {
if((!suspendCollectionEvents) && (value instanceof ViewController)) {
ExpandItem previous = getPreviousExpandItem();
int tabIndex = (previous == null ? 0 : getSwtExpandBar().indexOf(previous) + 1) + index;
internalAddItem((ViewController) value, tabIndex);
}//if//
}//valueAdded()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineCollectionObserver#valueRemoved(java.lang.Object)
*/
public void valueRemoved(Object value) {
if((!suspendCollectionEvents) && (value instanceof ViewController)) {
internalRemoveItem((ViewController) value);
}//if//
}//valueRemoved()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#valueRemoved(java.lang.Object, int)
*/
public void valueRemoved(Object value, int index) {
valueRemoved(value);
}//valueRemoved()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#removingAll()
*/
public void removingAll() {
if(!suspendCollectionEvents) {
IIterator iterator = viewControllers.iterator();
startChanges(viewControllers.getSize());
while(iterator.hasNext()) {
valueRemoved(iterator.next());
}//while//
stopChanges();
}//if//
}//removingAll()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#valuesSorted(int[])
*/
public void valuesSorted(int[] mapping) {
if(!suspendCollectionEvents) {
ExpandItem previousExpandItem = getPreviousExpandItem();
int nextIndex = previousExpandItem == null ? 0 : getSwtExpandBar().indexOf(previousExpandItem) + 1;
ExpandItem[] oldExpandItems = new ExpandItem[mapping.length];
startChanges(0);
//Reorder the tab items by adding new tab items before the old ones.//
for(int index = 0; index < mapping.length; index++) {
int oldIndex = nextIndex + index + mapping[index];
ExpandItem oldExpandItem = getSwtExpandBar().getItem(oldIndex);
ExpandItem expandItem = new org.eclipse.swt.widgets.ExpandItem(getSwtExpandBar(), 0, nextIndex);
ViewController controller = (ViewController) componentControllerMapping.get(oldExpandItem.getData());
expandItem.setText(oldExpandItem.getText());
expandItem.setImage(oldExpandItem.getImage());
//SWT does not yet support tool tips on expand items.//
//expandItem.setToolTipText(oldExpandItem.getToolTipText());
expandItem.setControl(oldExpandItem.getControl());
expandItem.setData(oldExpandItem.getData());
nextIndex++;
oldExpandItems[index] = oldExpandItem;
//Replace the expand item in the mapping by view controller.//
expandItemsByViewControllerMap.put(controller, expandItem);
}//for//
//Remove the old expand items.//
for(int index = 0; index < oldExpandItems.length; index++) {
oldExpandItems[index].dispose();
}//for//
stopChanges();
}//if//
}//valuesSorted()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container.IContainerListener#imageChanged(com.foundation.view.swt.Container, org.eclipse.swt.graphics.Image)
*/
public void imageChanged(Component component, Image newImage) {
ViewController controller = (ViewController) componentControllerMapping.get(component);
if(controller != null) {
ExpandItem expandItem = (ExpandItem) expandItemsByViewControllerMap.get(controller);
if(expandItem != null) {
expandItem.setImage(newImage);
}//if//
}//if//
}//imageChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container.IContainerListener#titleChanged(com.foundation.view.swt.Container, java.lang.String)
*/
public void titleChanged(Component component, String newTitle) {
ViewController controller = (ViewController) componentControllerMapping.get(component);
if(controller != null) {
ExpandItem expandItem = (ExpandItem) expandItemsByViewControllerMap.get(controller);
if(expandItem != null) {
expandItem.setText(newTitle == null ? "" : newTitle);
}//if//
}//if//
}//titleChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component.IComponentListener#toolTipTextChanged(com.foundation.view.swt.Component, java.lang.String)
*/
public void toolTipTextChanged(Component component, String newToolTipText) {
ViewController controller = (ViewController) componentControllerMapping.get(component);
if(controller != null) {
ExpandItem expandItem = (ExpandItem) expandItemsByViewControllerMap.get(controller);
if(expandItem != null) {
//SWT does not yet support tool tip text on expand items.//
//expandItem.setToolTipText(newToolTipText);
}//if//
}//if//
}//toolTipTextChanged()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#getResourceService()
*/
public AbstractResourceService getResourceService() {
return ExpandBar.this.getResourceService();
}//getResourceService()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#getDecorationManager()
*/
public DecorationManager getDecorationManager() {
return ExpandBar.this.getDecorationManager();
}//getDecorationManager()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#addDecoration(com.foundation.view.AbstractDecoration)
*/
public void addDecoration(AbstractDecoration decoration) {
//Never used.//
}//addDecoration()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#removeDecoration(com.foundation.view.AbstractDecoration)
*/
public void removeDecoration(AbstractDecoration decoration) {
//Never used.//
}//removeDecoration()//
}//ItemsHolder//
/**
* ExpandBar constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_VERTICAL_SCROLL
*/
public ExpandBar(Container parent, String name, int style) {
super(parent, name, style);
}//ExpandBar()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.ExpandBar(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT button that represents this button.
* @return The SWT button providing visualization for this button.
*/
public org.eclipse.swt.widgets.ExpandBar getSwtExpandBar() {
return (org.eclipse.swt.widgets.ExpandBar) getSwtControl();
}//getSwtExpandBar()//
/**
* Sets the spacing.
* @param spacing The spacing that will be used by the component.
*/
public void setSpacing(Integer spacing) {
verifyThread();
this.spacing.setDefaultValue(spacing);
}//setSpacing()//
/**
* Sets the association container used to access the spacing.
* @param container The spacing association metadata.
*/
public void setSpacingAssociation(SingleAssociationContainer container) {
verifyThread();
this.spacing.setAssociations(container);
}//setSpacingAssociation()//
/**
* Adds N items to the expand bar, where the items come from an association with the model.
* @return The item holder which can be used to add associations.
*/
public IItemsHolder addPages() {
ItemsHolder holder = new ItemsHolder(items.getSize() > 0 ? items.getLast() : null);
items.add(holder);
return holder;
}//addPages()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container#addComponent(com.foundation.view.IAbstractComponent)
*/
public void addComponent(IAbstractComponent component) {
super.addComponent(component);
if(!suspendCustomComponentBehavior) {
items.add(component);
if(isInitialized()) {
internalAddItem((Component) component);
}//if//
}//if//
}//addComponent()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container#removeComponent(com.foundation.view.IAbstractComponent)
*/
public void removeComponent(IAbstractComponent component) {
if(!suspendCustomComponentBehavior) {
if(isInitialized()) {
internalRemoveItem((Component) component);
}//if//
items.remove(component);
}//if//
super.removeComponent(component);
}//removeComponent()//
/**
* Adds an expand item to the panel for the given view component.
* <p>Tabs displaying a view controller's view should set the expand item's data to be the view controller instead of the view component.</p>
* @param component The view component that will be displayed in the expand item.
*/
protected void internalAddItem(Component component) {
if((component != null) && (component.getSwtControl() != null)) {
ExpandItem expandItem = new org.eclipse.swt.widgets.ExpandItem(getSwtExpandBar(), 0);
Image image = component.getContainerImage();
expandItem.setText(component.getContainerTitle() == null ? "" : component.getContainerTitle());
expandItem.setImage(image);
//SWT does not yet support tool tip text for expand items.//
//expandItem.setToolTipText(component.getToolTipText());
expandItem.setControl(component.getSwtControl());
expandItem.setData(component);
expandItemsByComponentMap.put(component, expandItem);
component.registerListener(this);
component.getSwtControl().addControlListener(this);
}//if//
else {
Debug.log("Error: Invalid component. Unable to add the component as an item in the expand bar.");
}//else//
}//internalAddItem()//
/**
* Removes an expand item from the panel for the given related view component.
* @param component The view component associated with the expand item to be removed.
*/
protected void internalRemoveItem(Component component) {
ExpandItem expandItem = (ExpandItem) expandItemsByComponentMap.remove(component);
//Dispose of the old expand item.//
if(expandItem != null) {
expandItem.dispose();
}//if//
if((component.getSwtControl() != null) && (!component.getSwtControl().isDisposed())) {
component.getSwtControl().removeControlListener(this);
}//if//
component.unregisterListener(this);
}//internalRemoveItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitializeAll()
*/
public void internalViewInitializeAll() {
IIterator iterator = null;
//Note: We are using the initialize all to setup the tabs so that they can be released before releasing the children.//
super.internalViewInitializeAll();
iterator = items.iterator();
//Initialize the tabs.//
while(iterator.hasNext()) {
Object page = iterator.next();
if(page instanceof ItemsHolder) {
((ItemsHolder) page).initialize();
}//if//
else {
//Ignore the component.//
}//else//
}//for//
}//internalViewInitializeAll()//
/* (non-Javadoc)
* @see com.foundation.view.IView#viewReleaseAll()
*/
public void internalViewReleaseAll() {
IIterator iterator = items.iterator();
//Note: We are using the release all to release the tabs so that they can be released before releasing the children.//
while(iterator.hasNext()) {
Object page = iterator.next();
if(page instanceof Component) {
internalRemoveItem((Component) page);
}//if//
else if(page instanceof ItemsHolder) {
((ItemsHolder) page).release();
}//else if//
else {
//Ignore the component.//
}//else//
}//for//
super.internalViewReleaseAll();
}//internalViewReleaseAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
spacing.initialize();
//Complete the initialization of the component items since the components should have set themselves up by now.//
for(int index = 0; index < items.getSize(); index++) {
if(items.get(index) instanceof Component) {
internalAddItem((Component) items.get(index));
}//if//
}//for//
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
super.internalViewRelease();
spacing.release();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
for(int index = 0; index < items.getSize(); index++) {
Object page = items.get(index);
if(page instanceof ItemsHolder) {
((ItemsHolder) page).refreshItems();
}//if//
else {
//Ignore the component.//
}//else//
}//for//
super.internalViewRefresh();
internalViewRefreshSpacing();
}//internalViewRefresh()//
/**
* Refreshes the spacing.
*/
protected void internalViewRefreshSpacing() {
if(spacing.refresh()) {
Integer spacing = (Integer) this.spacing.getValue();
if(spacing != null) {
getSwtExpandBar().setSpacing(spacing.intValue());
}//if//
resize();
}//if//
}//internalViewRefreshSpacing()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == spacing) {
internalViewRefreshSpacing();
}//if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component.IComponentListener#toolTipTextChanged(com.foundation.view.swt.Component, java.lang.String)
*/
public void toolTipTextChanged(Component component, String newToolTipText) {
ExpandItem expandItem = (ExpandItem) expandItemsByComponentMap.get(component);
if(expandItem != null && !expandItem.isDisposed()) {
//SWT does not yet support tool tip text for expand items.//
//expandItem.setToolTipText(newToolTipText);
}//if//
}//toolTipTextChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component.IComponentListener#imageChanged(com.foundation.view.swt.Component, org.eclipse.swt.graphics.Image)
*/
public void imageChanged(Component container, Image image) {
ExpandItem expandItem = (ExpandItem) expandItemsByComponentMap.get(container);
if(expandItem != null && !expandItem.isDisposed()) {
expandItem.setImage(image);
}//if//
}//imageChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component.IComponentListener#titleChanged(com.foundation.view.swt.Component, java.lang.String)
*/
public void titleChanged(Component container, String newTitle) {
ExpandItem expandItem = (ExpandItem) expandItemsByComponentMap.get(container);
if(expandItem != null && !expandItem.isDisposed()) {
expandItem.setText(newTitle);
}//if//
}//titleChanged()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ControlListener#controlMoved(org.eclipse.swt.events.ControlEvent)
*/
public void controlMoved(ControlEvent e) {
}//controlMoved()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ControlListener#controlResized(org.eclipse.swt.events.ControlEvent)
*/
public void controlResized(ControlEvent e) {
//TODO: Is this the right place for this?
((ExpandItem) expandItemsByComponentMap.get(e.widget.getData())).setHeight(((Control) e.widget).computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
}//controlResized()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container#internalLayout()
*/
protected void internalLayout() {
ExpandItem[] items = getSwtExpandBar().getItems();
//TODO: Is this the right place for this?
//Set the height of all the expand items.//
for(int index = 0; index < items.length; index++) {
items[index].setHeight(items[index].getControl().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
}//for//
super.internalLayout();
}//internalLayout()//
}//ExpandBar//

View File

@@ -0,0 +1,154 @@
/*
* Copyright (c) 2003,2006 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 java.io.File;
import org.eclipse.swt.SWT;
import com.common.debug.*;
import com.foundation.view.*;
public class FileDialog extends Dialog {
public static final int STYLE_OPEN = SWT.OPEN;
public static final int STYLE_SAVE = SWT.SAVE;
public static final int STYLE_MULTI = SWT.MULTI;
/**
* FileDialog constructor.
*/
private FileDialog() {
super();
}//FileDialog()//
/**
* FileDialog constructor.
* @param parent The parent view which is required for this dialog.
*/
public FileDialog(IView parent) {
super();
if(parent instanceof Container) {
org.eclipse.swt.widgets.Shell shell = ((Container) parent).getSwtControl().getShell();
shell.setFocus();
setSwtDialog(new org.eclipse.swt.widgets.FileDialog(shell));
}//if//
else {
Debug.log("Error: Cannot create a dialog without a valid SWT parent control.");
}//else//
}//FileDialog()//
/**
* FileDialog constructor.
* @param parent The parent view which is required for this dialog.
* @param style Zero or more of the STYLE_xxx identifiers defined by this class.
*/
public FileDialog(IView parent, int style) {
super();
if(parent instanceof Container) {
setSwtDialog(new org.eclipse.swt.widgets.FileDialog(((Container) parent).getSwtControl().getShell(), style));
}//if//
else {
Debug.log("Error: Cannot create a dialog without a valid SWT parent control.");
}//else//
}//FileDialog()//
/**
* Gets the SWT file dialog instance.
* @return The SWT file dialog.
*/
protected org.eclipse.swt.widgets.FileDialog getSwtFileDialog() {
return (org.eclipse.swt.widgets.FileDialog) getSwtDialog();
}//getSwtFileDialog()//
/**
* Gets the file name of the first file selected by the user.
* @return One of the selected file names.
*/
public String getFileName() {
return getSwtFileDialog().getFileName();
}//getFileName()//
/**
* Gets the path + file name of the first file selected by the user.
* @return One of the selected file names.
*/
public String getPathAndFileName() {
return getFilterPath() + File.separator + getFileName();
}//getPathAndFileName()//
/**
* Sets the initially selected file in the dialog.
* @return The initially selected file.
*/
public void setFileName(String fileName) {
getSwtFileDialog().setFileName(fileName);
}//setFileName()//
/**
* Gets all of the file names selected by the user.
* @return An array of the selected file names.
*/
public String[] getFileNames() {
return getSwtFileDialog().getFileNames();
}//getFileNames()//
/**
* Gets all of the path + file names selected by the user.
* @return An array of the selected file names.
*/
public String[] getPathAndFileNames() {
String[] fileNames = getFileNames();
for(int index = 0; index < fileNames.length; index++) {
fileNames[index] = getFilterPath() + File.separator + fileNames[index];
}//for//
return fileNames;
}//getPathAndFileNames()//
/**
* Gets the extensions used to filter what files the user sees.
* @return An array of file extensions that the user may view or save as.
*/
public String[] getFilterExtensions() {
return getSwtFileDialog().getFilterExtensions();
}//getFilterExtensions()//
/**
* Sets the extensions used to filter what files the user sees.
* @param filterExtensions An array of file extensions that the user may view or save as.
*/
public void setFilterExtensions(String[] filterExtensions) {
getSwtFileDialog().setFilterExtensions(filterExtensions);
}//setFilterExtensions()//
/**
* Gets the file names used to filter what files the user sees.
* @return An array of file names that the user may view or save as.
*/
public String[] getFilterNames() {
return getSwtFileDialog().getFilterNames();
}//getFilterNames()//
/**
* Sets the file names used to filter what files the user sees.
* @param filterNames An array of file names that the user may view or save as.
*/
public void setFilterNames(String[] filterNames) {
getSwtFileDialog().setFilterNames(filterNames);
}//setFilterNames()//
/**
* Gets the directory path the user will see.
* @return The directory seen by the user.
*/
public String getFilterPath() {
return getSwtFileDialog().getFilterPath();
}//getFilterPath()//
/**
* Sets the directory path the user will see.
* @param filterPath The directory seen by the user.
*/
public void setFilterPath(String filterPath) {
getSwtFileDialog().setFilterPath(filterPath);
}//setFilterPath()//
/**
* Opens the dialog making it visible to the user.
* @return The directory of the first selected file. This will be null if an error occured.
*/
public String open() {
return getSwtFileDialog().open();
}//open()//
}//FileDialog//

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 2007 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
public class FillLayout extends Layout {
private int type = SWT.HORIZONTAL;
private int marginWidth = 0;
private int marginHeight = 0;
private int spacing = 0;
/**
* FillLayout constructor.
* @param container The container that is using the layout.
*/
public FillLayout(IAbstractSwtContainer container) {
super(container);
}//FillLayout()//
/**
* FillLayout constructor.
* @param container The container that is using the layout.
*/
public FillLayout(ICellContainer container) {
super(container);
}//FillLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#createLayout(java.lang.Object)
*/
public org.eclipse.swt.widgets.Layout createLayout(Object rowObject) {
com.foundation.view.swt.layout.FillLayout result = new com.foundation.view.swt.layout.FillLayout();
result.type = type;
result.marginHeight = marginHeight;
result.marginWidth = marginWidth;
result.spacing = spacing;
return result;
}//createLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#initialize()
*/
public void initialize() {
}//initialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#refresh()
*/
public void refresh() {
}//refresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#synchronize()
*/
public void synchronize() {
}//synchronize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#release()
*/
public void release() {
}//release()//
/**
* Sets the layout type.
* @param type The layout type.
*/
public void setType(int type) {
this.type = type;
}//setType()//
/**
* Sets the layout margin width.
* @param marginWidth The layout margin width.
*/
public void setMarginWidth(int marginWidth) {
this.marginWidth = marginWidth;
}//setMarginWidth()//
/**
* Sets the layout margin height.
* @param marginHeight The layout margin height.
*/
public void setMarginHeight(int marginHeight) {
this.marginHeight = marginHeight;
}//setMarginHeight()//
/**
* Sets the layout spacing.
* @param spacing The layout spacing.
*/
public void setSpacing(int spacing) {
this.spacing = spacing;
}//setSpacing()//
}//FillLayout//

View File

@@ -0,0 +1,493 @@
/*
* Copyright (c) 2006,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
import com.common.comparison.Comparator;
import com.common.util.LiteHashMap;
import com.common.util.LiteList;
import com.foundation.view.LinkData;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
public class FontNameComboBox extends Component {
public static final int LINK_TARGET_SELECTION = Component.LAST_LINK_TARGET + 1;
public static final int LAST_LINK_TARGET = Component.LAST_LINK_TARGET + 1;
/** The selection state resource. */
private SingleResourceAssociation selection = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_TEXT, true, null);
/** The linkage for the selection. */
private Linkage selectionLinkage = new Linkage();
/** Whether the selection state is auto synchronized. */
private boolean autoSynchronizeSelection = true;
/** The last known selection used to prevent sending unnecessary messages. This value will be null if there isn't a selection. */
private String lastSelection = null;
private class FontNameCombo extends com.foundation.view.swt.custom.CustomCombo {
private org.eclipse.swt.widgets.Table table;
private org.eclipse.swt.widgets.Text editor;
private LiteList allFontMetadata;
private boolean isDisplayingSubset = false;
private boolean caseSensitive = false;
/** A flag to prevent the synchronization of the selection from causing a refresh of the list contents and re-display of the drop down. */
private boolean ignoreEditorChanges = false;
//private org.eclipse.swt.graphics.Image scalableFontImage = null;
//private org.eclipse.swt.graphics.Image unscalableFontImage = null;
/**
* Encapsulates metadata about the font that is relavant to the combo.
*/
private class FontMetadata {
public String name;
public boolean isScalable;
public Font font;
public FontMetadata(Display display, FontData fontData, boolean isScalable) {
this.font = new Font(display, fontData.getName(), 10, 0);
this.name = fontData.getName();
this.isScalable = isScalable;
}//FontMetadata()//
public void dispose() {
if(font != null) {
font.dispose();
}//if//
}//dispose()//
}//FontMetadata//
/**
* FontNameCombo constructor.
* @param parent A non-null widget which will be the parent of the new instance.
* @param style The style of widget to construct.
* @see SWT#RESIZE
* @see SWT#BORDER
*/
public FontNameCombo(Composite parent, int style) {
super(parent, style);
}//FontNameCombo()//
/**
* Gets the current selection text for the combo.
* <p>This will be the text in the text box.</p>
* @return The selection or an empty string if there is no selection.
*/
public String getSelection() {
return editor.getText() == null ? "" : editor.getText();
}//getSelection()//
/**
* Sets the current selection text for the combo.
* @param selection The selection or an empty string if there is no selection.
*/
public void setSelection(String selection) {
if(refreshDrop(selection == null ? "" : selection)) {
ignoreEditorChanges = true;
editor.setText(selection == null ? "" : selection);
ignoreEditorChanges = false;
}//if//
else {
//TODO: What should we do here - the font is not on this system!
//We could set the text to the selection and highlight it red to indicate the font is missing. We probably should also show the full font list in the drop box.
}//else//
//If the selection is not in the list then update the editor.//
if(isDisplayingSubset) {
if(table.getSelectionCount() == 1) {
int selectionIndex = table.getSelectionIndex();
String tableSelection = selectionIndex != -1 ? ((FontMetadata) table.getItem(selectionIndex).getData()).name : null;
editor.setText(tableSelection);
}//if//
else {
editor.setText("");
}//else//
}//if//
}//getSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.custom.CustomCombo#createDropControl(org.eclipse.swt.widgets.Shell)
*/
protected Control createDropControl(Shell parent) {
table = new org.eclipse.swt.widgets.Table(parent, SWT.SINGLE | SWT.FULL_SELECTION | SWT.V_SCROLL);
table.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent event) {
}//widgetDefaultSelected()//
public void widgetSelected(SelectionEvent event) {
hideDrop(true);
}//widgetSelected()//
});
return table;
}//createDropControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.custom.CustomCombo#createSelectionControl()
*/
protected Control createSelectionControl() {
editor = new org.eclipse.swt.widgets.Text(this, SWT.SINGLE | SWT.LEFT);
editor.addFocusListener(new FocusListener() {
public void focusLost(FocusEvent e) {
String text = editor.getText();
String selection = null;
if((text == null) || (text.trim().length() == 0)) {
if(isDisplayingSubset) {
updateTable(allFontMetadata);
isDisplayingSubset = false;
}//if//
}//if//
else {
if(isDisplayingSubset) {
selection = ((FontMetadata) table.getItem(table.getSelectionIndex()).getData()).name;
editor.setText(selection);
updateTable(allFontMetadata);
isDisplayingSubset = false;
}//if//
}//else//
selectionChanged(selection);
}//focusLost()//
public void focusGained(FocusEvent e) {
}//focusGained()//
});
editor.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
if(!ignoreEditorChanges) {
refreshDrop();
if(!isShowingDrop()) {
showDrop();
}//if//
//TODO: Do we need to force the focus back to the editor?
//TODO: Do we need to keep the drop from hiding?
}//if//
}//modifyText()//
});
return editor;
}//createSelectionControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.custom.CustomCombo#initialize()
*/
protected void initialize() {
}//initialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.custom.CustomCombo#postInitialize()
*/
protected void postInitialize() {
FontData[] fonts = table.getDisplay().getFontList(null, true);
LiteHashMap fontNameMap = new LiteHashMap(100);
allFontMetadata = new LiteList(fonts.length);
//Order the fonts by name.//
allFontMetadata.setOrderComparator(new Comparator() {
public int compare(Object value1, Object value2) {
return ((FontMetadata) value1).name.compareTo(((FontMetadata) value2).name);
}//compare()//
});
//Collect all the font metadata for scalable fonts.//
for(int index = 0; index < fonts.length; index++) {
FontMetadata metadata = null;
if((metadata = (FontMetadata) fontNameMap.get(fonts[index].getName())) != null) {
//TODO: Should we record in the metadata whether the font is capable of various styles and sizes?
}//if//
else {
metadata = new FontMetadata(table.getDisplay(), fonts[index], true);
allFontMetadata.add(metadata);
fontNameMap.put(fonts[index].getName(), metadata);
}//else//
}//for//
updateTable(allFontMetadata);
}//postInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.custom.CustomCombo#refreshDrop()
*/
protected void refreshDrop() {
refreshDrop(editor.getText() == null ? "" : editor.getText().trim());
}//refreshDrop()//
/**
* Refreshes the drop down table so it has the selection displayed.
* @param selection The table item to be selected. This should be an empty string if there isn't a selection.
* @return Whether the selection could be found. If not found then the drop control will be populated with the matching subset of the font names and the most likely match will be selected.
*/
protected boolean refreshDrop(String selection) {
boolean result = false;
if(selection == null || selection.length() == 0) {
table.setSelection(-1);
result = true;
}//if//
else if(allFontMetadata != null) {
for(int index = 0; (!result) && (index < allFontMetadata.getSize()); index++) {
if(areEqual(((FontMetadata) allFontMetadata.get(index)).name, selection)) {
if(isDisplayingSubset) {
updateTable(allFontMetadata);
isDisplayingSubset = false;
}//if//
table.setSelection(index);
result = true;
}//if//
}//for//
//If we couldn't find an exact match then find the closest thing and filter the list to all possible matches (placing starts with's first).//
if(!result) {
LiteList startsWithMatches = new LiteList(allFontMetadata.getSize());
LiteList containsMatches = new LiteList(allFontMetadata.getSize());
//Collect any matches.//
for(int index = 0; index < allFontMetadata.getSize(); index++) {
String next = ((FontMetadata) allFontMetadata.get(index)).name;
if(startsWith(next, selection)) {
startsWithMatches.add(allFontMetadata.get(index));
}//if//
else if(contains(next, selection)) {
containsMatches.add(allFontMetadata.get(index));
}//else if//
}//for//
//TODO: Sort matches by relavance.
//Collect all matches into one list.//
startsWithMatches.addAll(containsMatches);
isDisplayingSubset = true;
if(startsWithMatches.getSize() > 0) {
table.setSelection(0);
}//if//
}//if//
}//else if//
return result;
}//refreshDrop()//
/* (non-Javadoc)
* @see com.foundation.view.swt.custom.CustomCombo#synchronizeDrop()
*/
protected void synchronizeDrop() {
int selectionIndex = table.getSelectionIndex();
String selection = selectionIndex != -1 ? ((FontMetadata) table.getItem(selectionIndex).getData()).name : null;
String editorContents = selection == null ? "" : selection;
if(!Comparator.equals(editor.getText(), editorContents)) {
ignoreEditorChanges = true;
editor.setText(editorContents);
ignoreEditorChanges = false;
}//if//
if(!Comparator.equals(lastSelection, selection)) {
lastSelection = selection;
selectionChanged(selection);
}//if//
}//synchronizeDrop()//
/**
* Updates the table items to display the given font metadata objects.
* @param fontMetadata The fonts to be displayed in the table.
*/
private void updateTable(LiteList fontMetadata) {
table.removeAll();
for(int index = 0; index < fontMetadata.getSize(); index++) {
org.eclipse.swt.widgets.TableItem item = new org.eclipse.swt.widgets.TableItem(table, 0);
FontMetadata font = (FontMetadata) fontMetadata.get(index);
item.setFont(font.font);
item.setText(font.name);
//item.setImage(font.isScalable ? )
item.setData(font);
}//for//
}//updateTable()//
/**
* Determines whether the two strings are equivalent.
* @param s1 The first string.
* @param s2 The second string.
* @return Whether they are considered equal.
*/
private boolean areEqual(String s1, String s2) {
return caseSensitive ? s1.equals(s2) : s1.equalsIgnoreCase(s2);
}//areEqual()//
/**
* Determines whether the full string starts with the second string.
* @param fullString The full string to compare with.
* @param part The string part to compare against the first characters in the full string.
* @return Whether they are considered equal.
*/
private boolean startsWith(String fullString, String part) {
return caseSensitive ? fullString.toLowerCase().startsWith(part.toLowerCase()) : fullString.startsWith(part);
}//startsWith()//
/**
* Determines whether the full string contains the second string as a subset.
* @param fullString The full string to compare with.
* @param part The string part to compare against any subset of characters in the full string.
* @return Whether they are considered equal.
*/
private boolean contains(String fullString, String part) {
return caseSensitive ? fullString.toLowerCase().contains(part.toLowerCase()) : fullString.contains(part);
}//contains()//
}//FontNameCombo//
/**
* FontNameComboBox constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
*/
public FontNameComboBox(Container parent, String name, int style) {
super(parent, name, SWT.DROP_DOWN | SWT.READ_ONLY);
}//FontNameComboBox()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new FontNameCombo(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT control that represents this combo.
* @return The SWT control providing visualization for this combo.
*/
public FontNameCombo getSwtCombo() {
return (FontNameCombo) getSwtControl();
}//getSwtCombo()//
/**
* Gets the component selection.
* @return The selection.
*/
public String getSelection() {
verifyThread();
return (String) selection.getValue();
}//getSelection()//
/**
* Sets the component default selection.
* @param selection The selection.
*/
public void setSelection(String selection) {
verifyThread();
this.selection.setDefaultValue(selection);
}//setSelection()//
/**
* Sets the association container used to access the selection.
* @param container The selection association metadata.
*/
public void setSelectionAssociation(SingleAssociationContainer container) {
verifyThread();
this.selection.setAssociations(container);
}//setSelectionAssociation()//
/**
* Adds a link for the selection.
* @param link The local linkage for the selection.
*/
public void addSelectionLink(LinkData link) {
selectionLinkage.add(link);
}//addSelectionLink()//
/**
* Sets whether the control auto synchronizes the selection.
* @param autoSynchronizeSelection Whether the selection is automatically synchronized.
*/
public void setAutoSynchronizeSelection(boolean autoSynchronizeSelection) {
this.autoSynchronizeSelection = autoSynchronizeSelection;
}//setAutoSynchronizeSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
selection.initialize();
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
super.internalViewRelease();
selection.release();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalViewRefreshSelection();
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
super.internalViewSynchronize();
if(!autoSynchronizeSelection) {
String text = getSwtCombo().getSelection();
//Convert empty strings to no selection.//
selection.setValue(text == null || text.trim().length() == 0 ? null : text.trim());
}//if//
}//internalViewSynchronize()//
/**
* Refreshes the selection.
*/
protected void internalViewRefreshSelection() {
if(selection.refresh()) {
String selection = (String) this.selection.getValue();
if(!Comparator.equals(getSwtCombo().getSelection(), selection)) {
lastSelection = selection == null || selection.length() == 0 ? null : selection;
getSwtCombo().setSelection(selection);
selectionLinkage.invoke(selection);
}//if//
}//if//
}//internalViewRefreshSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnLinkInvoked(int, java.lang.Object)
*/
protected void internalOnLinkInvoked(int linkTarget, Object data) {
switch(linkTarget) {
case LINK_TARGET_SELECTION: {
String selection = data instanceof String ? (String) data : null;
if(!Comparator.equals(selection, getSwtCombo().getSelection())) {
getSwtCombo().setSelection(selection);
selectionChanged(selection);
}//if//
break;
}//case//
default: {
super.internalOnLinkInvoked(linkTarget, data);
break;
}//default//
}//switch//
}//internalOnLinkInvoked()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == selection) {
internalViewRefreshSelection();
}//if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/**
* Called when the selection is changed in the view control.
* @param selection The control's selection.
*/
protected void selectionChanged(String selection) {
if(autoSynchronizeSelection) {
this.selection.setValue(selection);
}//if//
selectionLinkage.invoke(selection);
}//selectionChanged()//
}//FontNameComboBox//

View File

@@ -0,0 +1,389 @@
/*
* Copyright (c) 2006,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import com.common.comparison.Comparator;
import com.foundation.view.LinkData;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
public class FontSizeComboBox extends Component {
public static final int LINK_TARGET_SELECTION = Component.LAST_LINK_TARGET + 1;
public static final int LAST_LINK_TARGET = Component.LAST_LINK_TARGET + 1;
/** The selection state resource. */
private SingleResourceAssociation selection = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, true, null);
/** The linkage for the selection. */
private Linkage selectionLinkage = new Linkage();
/** Whether the selection state is auto synchronized. */
private boolean autoSynchronizeSelection = true;
/**
* This combo allows the user to type an integer on a specified range, or pull down the drop box containing all numbers or a subset of available numbers.
*/
private class FontSizeCombo extends com.foundation.view.swt.custom.CustomCombo {
private org.eclipse.swt.widgets.List list;
private org.eclipse.swt.widgets.Text editor;
/** The displayed values in the combo drop down. */
private int[] listed;
/** The beginning of the range of valid values. */
private int start;
/** The end of the range of valid values. */
private int end;
/** The value to use when the user has not specified a value (ie: equivalent to null). */
private int empty;
/**
* FontSizeCombo constructor.
* @param parent A non-null widget which will be the parent of the new instance.
* @param style The style of widget to construct.
* @see SWT#RESIZE
* @see SWT#BORDER
*/
public FontSizeCombo(Composite parent, int style) {
super(parent, style);
}//FontSizeCombo()//
/**
* Sets the range data for the combo.
* <p>Note: This method tries to fix any data that is not correct.</p>
* @param start The start of the valid range of integers.
* @param end The end of the valid range.
* @param empty The value to use if the user removes all text from the combo.
* @param listed The list of listed numbers. This may not be null.
*/
private void setRange(int start, int end, int empty, int[] listed) {
String[] items = null;
//Ensure the ranges are correct.//
if(start > end) {
int temp = start;
start = end;
end = temp;
}//if//
if(empty < start) {
empty = start;
}//if//
if(empty > end) {
empty = end;
}//if//
this.start = start;
this.end = end;
this.empty = empty;
this.listed = listed;
//Update the list control.//
list.removeAll();
items = new String[listed.length];
for(int index = 0; index < listed.length; index++) {
items[index] = "" + listed[index];
}//for//
list.setItems(items);
}//setRange()//
/**
* Gets the integer selected in the view.
* @return The selected integer.
*/
public Integer getSelection() {
validateText();
return new Integer(editor.getText().trim());
}//getSelection()//
/**
* Sets the integer selected in the view.
* @param The selected integer.
*/
public void setSelection(Integer integer) {
editor.setText(integer == null ? "" : integer.toString());
for(int index = 0; (integer != null) && (index < listed.length); index++) {
if(listed[index] == integer.intValue()) {
list.setSelection(index);
integer = null;
}//if//
}//for//
}//setSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.custom.CustomCombo#createDropControl(org.eclipse.swt.widgets.Shell)
*/
protected Control createDropControl(Shell parent) {
list = new org.eclipse.swt.widgets.List(parent, SWT.SINGLE);
list.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent event) {
}//widgetDefaultSelected()//
public void widgetSelected(SelectionEvent event) {
hideDrop(true);
}//widgetSelected()//
});
return list;
}//createDropControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.custom.CustomCombo#createSelectionControl()
*/
protected Control createSelectionControl() {
//TODO: We should probably synchronize the value to the IntegerComboBox after a user types the value and after some time limit. We currently only synchronize upon focus lost.
editor = new org.eclipse.swt.widgets.Text(this, SWT.SINGLE | SWT.LEFT);
editor.addFocusListener(new FocusListener() {
public void focusLost(FocusEvent e) {
selectionChanged(getSelection());
}//focusLost()//
public void focusGained(FocusEvent e) {
}//focusGained()//
});
editor.addVerifyListener(new VerifyListener() {
public void verifyText(VerifyEvent event) {
if((event.text != null) && (event.text.length() != 0)) {
boolean isValid = true;
for(int index = 0; (isValid) && (index < event.text.length()); index++) {
char next = event.text.charAt(index);
if(!Character.isDigit(next)) {
//Allow the negative sign if the range allows negatives.//
if(!((start < 0) && (next == '-') && (event.start == 0) && (index == 0))) {
isValid = false;
}//if//
}//if//
}//for//
if(!isValid) {
event.doit = false;
}//if//
}//if//
}//verifyText()//
});
return editor;
}//createSelectionControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.custom.CustomCombo#initialize()
*/
protected void initialize() {
}//initialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.custom.CustomCombo#postInitialize()
*/
protected void postInitialize() {
setRange(1, 1638, 12, new int[] {8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72});
}//postInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.custom.CustomCombo#refreshDrop()
*/
protected void refreshDrop() {
String selection = editor.getText().trim();
int number = selection.length() == 0 ? 0 : Integer.parseInt(selection);
for(int index = 0; (selection != null) && (index < listed.length); index++) {
if(listed[index] == number) {
list.setSelection(index);
selection = null;
}//if//
}//for//
}//refreshDrop()//
/* (non-Javadoc)
* @see com.foundation.view.swt.custom.CustomCombo#synchronizeDrop()
*/
protected void synchronizeDrop() {
int selectionIndex = list.getSelectionIndex();
String selection = selectionIndex != -1 ? list.getItem(selectionIndex) : null;
if(selection != null) {
editor.setText(selection == null ? "" : selection);
selectionChanged(new Integer(selection));
}//if//
}//synchronizeDrop()//
/**
* Validates the text in the editor after the user finishes typing or before the value is synchronized to the data model.
* This method will replace the value if it does not meet the requirements.
*/
protected void validateText() {
//Replace no text with the empty value, and ensure that the value is on the right range.//
if(editor.getText().trim().length() == 0) {
editor.setText("" + empty);
}//if//
else {
long number = Long.parseLong(editor.getText().trim());
if(number < start) {
editor.setText("" + start);
refreshDrop();
}//if//
else if(number > end) {
editor.setText("" + end);
refreshDrop();
}//else if//
}//else//
}//validateText()//
}//FontSizeCombo//
/**
* FontSizeComboBox constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
*/
public FontSizeComboBox(Container parent, String name, int style) {
super(parent, name, SWT.DROP_DOWN);
}//FontSizeComboBox()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new FontSizeCombo(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT control that represents this combo.
* @return The SWT control providing visualization for this combo.
*/
public FontSizeCombo getSwtCombo() {
return (FontSizeCombo) getSwtControl();
}//getSwtCombo()//
/**
* Gets the component selection.
* @return The selection.
*/
public Integer getSelection() {
verifyThread();
return (Integer) selection.getValue();
}//getSelection()//
/**
* Sets the component default selection.
* @param selection The selection.
*/
public void setSelection(Integer selection) {
verifyThread();
this.selection.setDefaultValue(selection);
}//setSelection()//
/**
* Sets the association container used to access the selection.
* @param container The selection association metadata.
*/
public void setSelectionAssociation(SingleAssociationContainer container) {
verifyThread();
this.selection.setAssociations(container);
}//setSelectionAssociation()//
/**
* Adds a link for the selection.
* @param link The local linkage for the selection.
*/
public void addSelectionLink(LinkData link) {
selectionLinkage.add(link);
}//addSelectionLink()//
/**
* Sets whether the control auto synchronizes the selection.
* @param autoSynchronizeSelection Whether the selection is automatically synchronized.
*/
public void setAutoSynchronizeSelection(boolean autoSynchronizeSelection) {
this.autoSynchronizeSelection = autoSynchronizeSelection;
}//setAutoSynchronizeSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
selection.initialize();
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
super.internalViewRelease();
selection.release();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalViewRefreshSelection();
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
super.internalViewSynchronize();
if(!autoSynchronizeSelection) {
this.selection.setValue(getSwtCombo().getSelection());
}//if//
}//internalViewSynchronize()//
/**
* Refreshes the selection.
*/
protected void internalViewRefreshSelection() {
if(selection.refresh()) {
Integer selection = (Integer) this.selection.getValue();
if(!Comparator.equals(getSwtCombo().getSelection(), selection)) {
getSwtCombo().setSelection(selection);
selectionLinkage.invoke(selection);
}//if//
}//if//
}//internalViewRefreshSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnLinkInvoked(int, java.lang.Object)
*/
protected void internalOnLinkInvoked(int linkTarget, Object data) {
switch(linkTarget) {
case LINK_TARGET_SELECTION: {
Integer selection = data instanceof Integer ? (Integer) data : null;
if(!Comparator.equals(selection, getSwtCombo().getSelection())) {
getSwtCombo().setSelection(selection);
selectionChanged(selection);
}//if//
break;
}//case//
default: {
super.internalOnLinkInvoked(linkTarget, data);
break;
}//default//
}//switch//
}//internalOnLinkInvoked()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == selection) {
internalViewRefreshSelection();
}//if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/**
* Called when the selection is changed in the view control.
* @param selection The control's selection.
*/
protected void selectionChanged(Integer selection) {
if(autoSynchronizeSelection) {
this.selection.setValue(selection);
}//if//
selectionLinkage.invoke(selection);
}//selectionChanged()//
}//FontSizeComboBox//

View File

@@ -0,0 +1,117 @@
/*
* Copyright (c) 2007 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;
public class FormLayout extends Layout {
public int marginWidth = 0;
public int marginHeight = 0;
public int marginLeft = 0;
public int marginTop = 0;
public int marginRight = 0;
public int marginBottom = 0;
public int spacing = 0;
/**
* FormLayout constructor.
* @param container The container that is using the layout.
*/
public FormLayout(IAbstractSwtContainer container) {
super(container);
}//FormLayout()//
/**
* FormLayout constructor.
* @param container The container that is using the layout.
*/
public FormLayout(ICellContainer container) {
super(container);
}//FormLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#createLayout(java.lang.Object)
*/
public org.eclipse.swt.widgets.Layout createLayout(Object rowObject) {
com.foundation.view.swt.layout.FormLayout result = new com.foundation.view.swt.layout.FormLayout();
result.marginHeight = marginHeight;
result.marginWidth = marginWidth;
result.spacing = spacing;
result.marginLeft = marginLeft;
result.marginTop = marginTop;
result.marginRight = marginRight;
result.marginBottom = marginBottom;
return result;
}//createLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#initialize()
*/
public void initialize() {
}//initialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#refresh()
*/
public void refresh() {
}//refresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#synchronize()
*/
public void synchronize() {
}//synchronize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#release()
*/
public void release() {
}//release()//
/**
* Sets the layout margin width.
* @param marginWidth The layout margin width.
*/
public void setMarginWidth(int marginWidth) {
this.marginWidth = marginWidth;
}//setMarginWidth()//
/**
* Sets the layout margin height.
* @param marginHeight The layout margin height.
*/
public void setMarginHeight(int marginHeight) {
this.marginHeight = marginHeight;
}//setMarginHeight()//
/**
* Sets the layout margin top.
* @param marginTop The layout margin top.
*/
public void setMarginTop(int marginTop) {
this.marginTop = marginTop;
}//setMarginTop()//
/**
* Sets the layout margin bottom.
* @param marginBottom The layout margin bottom.
*/
public void setMarginBottom(int marginBottom) {
this.marginBottom = marginBottom;
}//setMarginBottom()//
/**
* Sets the layout margin right.
* @param marginRight The layout margin right.
*/
public void setMarginRight(int marginRight) {
this.marginRight = marginRight;
}//setMarginRight()//
/**
* Sets the layout margin left.
* @param marginLeft The layout margin left.
*/
public void setMarginLeft(int marginLeft) {
this.marginLeft = marginLeft;
}//setMarginLeft()//
/**
* Sets the layout spacing.
* @param spacing The layout spacing.
*/
public void setSpacing(int spacing) {
this.spacing = spacing;
}//setSpacing()//
}//FormLayout//

View File

@@ -0,0 +1,544 @@
/*
* 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.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import com.common.debug.*;
import com.foundation.view.*;
import com.foundation.view.resource.ResourceReference;
public class Frame extends Container implements IFrame, ShellListener, Component.IComponentListener {
public static final int STYLE_CLOSE = SWT.CLOSE;
public static final int STYLE_MIN = SWT.MIN;
public static final int STYLE_MAX = SWT.MAX;
public static final int STYLE_RESIZE = SWT.RESIZE;
public static final int STYLE_TITLE = SWT.TITLE;
public static final int STYLE_NO_TRIM = SWT.NO_TRIM;
public static final int STYLE_SHELL_TRIM = SWT.SHELL_TRIM;
public static final int STYLE_DIALOG_TRIM = SWT.DIALOG_TRIM;
public static final int STYLE_ON_TOP = SWT.ON_TOP;
public static final int STYLE_TOOL = SWT.TOOL;
/** The container's images resource (similar to component's containerImage, but allows multiple images to be specified). */
private SingleResourceAssociation containerImages;
/** A holder for the value of the container images. */
private ResourceHolder containerImagesHolder = new ResourceHolder(this);
/** The swt images used by the container of this component to represent the component. */
private Image[] swtContainerImages = null;
/** The optional method which will be called when the frame is closed. */
private IMethodAssociation closedMethod = null;
/** The optional method which will be called when the frame is activated. */
private IMethodAssociation activatedMethod = null;
/** The optional method which will be called when the frame is deactivated. */
private IMethodAssociation deactivatedMethod = null;
/** The optional menu bar for the frame. */
private Menu menuBar = null;
/**
* Frame default constructor.
* <p>Warning: This is only for use by the framework. This should never be called to create a useable instance.</p>
*/
public Frame() {
}//Frame()//
/**
* Frame constructor.
* This constructor is only used by the Window subclass.
* @param name The unique component name.
* @param viewContext The context under which this view component operates. For all but the outer most control this can be null.
* @param style The style for the control.
* @param data The optional data passed to the initializeControl(int, java.lang.Object) method.
*/
protected Frame(String name, IViewContext viewContext, int style, Object data) {
super(null, name, viewContext, style, data);
containerImages = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_IMAGES, false, null);
}//Frame()//
/**
* Frame constructor.
* This constructor is only used to create instances of a Frame <b>(Not currently supported by SWT - no floating frames)</b>.
* @param parent The parent frame.
* @param name The unique component name.
* @param style The frame style.
* @see #STYLE_BORDER
* @see #STYLE_H_SCROLL
* @see #STYLE_V_SCROLL
* @see #STYLE_BORDER
* @see #STYLE_LEFT_TO_RIGHT
* @see #STYLE_RIGHT_TO_LEFT
* @see #STYLE_NO_BACKGROUND
* @see #STYLE_NO_FOCUS
* @see #STYLE_NO_MERGE_PAINTS
* @see #STYLE_NO_REDRAW_RESIZE
* @see #STYLE_NO_RADIO_GROUP
* @see #STYLE_CLOSE
* @see #STYLE_MIN
* @see #STYLE_MAX
* @see #STYLE_RESIZE
* @see #STYLE_TITLE
* @see #STYLE_NO_TRIM
* @see #STYLE_SHELL_TRIM
* @see #STYLE_DIALOG_TRIM
* @see #STYLE_ON_TOP
* @see #STYLE_TOOL
*/
public Frame(Container parent, String name, int style) {
super(parent, name, style);
containerImages = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_IMAGES, false, null);
}//Frame()//
/**
* Sets the association container used to access the image array.
* @param container The images association metadata.
*/
public void setContainerImagesAssociation(SingleAssociationContainer container) {
verifyThread();
this.containerImages.setAssociations(container);
}//setContainerImagesAssociation()//
/**
* Sets the component's default image array resource.
* @param images The images to be displayed by this component.
*/
public void setDefaultContainerImages(ResourceReference images) {
verifyThread();
this.containerImages.setDefaultValue(images);
}//setDefaultContainerImages()//
/**
* Sets the container's default images.
* @param images The image data array that will be displayed by the container when an image is needed to represent it (example: a tab in a tab panel).
*/
public void setDefaultContainerImages(JefImage[] images) {
verifyThread();
this.containerImages.setDefaultValue(images);
}//setDefaultContainerImages()//
/**
* Refreshes the images for the frame.
*/
protected void internalViewRefreshContainerImages() {
if(containerImages.refresh()) {
containerImagesHolder.setValue(containerImages.getValue());
}//if//
}//internalViewRefreshContainerImages()//
/* (non-Javadoc)
* @see com.foundation.view.IView#maximize()
*/
public void maximize() {
getSwtDecorations().setMaximized(true);
}//maximize()//
/* (non-Javadoc)
* @see com.foundation.view.IView#minimize()
*/
public void minimize() {
getSwtDecorations().setMinimized(true);
}//minimize()//
/* (non-Javadoc)
* @see com.foundation.view.IView#show()
*/
public void show() {
if(getSwtDecorations().getMinimized()) {
getSwtDecorations().setMinimized(false);
}//if//
getSwtDecorations().setVisible(true);
getSwtDecorations().setFocus();
}//show()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#getDefaultVisibility()
*/
protected boolean getDefaultVisibility() {
return false;
}//getDefaultVisibility()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.Decorations(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT decorations that represents this frame.
* @return The decorations providing visualization for this frame.
*/
public org.eclipse.swt.widgets.Decorations getSwtDecorations() {
return (org.eclipse.swt.widgets.Decorations) getSwtControl();
}//getSwtDecorations()//
/**
* Sets the method to be called when the frame is closed.
* @param closedMethod The method to notify when the close function is performed.
*/
public void setClosedMethod(IMethodAssociation closedMethod) {
this.closedMethod = closedMethod;
}//setClosedMethod()//
/**
* Gets the frame's default button.
* @return The default button in this container.
*/
public Button getDefaultButton() {
verifyThread();
return (Button) getSwtDecorations().getDefaultButton().getData();
}//getDefaultButton()//
/**
* Sets the frame's default button.
* @param defaultButton The default button in this container.
*/
public void setDefaultButton(Button defaultButton) {
getSwtDecorations().setDefaultButton(defaultButton != null ? defaultButton.getSwtButton() : null);
}//setDefaultButton()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IDecoration#getMenuBar()
*/
public Menu getMenuBar() {
return menuBar;
}//getMenuBar()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IDecoration#setMenuBar(com.foundation.view.swt.Menu)
*/
public void setMenuBar(Menu menuBar) {
this.menuBar = menuBar;
}//setMenuBar()//
/**
* Centers the frame on the screen.
*/
public void center() {
verifyThread();
Rectangle window = getSwtDecorations().getBounds();
Rectangle screen = getSwtDecorations().getMonitor().getBounds();
int x = (int) ((screen.width / 2) - (window.width / 2));
int y = (int) ((screen.height / 2) - (window.height / 2));
if(x < screen.x) {
x = screen.x;
}//if//
if(y < screen.y) {
y = screen.y;
}//if//
getSwtDecorations().setLocation(x, y);
}//center()//
/**
* Centers the frame on another frame.
*/
public void center(IView view) {
verifyThread();
Rectangle windowRect = getSwtDecorations().getBounds();
Rectangle screen = getSwtDecorations().getDisplay().getBounds();
Rectangle componentRect = ((Container) view).getSwtComposite().getShell().getBounds();
int x = (int) ((componentRect.width / 2) - (windowRect.width / 2) + componentRect.x);
int y = (int) ((componentRect.height / 2) - (windowRect.height / 2) + componentRect.y);
if((x + windowRect.width) - screen.x > screen.width) {
x = (int) (screen.width - windowRect.width + screen.x);
}//if//
if((y + windowRect.height) - screen.y > screen.height) {
y = (int) (screen.height - windowRect.height + screen.y);
}//if//
if(x < screen.x) {
x = screen.x;
}//if//
if(y < screen.y) {
y = screen.y;
}//if//
getSwtDecorations().setLocation(x, y);
}//center()//
/**
* Sets the method to be called when the frame is activated.
* @param activatedMethod The method to notify when the activated function is performed.
*/
public void setActivatedMethod(IMethodAssociation activatedMethod) {
this.activatedMethod = activatedMethod;
}//setActivatedMethod()//
/**
* Sets the method to be called when the frame is deactivated.
* @param deactivatedMethod The method to notify when the deactivated function is performed.
*/
public void setDeactivatedMethod(IMethodAssociation deactivatedMethod) {
this.deactivatedMethod = deactivatedMethod;
}//setDeactivatedMethod()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitializeAll()
*/
public void internalViewInitializeAll() {
try {
//Initialize the super class components.//
super.internalViewInitializeAll();
//Initialize the menu bar if there is one.//
if(getMenuBar() != null) {
getMenuBar().internalViewInitializeAll();
}//if//
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}//internalViewInitializeAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewReleaseAll()
*/
public void internalViewReleaseAll() {
if(getSwtControl() instanceof Shell) {
((Shell) getSwtControl()).setLayoutDeferred(false);
}//if//
if(getMenuBar() != null) {
getMenuBar().internalViewReleaseAll();
}//if//
super.internalViewReleaseAll();
}//internalViewReleaseAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefreshAll()
*/
public void internalViewRefreshAll() {
try {
super.internalViewRefreshAll();
if(getMenuBar() != null) {
getMenuBar().internalViewRefreshAll();
}//if//
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}//internalViewRefreshAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronizeAll()
*/
public void internalViewSynchronizeAll() {
if(getMenuBar() != null) {
getMenuBar().internalViewSynchronizeAll();
}//if//
super.internalViewSynchronizeAll();
}//internalViewSynchronizeAll()//
/**
* Registers the listener(s) necessary to capture shell events.
*/
protected void registerShellListeners() {
/* GCJ Doesn't like this... since I don't use it I am commenting it.
getSwtDecorations().addListener(SWT.Close, new org.eclipse.swt.widgets.Listener() {
public void handleEvent(Event event) {
shellClosed(event);
event.doit = false;
}//handleEvent()//
});
getSwtDecorations().addListener(SWT.Activate, new org.eclipse.swt.widgets.Listener() {
public void handleEvent(Event event) {
shellActivated(event);
}//handleEvent()//
});
getSwtDecorations().addListener(SWT.Deactivate, new org.eclipse.swt.widgets.Listener() {
public void handleEvent(Event event) {
shellDeactivated(event);
}//handleEvent()//
});
*/
/* Not used.
getSwtDecorations().addListener(SWT.Iconify, new org.eclipse.swt.widgets.Listener() {
public void handleEvent(Event event) {
shellIconified(event);
}//handleEvent()//
});
getSwtDecorations().addListener(SWT.Deiconify, new org.eclipse.swt.widgets.Listener() {
public void handleEvent(Event event) {
shellDeiconified(event);
}//handleEvent()//
});
*/
}//registerShellListeners()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component.IComponentListener#toolTipTextChanged(com.foundation.view.swt.Component, java.lang.String)
*/
public void toolTipTextChanged(Component component, String newToolTipText) {
//Does nothing. The tool tip is already set by the caller.//
}//toolTipTextChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component.IComponentListener#imageChanged(com.foundation.view.swt.Component, org.eclipse.swt.graphics.Image)
*/
public void imageChanged(Component component, Image newImage) {
getSwtDecorations().setImage(newImage);
}//imageChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component.IComponentListener#titleChanged(com.foundation.view.swt.Component, java.lang.String)
*/
public void titleChanged(Component component, String newTitle) {
getSwtDecorations().setText(newTitle);
}//titleChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
try {
containerImages.initialize();
//Add this component as a shell listener so we get shell events.//
registerShellListeners();
//Register for image and title changes. Note: it is not necessary to initialize the title & image since they will be updated on the container's refresh and an event will fire if they are anything other than null.//
registerListener(this);
if(getContainerTitle() != null) {
getSwtDecorations().setText(getContainerTitle());
}//if//
super.internalViewInitialize();
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
containerImages.release();
containerImagesHolder.release();
if(swtContainerImages != null) {
destroyImages(swtContainerImages);
swtContainerImages = null;
}//if//
//Unregister for image and title changes.//
unregisterListener(this);
//Release the super class components.//
super.internalViewRelease();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
try {
internalViewRefreshContainerImages();
super.internalViewRefresh();
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
super.internalViewSynchronize();
}//internalViewSynchronize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#internalOnValueChanged(com.foundation.view.SingleResourceAssociation, boolean)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == containerImages) {
internalViewRefreshContainerImages();
}//if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#internalResourceHolderChanged(com.foundation.view.swt.ResourceHolder, java.lang.Object, java.lang.Object)
*/
protected void internalResourceHolderChanged(ResourceHolder resource, Object oldValue, Object newValue, int flags) {
if(resource == containerImagesHolder) {
destroyImages(swtContainerImages);
swtContainerImages = createImages(containerImagesHolder.getValue() instanceof JefImage ? new JefImage[] {(JefImage) containerImagesHolder.getValue()} : (JefImage[]) containerImagesHolder.getValue());
getSwtDecorations().setImages(swtContainerImages == null ? new Image[0] : swtContainerImages);
}//if//
else {
super.internalResourceHolderChanged(resource, oldValue, newValue, flags);
}//else//
}//internalOnAssociationChanged()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellClosed(org.eclipse.swt.events.ShellEvent)
*/
public void shellClosed(ShellEvent event) {
if(closedMethod != null) {
closedMethod.invoke(null, true);
}//if//
event.doit = false;
}//shellClosed()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellClosed(org.eclipse.swt.events.ShellEvent)
*/
public void shellClosed(Event event) {
if(closedMethod != null) {
closedMethod.invoke(null, true);
}//if//
event.doit = false;
}//shellClosed()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellActivated(org.eclipse.swt.events.ShellEvent)
*/
public void shellActivated(ShellEvent event) {
if(activatedMethod != null) {
activatedMethod.invoke(null, true);
}//if//
}//shellActivated()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellActivated(org.eclipse.swt.events.ShellEvent)
*/
public void shellActivated(Event event) {
if(activatedMethod != null) {
activatedMethod.invoke(null, true);
}//if//
}//shellActivated()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellDeactivated(org.eclipse.swt.events.ShellEvent)
*/
public void shellDeactivated(ShellEvent event) {
if(deactivatedMethod != null) {
deactivatedMethod.invoke(null, true);
}//if//
}//shellDeactivated()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellDeactivated(org.eclipse.swt.events.ShellEvent)
*/
public void shellDeactivated(Event event) {
if(deactivatedMethod != null) {
deactivatedMethod.invoke(null, true);
}//if//
}//shellDeactivated()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellDeiconified(org.eclipse.swt.events.ShellEvent)
*/
public void shellDeiconified(ShellEvent event) {
//if(deiconifiedMethod != null) {
// deiconifiedMethod.invoke(null, true);
//}//if//
}//shellDeiconified()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellDeiconified(org.eclipse.swt.events.ShellEvent)
*/
public void shellDeiconified(Event event) {
//if(deiconifiedMethod != null) {
// deiconifiedMethod.invoke(null, true);
//}//if//
}//shellDeiconified()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellIconified(org.eclipse.swt.events.ShellEvent)
*/
public void shellIconified(ShellEvent event) {
//if(iconifiedMethod != null) {
// iconifiedMethod.invoke(null, true);
//}//if//
}//shellIconified()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellIconified(org.eclipse.swt.events.ShellEvent)
*/
public void shellIconified(Event event) {
//if(iconifiedMethod != null) {
// iconifiedMethod.invoke(null, true);
//}//if//
}//shellIconified()//
}//Frame//

View File

@@ -0,0 +1,144 @@
/*
* Copyright (c) 2007 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;
public class GridLayout extends Layout {
public int numColumns = 1;
public boolean makeColumnsEqualWidth = false;
public int marginWidth = 0;
public int marginHeight = 0;
public int marginLeft = 0;
public int marginTop = 0;
public int marginRight = 0;
public int marginBottom = 0;
public int horizontalSpacing = 5;
public int verticalSpacing = 5;
/**
* GridLayout constructor.
* @param container The container that is using the layout.
*/
public GridLayout(IAbstractSwtContainer container) {
super(container);
}//GridLayout()//
/**
* GridLayout constructor.
* @param cellContainer The container that is using the layout.
*/
public GridLayout(ICellContainer cellContainer) {
super(cellContainer);
}//GridLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#createLayout(java.lang.Object)
*/
public org.eclipse.swt.widgets.Layout createLayout(Object rowObject) {
com.foundation.view.swt.layout.GridLayout result = new com.foundation.view.swt.layout.GridLayout();
result.marginHeight = marginHeight;
result.marginWidth = marginWidth;
result.marginLeft = marginLeft;
result.marginTop = marginTop;
result.marginRight = marginRight;
result.marginBottom = marginBottom;
result.numColumns = numColumns;
result.makeColumnsEqualWidth = makeColumnsEqualWidth;
result.horizontalSpacing = horizontalSpacing;
result.verticalSpacing = verticalSpacing;
return result;
}//createLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#initialize()
*/
public void initialize() {
}//initialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#refresh()
*/
public void refresh() {
}//refresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#synchronize()
*/
public void synchronize() {
}//synchronize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#release()
*/
public void release() {
}//release()//
/**
* Sets the layout column count.
* @param type The layout column count.
*/
public void setNumColumns(int numColumns) {
this.numColumns = numColumns;
}//setNumColumns()//
/**
* Sets the layout margin width.
* @param marginWidth The layout margin width.
*/
public void setMarginWidth(int marginWidth) {
this.marginWidth = marginWidth;
}//setMarginWidth()//
/**
* Sets the layout margin height.
* @param marginHeight The layout margin height.
*/
public void setMarginHeight(int marginHeight) {
this.marginHeight = marginHeight;
}//setMarginHeight()//
/**
* Sets the layout margin top.
* @param marginTop The layout margin top.
*/
public void setMarginTop(int marginTop) {
this.marginTop = marginTop;
}//setMarginTop()//
/**
* Sets the layout margin bottom.
* @param marginBottom The layout margin bottom.
*/
public void setMarginBottom(int marginBottom) {
this.marginBottom = marginBottom;
}//setMarginBottom()//
/**
* Sets the layout margin right.
* @param marginRight The layout margin right.
*/
public void setMarginRight(int marginRight) {
this.marginRight = marginRight;
}//setMarginRight()//
/**
* Sets the layout margin left.
* @param marginLeft The layout margin left.
*/
public void setMarginLeft(int marginLeft) {
this.marginLeft = marginLeft;
}//setMarginLeft()//
/**
* Sets whether the layout columns have the same widths.
* @param makeColumnsEqualWidth Whether the layout columns are equal width.
*/
public void setMakeColumnsEqualWidth(boolean makeColumnsEqualWidth) {
this.makeColumnsEqualWidth = makeColumnsEqualWidth;
}//setMakeColumnsEqualWidth()//
/**
* Sets the layout horizontal spacing.
* @param horizontalSpacing The layout horizontal spacing.
*/
public void setHorizontalSpacing(int horizontalSpacing) {
this.horizontalSpacing = horizontalSpacing;
}//setHorizontalSpacing()//
/**
* Sets the layout vertical spacing.
* @param verticalSpacing The layout vertical spacing.
*/
public void setVerticalSpacing(int verticalSpacing) {
this.verticalSpacing = verticalSpacing;
}//setVerticalSpacing()//
}//GridLayout//

View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 2007,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import com.common.debug.Debug;
public class Group extends Container implements Component.IComponentListener {
public static final int STYLE_SHADOW_ETCHED_IN = SWT.SHADOW_ETCHED_IN;
public static final int STYLE_SHADOW_ETCHED_OUT = SWT.SHADOW_ETCHED_OUT;
public static final int STYLE_SHADOW_IN = SWT.SHADOW_IN;
public static final int STYLE_SHADOW_OUT = SWT.SHADOW_OUT;
public static final int STYLE_SHADOW_NONE = SWT.SHADOW_NONE;
/**
* Group default constructor.
* <p>Warning: This is only for use by the framework. This should never be called to create a useable instance.</p>
*/
public Group() {
}//Group()//
/**
* Group constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_SHADOW_ETCHED_IN
* @see #STYLE_SHADOW_ETCHED_OUT
* @see #STYLE_SHADOW_IN
* @see #STYLE_SHADOW_OUT
* @see #STYLE_SHADOW_NONE
*/
public Group(Container parent, String name, int style) {
super(parent, name, style);
}//Group()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.Group(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT group that represents this component.
* @return The group control providing visualization for this componnet.
*/
public org.eclipse.swt.widgets.Group getSwtGroup() {
return (org.eclipse.swt.widgets.Group) getSwtControl();
}//getSwtGroup()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container#internalViewInitialize()
*/
protected void internalViewInitialize() {
try {
//Register for image and title changes. Note: it is not necessary to initialize the title & image since they will be updated on the container's refresh and an event will fire if they are anything other than null.//
registerListener(this);
if(getContainerTitle() != null) {
getSwtGroup().setText(getContainerTitle());
}//if//
super.internalViewInitialize();
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
if(getContainerTitle() != null) {
getSwtGroup().setText(getContainerTitle());
}//if//
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container#internalViewRelease()
*/
protected void internalViewRelease() {
//Unregister for image and title changes.//
unregisterListener(this);
//Release the super class components.//
super.internalViewRelease();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component.IComponentListener#toolTipTextChanged(com.foundation.view.swt.Component, java.lang.String)
*/
public void toolTipTextChanged(Component component, String newToolTipText) {
//Does nothing. The tool tip is already set by the caller.//
}//toolTipTextChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component.IComponentListener#imageChanged(com.foundation.view.swt.Component, org.eclipse.swt.graphics.Image)
*/
public void imageChanged(Component component, Image newImage) {
//Group currently doesn't support an image.//
//getSwtGroup().setImage(newImage);
}//imageChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component.IComponentListener#titleChanged(com.foundation.view.swt.Component, java.lang.String)
*/
public void titleChanged(Component component, String newTitle) {
getSwtGroup().setText(newTitle);
}//titleChanged()//
}//Group//

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2008,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;
public interface IAbstractMenu {
/**
* Creates this menu's resources.
* This allows the menu to be lazily created when the user wants to interact with it, and then cleaned up when done.
*/
public void loadMenu();
/**
* Destroys this menu's resources.
* This allows the menu to be lazily created when the user wants to interact with it, and then cleaned up when done.
*/
public void unloadMenu();
/**
* Creates the menu's children's resources (all children in the tree).
* This allows the menu to be lazily created when the user wants to interact with it, and then cleaned up when done.
*/
public void loadMenuChildren();
/**
* Destroys the menu's children's resources (all children in the tree).
* This allows the menu to be lazily created when the user wants to interact with it, and then cleaned up when done.
*/
public void unloadMenuChildren();
}//IAbstractMenu//

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2006,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Widget;
public interface IAbstractSwtContainer extends com.foundation.view.IAbstractContainer {
/**
* Gets the SWT composite control for the container.
* Note that this composite might not be the one to place children in.
* <p>Warning: Not all containers have a composite, but all should have a widget.</p>
* @return The composite control that SWT uses to designate a container.
*/
public Composite getSwtComposite();
/**
* Gets the SWT composite control used to contain the child controls.
* Note that this may be the same object as returned by the getSwtComposite() method.
* @return The composite control that SWT uses to designate a container and which will be used to contain any children.
*/
public Composite getSwtParent();
/**
* Gets the SWT widget used to contain the child controls.
* Note that this may be the same object as returned by the getSwtComposite() method.
* @return The composite control that SWT uses to designate a container and which will be used to contain any children.
*/
public Widget getSwtWidget();
}//IAbstractContainer//

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2006,2007 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.widgets.Composite;
import com.common.util.IIterator;
import com.foundation.view.IAbstractContainer;
import com.foundation.view.swt.cell.CellComponent;
public interface ICellContainer {
/**
* Gets the composite that will contain the swt resources for the contained control.
* @param rowObject The row object whose composite is required. The composite may be the container for the cells, or a sub-container within the cell.
* @return The composite that the cell controls can be added to.
*/
public Composite getSwtComposite(Object rowObject);
/**
* Gets the composites that the cells use as the parent SWT component.
* @return The iterator over all active SWT composites that contain all children.
*/
public IIterator getSwtComposites();
/**
* Gets the container for the cell container.
* @return The container for the cells.
*/
public IAbstractContainer getContainer();
/**
* Adds a cell component as a child of this container.
* @param component The cell component to be contained by this container.
*/
public void addCellComponent(CellComponent component);
}//ICellContainer//

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2007 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import com.foundation.view.JefImage;
import com.foundation.view.resource.AbstractResourceService;
public interface IDecorationContainer {
/**
* Gets the view system's resource service.
* @return The resource service for the view system.
*/
public AbstractResourceService getResourceService();
/**
* Gets the parent control for the decorations.
* @return The decoration's parent control.
*/
public Composite getDecorationParent();
/**
* Gets the decoration's peer control (the one it is decorating).
* @return The peer control for the decorations.
*/
public Control getDecorationPeer();
/**
* Creates an image given the jef image.
* @param image The image to be created.
* @return The image resource.
*/
public Image createImage(JefImage image);
/**
* Destroys an image resource, or decrements the useage count.
* @param image The image to destroy.
*/
public void destroyImage(Image image);
}//IDecorationContainer//

View File

@@ -0,0 +1,18 @@
/*
* Copyright (c) 2007 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.widgets.Composite;
public interface IDualLayerContainer {
/**
* Gets the parent composite for the child controls.
* @return The child control's parent composite which may differ from the container's outer composite.
*/
public Composite getSwtParent();
}//IDualLayerContainer//

View File

@@ -0,0 +1,19 @@
/*
* 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.view.swt;
/**
* Implementors must be able to display them selves with a menu bar.
*/
public interface IFrame {
/**
* Sets the decoration's menu bar.
* @param menu The menu to be displayed in the menu bar.
*/
public void setMenuBar(Menu menu);
}//IFrame//

View File

@@ -0,0 +1,27 @@
/*
* Copyright (c) 2005,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Widget;
/**
* An internal interface defining some internal use only methods.
*/
public interface IInternalAbstractComponent {
/**
* Gets the widget encapsulated by this component.
* @return The encapsulated widget, or null if this component does not have a viewable element.
*/
public Widget getSwtWidget();
/**
* Gets the SWT shell for the component.
* @return The shell for this component.
*/
public Shell getShell();
}//IInternalAbstractComponent//

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2007,2008 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Control;
import com.foundation.view.AbstractDecoration;
public interface IOverlay {
public static final int POSITION_UPPER_LEFT = AbstractDecoration.POSITION_UPPER_LEFT;
public static final int POSITION_UPPER_RIGHT = AbstractDecoration.POSITION_UPPER_RIGHT;
public static final int POSITION_LOWER_LEFT = AbstractDecoration.POSITION_LOWER_LEFT;
public static final int POSITION_LOWER_RIGHT = AbstractDecoration.POSITION_LOWER_RIGHT;
/**
* Gets the peer control that is being overlayed.
* @return The control the overlay is attached to.
*/
public Control getPeerControl();
/**
* Gets the horizontal offset.
* @return The offset (positive is inward) for the overlay.
*/
public int getHorizontalOffset();
/**
* Gets the vertical offset.
* @return The offset (positive is inward) for the overlay.
*/
public int getVerticalOffset();
/**
* Gets which corner the overlay should adorn.
* @return The corner of the peer control that is being overlayed.
*/
public int getPosition();
/**
* Gets the size of the overlay.
* @return The overlay size.
*/
public Point getSize();
}//IOverlay//

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) 2006 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.widgets.Display;
import com.foundation.view.IViewRequestHandler;
public interface ISwtViewRequestHandler extends IViewRequestHandler {
/**
* Gets the display for the request handler.
* @return The SWT display object.
*/
public Display getDisplay();
}//ISwtViewRequestHandler//

View File

@@ -0,0 +1,719 @@
/*
* 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//

View File

@@ -0,0 +1,191 @@
/*
* 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.view.swt;
import com.foundation.view.*;
import com.foundation.view.resource.ResourceReference;
import org.eclipse.swt.SWT;
public class Label extends Component {
public static final int STYLE_SEPARATOR = SWT.SEPARATOR;
public static final int STYLE_HORIZONTAL = SWT.HORIZONTAL;
public static final int STYLE_VERTICAL = SWT.VERTICAL;
public static final int STYLE_SHADOW_IN = SWT.SHADOW_IN;
public static final int STYLE_SHADOW_OUT = SWT.SHADOW_OUT;
public static final int STYLE_SHADOW_NONE = SWT.SHADOW_NONE;
public static final int STYLE_LEFT = SWT.LEFT;
public static final int STYLE_RIGHT = SWT.RIGHT;
public static final int STYLE_CENTER = SWT.CENTER;
public static final int STYLE_WRAP = SWT.WRAP;
/** The label text. */
private SingleResourceAssociation text = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_TEXT, false, "");
/** The label image. */
private SingleResourceAssociation image = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_IMAGE, false, null);
/** A holder for the value of the text. */
private ResourceHolder textHolder = new ResourceHolder(this);
/** A holder for the value of the image. */
private ResourceHolder imageHolder = new ResourceHolder(this);
/**
* Label constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct
* @see #SEPARATOR
* @see #HORIZONTAL
* @see #VERTICAL
* @see #SHADOW_IN
* @see #SHADOW_OUT
* @see #SHADOW_NONE
* @see #LEFT
* @see #RIGHT
* @see #CENTER
* @see #WRAP
*/
public Label(Container parent, String name, int style) {
super(parent, name, style);
}//Label()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.Label(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT label that represents this label.
* @return The SWT label providing visualization for this label.
*/
public org.eclipse.swt.widgets.Label getSwtLabel() {
return (org.eclipse.swt.widgets.Label) getSwtControl();
}//getSwtLabel()//
/**
* Sets the label's text. This will be the default text if there is a text attribute associated with this component.
* @param text The text that will appear in the label.
*/
public void setText(String text) {
verifyThread();
this.text.setDefaultValue(text);
}//setText()//
/**
* Sets the component's default text resource.
* @param text The text to be displayed by this component.
*/
public void setText(ResourceReference text) {
verifyThread();
this.text.setDefaultValue(text);
}//setText()//
/**
* Sets the association container used to access the text.
* @param container The text association metadata.
*/
public void setTextAssociation(SingleAssociationContainer container) {
verifyThread();
this.text.setAssociations(container);
}//setTextAssociation()//
/**
* Sets the association container used to access the image.
* @param container The image association metadata.
*/
public void setImageAssociation(SingleAssociationContainer container) {
verifyThread();
this.image.setAssociations(container);
}//setImageAssociation()//
/**
* Sets the label's image. This will be the default image if there is a image attribute associated with this component.
* @param image The image to be displayed by the label.
*/
public void setImage(JefImage image) {
verifyThread();
this.image.setDefaultValue(image);
}//setImage()//
/**
* Sets the component's default image resource.
* @param image The image to be displayed by this component.
*/
public void setImage(ResourceReference image) {
verifyThread();
this.image.setDefaultValue(image);
}//setImage()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
text.initialize(true);
image.initialize(true);
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
destroyImage((JefImage) imageHolder.getValue());
text.release();
image.release();
textHolder.release();
imageHolder.release();
super.internalViewRelease();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalViewRefreshText();
internalViewRefreshImage();
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#internalResourceHolderChanged(com.foundation.view.swt.ResourceHolder, java.lang.Object, java.lang.Object)
*/
protected void internalResourceHolderChanged(ResourceHolder resource, Object oldValue, Object newValue, int flags) {
if(resource == textHolder) {
String value = newValue != null ? (String) newValue : "";
getSwtLabel().setText(value == null ? "" : value);
resize();
}//if//
else if(resource == imageHolder) {
destroyImage(getSwtLabel().getImage());
getSwtLabel().setImage(createImage((JefImage) newValue));
resize();
}//else if//
else {
super.internalResourceHolderChanged(resource, oldValue, newValue, flags);
}//else//
}//internalOnAssociationChanged()//
/**
* Refreshes the component's text.
*/
protected void internalViewRefreshText() {
if(text.refresh()) {
textHolder.setValue(text.getValue());
}//if//
}//internalViewRefreshText()//
/**
* Refreshes the component's image.
*/
protected void internalViewRefreshImage() {
if(image.refresh()) {
imageHolder.setValue(image.getValue());
}//if//
}//internalViewRefreshImage()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == text) {
internalViewRefreshText();
}//if//
else if(resourceAssociation == image) {
internalViewRefreshImage();
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
}//Label//

View File

@@ -0,0 +1,219 @@
/*
* Copyright (c) 2007,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.widgets.Composite;
import com.common.debug.Debug;
import com.common.util.IIterator;
import com.foundation.controller.DecorationManager;
import com.foundation.view.AbstractDecoration;
import com.foundation.view.IVariableResourceAssociationChangeListener;
import com.foundation.view.IViewContext;
import com.foundation.view.ResourceAssociation;
import com.foundation.view.resource.AbstractResourceService;
public abstract class Layout implements IVariableResourceAssociationChangeListener {
/** The container that uses this layout. Only one of the container or cellContainer will be provided. */
private IAbstractSwtContainer container = null;
/** The cell container that uses this layout. */
private ICellContainer cellContainer = null;
/** Whether the layout has been initialized yet. */
private boolean isInitialized = false;
/**
* A handler that is called to apply a set of changes to one or more layout.
*/
public interface IChangeHandler {
/**
* Applies the changes to the layout.
* @param composite The composite whose layout to apply the changes to.
*/
public void applyChanges(org.eclipse.swt.widgets.Composite composite);
}//IChangeHandler//
/**
* Layout constructor.
* @param container The container that is using the layout.
*/
public Layout(IAbstractSwtContainer container) {
this.container = container;
}//Layout()//
/**
* Layout constructor.
* @param cellContainer The cell container that is using the layout.
*/
public Layout(ICellContainer cellContainer) {
if(cellContainer instanceof IAbstractSwtContainer) {
this.container = (IAbstractSwtContainer) cellContainer;
}//if//
else {
this.cellContainer = cellContainer;
}//else//
}//Layout()//
/**
* Gets whether the layout is already initialized.
* @return Whether the layout has been initialized yet.
*/
public boolean isInitialized() {
return isInitialized;
}//isInitialized()//
/**
* Calls layout on the container.
* @param rowObject The optional row object with which the container is associated.
* @param changed If the container's cache should be flushed.
* @param all If all the children also require laying out.
*/
protected void layoutContainer(Object rowObject, boolean changed, boolean all) {
if(getCellContainer() != null) {
if(rowObject != null) {
getCellContainer().getSwtComposite(rowObject).layout(changed, all);
}//if//
else {
IIterator iterator = getCellContainer().getSwtComposites();
while(iterator.hasNext()) {
((Composite) iterator.next()).layout(changed, all);
}//while//
}//else//
}//if//
else {
getContainer().getSwtComposite().layout(changed, all);
}//else//
}//layoutContainer()//
/**
* Applies changes to the layout in the container.
* @param rowObject The optional row object with which the container is associated.
* @param handler The handler called to make the actual changes.
*/
protected void applyChanges(Object rowObject, IChangeHandler handler) {
if(getCellContainer() != null) {
if(rowObject != null) {
handler.applyChanges(getCellContainer().getSwtComposite(rowObject));
}//if//
else {
IIterator iterator = getCellContainer().getSwtComposites();
while(iterator.hasNext()) {
handler.applyChanges((Composite) iterator.next());
}//while//
}//else//
}//if//
else {
if(getContainer().getSwtComposite() != null && !getContainer().getSwtComposite().isDisposed()) {
handler.applyChanges(getContainer().getSwtComposite());
}//if//
}//else//
}//applyChanges()//
/**
* Gets the view context for the layout.
* @return The layout's view context.
*/
protected IViewContext getViewContext() {
return container.getViewContext();
}//getViewContext()//
/**
* Gets the container using this layout.
* @return The container that this layout supports.
*/
protected IAbstractSwtContainer getContainer() {
return container;
}//getContainer()//
/**
* Gets the cell container using this layout.
* @return The cell container that this layout supports.
*/
protected ICellContainer getCellContainer() {
return cellContainer;
}//getCellContainer()//
/**
* Creates a layout that is used by an SWT control.
* @param rowObject The optional row object that the layout is associated with. This should be provided if the cellComponent is specified, otherwise it should be null.
* @return The SWT layout.
*/
public abstract org.eclipse.swt.widgets.Layout createLayout(Object rowObject);
/**
* Initializes the layout.
*/
public abstract void initialize();
/**
* Refreshes the layout by transfering data from the model to the view.
*/
public abstract void refresh();
/**
* Synchronizes the layout by transfering data from the view to the model.
*/
public abstract void synchronize();
/**
* Releases the layout.
*/
public abstract void release();
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#addDecoration(com.foundation.view.AbstractDecoration)
*/
public void addDecoration(AbstractDecoration decoration) {
}//addDecoration()//
/* (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.ISingleResourceAssociationChangeListener#addMessageHold()
*/
public void addMessageHold() {
}//addMessageHold()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#getDecorationManager()
*/
public DecorationManager getDecorationManager() {
return container.getDecorationManager();
}//getDecorationManager()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#getResourceService()
*/
public AbstractResourceService getResourceService() {
return container.getResourceService();
}//getResourceService()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#onValueChanged(com.foundation.view.ResourceAssociation)
*/
public void onValueChanged(ResourceAssociation resourceAssociation, int flags) {
Debug.log(new RuntimeException("Error: Unexpected (unhandled by Layout) resource association found. Resource URL: " + resourceAssociation.toString()));
}//onValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.IMultiResourceAssociationChangeListener#onValueChanged(com.foundation.view.ResourceAssociation, java.lang.Object, java.lang.Object, boolean)
*/
public void onValueChanged(ResourceAssociation resourceAssociation, Object alteredItem, Object data, boolean isUpdate) {
Debug.log(new RuntimeException("Error: Unexpected (unhandled by Layout) resource association found. Resource URL: " + resourceAssociation.toString()));
}//onValueChanged()//
/* (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) {
}//onModelExternallyChanged()//
/* (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) {
}//onModelExternallyChanged()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#removeDecoration(com.foundation.view.AbstractDecoration)
*/
public void removeDecoration(AbstractDecoration decoration) {
}//removeDecoration()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#removeMessageHold()
*/
public void removeMessageHold() {
}//removeMessageHold()//
/* (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()//
}//Layout//

View File

@@ -0,0 +1,130 @@
/*
* Copyright (c) 2005,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import com.common.debug.Debug;
import com.foundation.view.IMethodAssociation;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
public class Link extends Component implements SelectionListener {
/** Called when the link is pressed. */
private IMethodAssociation selectionMethod = null;
/** The button's text resource. */
private SingleResourceAssociation text = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_TEXT, false, "");
/**
* Link constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
*/
public Link(Container parent, String name, int style) {
super(parent, name, style);
}//Link()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.Link(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT link that represents this link.
* @return The SWT link providing visualization for this link.
*/
public org.eclipse.swt.widgets.Link getSwtLink() {
return (org.eclipse.swt.widgets.Link) getSwtControl();
}//getSwtLink()//
/**
* Sets the selection method called when the link is pressed.
* @param selectionMethod The method called when the link is pressed.
*/
public void setSelectionMethod(IMethodAssociation selectionMethod) {
verifyThread();
this.selectionMethod = selectionMethod;
}//setSelectionMethod()//
/**
* Sets the component text.
* @param text The text that will appear in the component.
*/
public void setText(String text) {
verifyThread();
this.text.setDefaultValue(text);
}//setText()//
/**
* Sets the association container used to access the text.
* @param container The text association metadata.
*/
public void setTextAssociation(SingleAssociationContainer container) {
verifyThread();
this.text.setAssociations(container);
}//setTextAssociation()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#internalViewInitialize()
*/
protected void internalViewInitialize() {
getSwtLink().addSelectionListener(this);
text.initialize();
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalViewRefreshText();
}//internalViewRefresh()//
/**
* Refreshes the link text.
*/
protected void internalViewRefreshText() {
if(text.refresh()) {
getSwtLink().setText((String) text.getValue());
}//if//
}//internalViewRefreshText()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#internalViewRelease()
*/
protected void internalViewRelease() {
if(getSwtLink() != null && !getSwtLink().isDisposed()) {
getSwtLink().removeSelectionListener(this);
}//if//
super.internalViewRelease();
text.release();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == text) {
internalViewRefreshText();
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent e) {
//TODO: When is this called?//
Debug.log("Default Selected Called <Why?>");
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent e) {
if(selectionMethod != null) {
selectionMethod.invoke(null, true);
}//if//
}//widgetSelected()//
}//Link//

View File

@@ -0,0 +1,449 @@
/*
* 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.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import com.common.thread.IRunnable;
import com.common.util.*;
import com.common.util.optimized.*;
import com.foundation.view.*;
/**
* A simple list of strings in a box with an optional vertical and horizontal scroll bar and allowing single or multiple selections.
*/
public class ListBox extends IndexedCollectionComponent implements SelectionListener {
public static final int STYLE_SINGLE = SWT.SINGLE;
public static final int STYLE_MULTI = SWT.MULTI;
/** Converts the collection item to a string used to show the item to the user. */
protected MultiResourceAssociation itemText = new MultiResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_TEXT, false, null);
/** Converts the collection item to an image used to show the item to the user. */
protected MultiResourceAssociation itemImage = new MultiResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_IMAGE, false, null);
/**
* ListBox constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_MULTI
* @see #STYLE_SINGLE
*/
public ListBox(Container parent, String name, int style) {
super(parent, name, style);
setAllowMultiSelection(((style & STYLE_MULTI) > 0));
}//ListBox()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.List(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT list that represents this list box.
* @return The SWT list providing visualization for this list box.
*/
public org.eclipse.swt.widgets.List getSwtList() {
return (org.eclipse.swt.widgets.List) getSwtControl();
}//getSwtList()//
/**
* Sets the association container used to access the item text.
* @param container The item text association metadata.
*/
public void setItemTextAssociation(MultiAssociationContainer container) {
verifyThread();
this.itemText.setAssociations(container);
}//setItemTextAssociation()//
/**
* Sets the association container used to access the item text.
* @param container The item text association metadata.
*/
public void setItemImageAssociation(MultiAssociationContainer container) {
verifyThread();
this.itemImage.setAssociations(container);
}//setItemImageAssociation()//
/**
* Adjusts the visible range of items to show some or all of the selections.
*/
public void showSelection() {
verifyThread();
getSwtList().showSelection();
}//showSelection()//
/**
* Gets the index of the top most visible item.
* @return The top most visible item's index.
*/
public Integer getTopIndex() {
verifyThread();
return new Integer(getSwtList().getTopIndex());
}//getTopIndex()//
/**
* Sets the index of the top most visible item.
* @parma topIndex The top most visible item's index.
*/
public void setTopIndex(Integer topIndex) {
verifyThread();
getSwtList().setTopIndex(topIndex.intValue());
}//setTopIndex()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
getSwtList().addSelectionListener(this);
itemText.initialize();
itemImage.initialize();
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
if((getSwtList() != null) && (!getSwtList().isDisposed())) {
getSwtList().removeSelectionListener(this);
}//if//
super.internalViewRelease();
itemText.release();
itemImage.release();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.MultiResourceAssociation, java.lang.Object)
*/
protected void internalOnValueChanged(MultiResourceAssociation resourceAssociation, Object alteredItem, Object data, boolean isUpdate) {
if(resourceAssociation == itemText) {
internalViewRefreshItemText(alteredItem);
}//if//
else if(resourceAssociation == itemImage) {
internalViewRefreshItemImage(alteredItem);
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, alteredItem, data, isUpdate);
}//else//
}//internalOnValueChanged()//
/**
* Refreshes the item image.
* @param item The collection item whose image needs refreshing.
*/
protected void internalViewRefreshItemImage(Object item) {
//TODO: Set the item image.//
}//internalViewRefreshItemImage()//
/**
* Refreshes the item text.
* @param item The collection item whose text needs refreshing.
*/
protected void internalViewRefreshItemText(Object item) {
Object indexData = getItemIndexData(item);
//Set the new item text.//
if(indexData instanceof Integer) {
controlSetItem(((Integer) indexData).intValue(), getItemData(item));
}//if//
else if(indexData instanceof IntArray) {
IntArray array = (IntArray) indexData;
for(int index = 0; index < array.getSize(); index++) {
controlSetItem(array.get(index), itemToString(item));
}//for//
}//if//
}//internalViewRefreshItemText()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IndexedCollectionComponent#getItemData(java.lang.Object)
*/
protected Object getItemData(Object item) {
return itemToString(item);
}//getItemData()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#itemAdded(java.lang.Object, int)
*/
protected void itemAdded(Object item, int index) {
registerItem(item);
super.itemAdded(item, index);
}//itemAdded()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#itemRemoved(java.lang.Object, int)
*/
protected void itemRemoved(Object item, int index) {
unregisterItem(item);
super.itemRemoved(item, index);
}//itemRemoved()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#itemAllRemoved()
*/
protected void itemAllRemoved() {
unregisterItems();
super.itemAllRemoved();
}//itemAllRemoved()//
/**
* Converts an item in the collection to a string that can be displayed.
* @param item The collection item to convert.
* @return The string that can be displayed.
*/
protected String itemToString(Object item) {
String result = null;
if(item instanceof JefImage) {
return "";
}//if//
else {
itemText.refresh(item);
result = (String) itemText.getValue(item);
if(result == null) {
result = item != null ? item.toString() : "";
}//if//
}//if//
return result;
}//itemToString()//
/**
* Converts an item in the collection to an image that can be displayed.
* @param item The collection item to convert.
* @return The image that can be displayed.
*/
protected JefImage itemToImage(Object item) {
JefImage result = null;
if(item instanceof JefImage) {
result = (JefImage) item;
}//if//
else {
itemImage.refresh(item);
result = (JefImage) itemImage.getValue(item);
}//else//
return result;
}//itemToImage()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#registerItem(java.lang.Object)
*/
protected void registerItem(Object item) {
itemText.registerItem(item);
itemImage.registerItem(item);
super.registerItem(item);
}//registerItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#unregisterItem(java.lang.Object)
*/
protected void unregisterItem(Object item) {
itemText.unregisterItem(item);
itemImage.unregisterItem(item);
super.unregisterItem(item);
}//unregisterItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#unregisterItems()
*/
protected void unregisterItems() {
itemText.unregisterAllItems();
itemImage.unregisterAllItems();
super.unregisterItems();
}//unregisterItems()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent e) {
//This method appears to always be called for the list box.//
widgetSelected(e);
//Handle the double-click.//
if(getDoubleClickMethod() != null) {
if(getDoubleClickMethod().getIsValueHolderAssociated()) {
getDoubleClickMethod().invoke(null, true); //For now we will assume no parameters. It would be nice to pass the selection perhaps.//
}//if//
else {
Object selection = null;
//Determine which selection to invoke the method on.//
if(getAllowMultiSelection()) {
ICollection selections = getModelSelections();
if((selections != null) && (selections.getSize() > 0)) {
selection = selections.iterator().next();
}//if//
}//if//
else {
selection = getModelSelection();
}//else//
if(selection != null) {
//Invoke the method on the selection object if there is one.//
getDoubleClickMethod().invoke(selection, null, true);
}//if//
}//else//
}//if//
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent e) {
updateSelectionLinks();
if(getAutoSynchronizeSelection()) {
if(getAutoSynchronizeSelectionDelay() > 0) {
//Start a task to send the selection to the server after a short delay. This will reduce the overhead of auto synchronizing the selection.//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
}//if//
autoSynchronizeSelectionTask = new Task() {
public void execute() {
//Make sure that this task is still valid and is not being superceeded.//
synchronized(ListBox.this) {
if(autoSynchronizeSelectionTask == this) {
//Cleanup after the task.//
autoSynchronizeSelectionTask = null;
getEventLoop().executeAsync(new IRunnable() {
public Object run() {
synchronizeSelection();
if(getAutoValidate()) {
postSynchronizeValidate();
}//if//
return null;
}//run()//
});
}//if//
}//synchronized//
}//run()//
};
addTask(autoSynchronizeSelectionTask, getAutoSynchronizeSelectionDelay());
}//synchronized//
}//if//
else {
synchronizeSelection();
if(getAutoValidate()) {
postSynchronizeValidate();
}//if//
}//else//
}//if//
}//widgetSelected()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlRemoveAll()
*/
protected void controlRemoveAll() {
getSwtList().removeAll();
}//controlRemoveAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlSetItems(String[])
*/
protected void controlSetItems(Object[] items) {
if((items == null) || (items.length == 0)) {
getSwtList().removeAll();
}//if//
else {
String[] itemTexts = new String[items.length];
System.arraycopy(items, 0, itemTexts, 0, itemTexts.length);
getSwtList().setItems(itemTexts);
}//else//
}//controlSetItems()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlSetItem(int, String)
*/
protected void controlSetItem(int index, Object itemData) {
getSwtList().setItem(index, (String) itemData);
}//controlSetItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlAddItem(String, int)
*/
protected void controlAddItem(Object itemData, int index) {
getSwtList().add((String) itemData, index);
}//controlAddItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlAddItem(String)
*/
protected void controlAddItem(Object itemData) {
getSwtList().add((String) itemData);
}//controlAddItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlRemoveItem(int)
*/
protected void controlRemoveItem(int index) {
getSwtList().remove(index);
}//controlRemoveItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlGetSelections()
*/
protected int[] controlGetSelections() {
return getSwtList().getSelectionIndices();
}//controlGetSelections()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlGetSelection()
*/
protected int controlGetSelection() {
return getSwtList().getSelectionIndex();
}//controlGetSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlSetSelections(int[])
*/
protected void controlSetSelections(int[] indices) {
getSwtList().setSelection(indices);
getSwtList().showSelection();
}//controlSetSelections()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlSetSelection(int)
*/
protected void controlSetSelection(int index) {
getSwtList().setSelection(index);
getSwtList().showSelection();
}//controlSetSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlAddSelection(int)
*/
protected void controlAddSelection(int index) {
getSwtList().select(index);
getSwtList().showSelection();
}//controlAddSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlRemoveSelection(int)
*/
protected void controlRemoveSelection(int index) {
getSwtList().deselect(index);
}//controlRemoveSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlRemoveAllSelections()
*/
protected void controlRemoveAllSelections() {
getSwtList().deselectAll();
}//controlRemoveAllSelections()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlIsSelected(int)
*/
protected boolean controlIsSelected(int index) {
return getSwtList().isSelected(index);
}//controlIsSelected()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlGetText()
*/
protected String controlGetText() {
throw new RuntimeException("Method not supported - controlGetText");
}//controlGetText()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlGetSelectionCount()
*/
protected int controlGetSelectionCount() {
return getSwtList().getSelectionCount();
}//controlGetSelectionCount()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#controlSetCustomItem(Object)
*/
protected void controlSetCustomItem(Object item) {
throw new RuntimeException("Method not supported - controlSetCustomItem");
}//controlSetCustomItem()//
/**
* Forces the selection event handler to be called.
*/
protected void forceSelectionEvent() { //Should call widgetSelected implemented by the subclass. This name may need to change.//
widgetSelected(null);
}//forceSelectionEvent()//
}//ListBox//

View File

@@ -0,0 +1,939 @@
/*
* 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.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.widgets.Shell;
import com.common.util.*;
import com.common.debug.*;
import com.foundation.view.*;
import com.foundation.view.resource.ResourceReference;
/*
* This one menu class can represent a menu bar, popup menu, cascade menu, or menu item.
*/
public class Menu extends AbstractComponent implements SelectionListener, IAbstractMenu {
public static final int STYLE_BAR = 1 << 10;
public static final int STYLE_POPUP = 1 << 11;
//public static final int STYLE_DROP_DOWN = SWT.DROP_DOWN; //Same as cascade.//
public static final int STYLE_RADIO = SWT.RADIO;
public static final int STYLE_CHECK = SWT.CHECK;
public static final int STYLE_PUSH = SWT.PUSH;
public static final int STYLE_SEPARATOR = SWT.SEPARATOR;
public static final int STYLE_CASCADE = SWT.CASCADE;
public static final int STYLE_RIGHT_TO_LEFT = SWT.RIGHT_TO_LEFT;
public static final int STYLE_LEFT_TO_RIGHT = SWT.LEFT_TO_RIGHT;
public static final int STYLE_UP = SWT.UP;
public static final int STYLE_DOWN = SWT.DOWN;
public static final int LINK_TARGET_SELECTION = AbstractComponent.LAST_LINK_TARGET + 1;
public static final int LINK_TARGET_IS_VISIBLE = AbstractComponent.LAST_LINK_TARGET + 2;
public static final int LINK_TARGET_IS_ENABLED = AbstractComponent.LAST_LINK_TARGET + 3;
public static final int LINK_TARGET_IMAGE = AbstractComponent.LAST_LINK_TARGET + 4;
public static final int LINK_TARGET_TEXT = AbstractComponent.LAST_LINK_TARGET + 5;
public static final int LAST_LINK_TARGET = AbstractComponent.LAST_LINK_TARGET + 5;
/** The menu's parent component which may be another menu. */
private AbstractComponent parent = null;
/** An internal flag to assist in determining whether this menu is allowed to have sub-menus. */
private boolean canHaveSubMenus = false;
/** A collection of sub menus. */
private IList subMenus = null;
/** The menu's name. */
private String name = null;
/** The style the menu was created with. */
private int style = 0;
/** Non-null if the menu is a bar, pop up, or cascade type menu. */
private org.eclipse.swt.widgets.Menu swtMenu;
/** Non-null if the menu is a cascade, push, radio, check, or separator type menu. */
private org.eclipse.swt.widgets.MenuItem swtMenuItem;
/** Called when the button is pressed. */
private IMethodAssociation selectionMethod = null;
/** The menu's selection state resource. */
private SingleResourceAssociation selection = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_BOOLEAN, true, Boolean.FALSE);
/** The linkage for the selection. */
private Linkage selectionLinkage = new Linkage();
/** The menu's title resource. */
private SingleResourceAssociation text = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_TEXT, false, "");
/** The menu's image resource. */
private SingleResourceAssociation image = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_IMAGE, false, null);
/** The resource defining the visible state for the menu. */
private SingleResourceAssociation isVisible = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_BOOLEAN, false, Boolean.TRUE);
/** The resource defining the enabled state for the menu. */
private SingleResourceAssociation isEnabled = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_BOOLEAN, false, Boolean.TRUE);
/** Whether the menu is a push menu which doesn't retain a selection state. */
private final boolean isPushMenu;
/** Whether the menu is a radio or check style menu which retains a selection state. */
private final boolean isRadioCheckMenu;
/** Whether the method called when the menu is pressed should be performed on the UI thread. */
private boolean synchronousSelection = false;
/** A holder for the value of the text. */
private ResourceHolder textHolder = new ResourceHolder(this);
/** A holder for the value of the image. */
private ResourceHolder imageHolder = new ResourceHolder(this);
/** A holder for the value of the visibility flag. */
private ResourceHolder isVisibleHolder = new ResourceHolder(this);
/** A holder for the value of the enabled state flag. */
private ResourceHolder isEnabledHolder = new ResourceHolder(this);
/** The current value for the visibility of the menu. This stores the visiblity even if the menu control is not currently created. */
private boolean isVisibleValue = true;
/** The current value for the enabled state of the menu. This stores the enabled state even if the menu control is not currently created. */
private boolean isEnabledValue = true;
/** The current value for the selection state of the menu. This stores the selection state even if the menu control is not currently created. */
private boolean isSelectedValue = false;
/** The current value for the menu's text. This stores the text even if the menu control is not currently created. */
private String textValue = null;
/** The current value for the menu's image. This stores the image even if the menu control is not currently created. */
private JefImage imageValue = null;
/** The accelerator for the menu item. */
private int acceleratorValue = 0;
/**
* Menu constructor.
* @param parent The component containing the menu. There are only a few components that allow a menu bar. All components may have one popup menu.
* @param name The optional name for the menu.
* @param style The menu style. The menu may be a bar, popup, or cascade if it contains other menus.
* @see #STYLE_BAR
* @see #STYLE_POPUP
* @see #STYLE_CASCADE
* @see #STYLE_RADIO
* @see #STYLE_CHECK
* @see #STYLE_PUSH
* @see #STYLE_SEPARATOR
* @see #STYLE_RIGHT_TO_LEFT
* @see #STYLE_LEFT_TO_RIGHT
* @see #STYLE_UP
* @see #STYLE_DOWN
*/
public Menu(AbstractComponent parent, String name, int style) {
super(parent instanceof IAbstractContainer ? (IAbstractContainer) parent : (IAbstractContainer) parent.getContainer(), null, style, parent);
this.name = name;
this.isPushMenu = (style & STYLE_PUSH) > 0;
this.isRadioCheckMenu = ((style & STYLE_RADIO) > 0) || ((style & STYLE_CHECK) > 0);
this.style = style;
this.canHaveSubMenus = true;
if(parent == null) {
throw new IllegalArgumentException("The menu parent may not be null.");
}//if//
if(!(((style & STYLE_BAR) > 0) || ((style & STYLE_POPUP) > 0))) {
throw new IllegalArgumentException("The parent must be another menu for this menu style.");
}//if//
if((style & STYLE_BAR) > 0) {
if(parent instanceof IFrame) {
((IFrame) parent).setMenuBar(this);
}//if//
}//if//
else if((style & STYLE_POPUP) > 0) {
if(parent instanceof AbstractComponent) {
((AbstractComponent) parent).setMenu(this);
}//if//
}//if//
}//Menu()//
/**
* Menu constructor.
* @param parent The menu containing the menu.
* @param name The optional name for the menu.
* @param style The menu style. The menu may be a bar, popup, or cascade if it contains other menus.
* @see #STYLE_BAR
* @see #STYLE_POPUP
* @see #STYLE_CASCADE
* @see #STYLE_RADIO
* @see #STYLE_CHECK
* @see #STYLE_PUSH
* @see #STYLE_SEPARATOR
* @see #STYLE_RIGHT_TO_LEFT
* @see #STYLE_LEFT_TO_RIGHT
*/
public Menu(Menu parent, String name, int style) {
super(parent.getContainer(), style);
this.parent = parent;
this.name = name;
this.isPushMenu = (style & STYLE_PUSH) > 0;
this.isRadioCheckMenu = ((style & STYLE_RADIO) > 0) || ((style & STYLE_CHECK) > 0);
this.style = style;
this.canHaveSubMenus = (style & STYLE_CASCADE) > 0;
if(parent == null) {
throw new IllegalArgumentException("The menu parent may not be null.");
}//if//
if(((style & STYLE_BAR) > 0) || ((style & STYLE_POPUP) > 0)) {
throw new IllegalArgumentException("The parent may not be another menu for this menu style.");
}//if//
parent.addSubMenu(this);
//Pre-load menus that are on the menu bar.//
if((((Menu) getParent()).style & STYLE_BAR) > 0) {
loadMenu();
}//if//
}//Menu()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
//Only create the SWT control for top level bar and popup menus. The children will be created on demand.//
if(((style & STYLE_BAR) > 0) || ((style & STYLE_POPUP) > 0)) {
this.parent = (AbstractComponent) data;
internalInitializeControl(style, data);
}//if//
}//initializeControl()//
protected void internalInitializeControl(int style, Object data) {
if((getSwtMenu() == null) && (getSwtMenuItem() == null)) {
if((style & STYLE_CASCADE) > 0) {
//Setup both a menu and menu item since they work as one in SWT.//
swtMenuItem = new org.eclipse.swt.widgets.MenuItem((org.eclipse.swt.widgets.Menu) ((Menu) getParent()).getSwtMenu(), SWT.CASCADE); //style
swtMenu = new org.eclipse.swt.widgets.Menu(swtMenuItem);
swtMenuItem.setMenu(swtMenu);
swtMenu.setData(this);
swtMenuItem.setData(this);
setSwtWidget(swtMenu);
if((((Menu) getParent()).style & STYLE_BAR) > 0) {
swtMenu.addMenuListener(new MenuListener() {
boolean isLoaded = false;
public void menuShown(MenuEvent e) {
if(isLoaded) {
unloadMenuChildren();
}//if//
loadMenuChildren();
}//menuShown()//
public void menuHidden(MenuEvent e) {
isLoaded = true;
}//menuHidden()//
});
}//if//
}//if//
else if((style & STYLE_BAR) > 0) {
org.eclipse.swt.widgets.Control parentControl = getParent() instanceof Component ? ((Component) getParent()).getSwtControl() : ((AbstractComponent) getParent()).getShell();
//Setup the popup menu or menu bar depending on the style.//
if(parentControl instanceof org.eclipse.swt.widgets.Decorations) {
swtMenu = new org.eclipse.swt.widgets.Menu((org.eclipse.swt.widgets.Decorations) parentControl, SWT.BAR); //(style ^ STYLE_BAR) |
((org.eclipse.swt.widgets.Decorations) parentControl).setMenuBar(swtMenu);
swtMenu.setData(this);
setSwtWidget(swtMenu);
}//if//
else {
Debug.log("Error: Cannot have a menu bar in a control that does not inherit from SWT's Decorations class.");
}//else//
}//else if//
else if((style & STYLE_POPUP) > 0) {
org.eclipse.swt.widgets.Control control = getParent() instanceof Component ? ((Component) getParent()).getSwtControl() : ((AbstractComponent) getParent()).getShell();
swtMenu = new org.eclipse.swt.widgets.Menu(control);
swtMenu.setData(this);
setSwtWidget(swtMenu);
swtMenu.addMenuListener(new MenuListener() {
boolean isLoaded = false;
public void menuShown(MenuEvent e) {
if(isLoaded) {
unloadMenuChildren();
}//if//
loadMenuChildren();
}//menuShown()//
public void menuHidden(MenuEvent e) {
isLoaded = true;
}//menuHidden()//
});
}//else if//
else {
if(isVisibleValue) {
swtMenuItem = new org.eclipse.swt.widgets.MenuItem(((Menu) getParent()).getSwtMenu(), style);
swtMenuItem.setData(this);
setSwtWidget(swtMenuItem);
swtMenuItem.addSelectionListener(this);
}//if//
}//else//
}//if//
}//initializeControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#getShell()
*/
public Shell getShell() {
return getParent() != null ? getParent().getShell() : null;
}//getShell()//
/**
* Gets the collection of all sub menus.
* @return A collection of menus, or null if this menu cannot hold other menus.
*/
private IList getSubMenus() {
if((canHaveSubMenus) && (subMenus == null)) {
subMenus = new LiteList(10, 30);
}//if//
return subMenus;
}//getSubMenus()//
/**
* Adds a sub menu to this menu.
* @param subMenu The sub menu to be added. Must also implement IAbstractMenu.
*/
public void addSubMenu(AbstractComponent subMenu) {
if(!isInitialized()) {
if(subMenu instanceof IAbstractMenu) {
getSubMenus().add(subMenu);
}//if//
else {
throw new RuntimeException();
}//else//
}//if//
}//addSubMenu()//
/**
* Gets the SWT menu item that represents this menu.
* @return The SWT menu item providing visualization for this menu.
*/
public org.eclipse.swt.widgets.MenuItem getSwtMenuItem() {
return (org.eclipse.swt.widgets.MenuItem) swtMenuItem;
}//getSwtMenuItem()//
/**
* Gets the SWT menu that represents this menu.
* @return The SWT menu providing visualization for this menu.
*/
public org.eclipse.swt.widgets.Menu getSwtMenu() {
return (org.eclipse.swt.widgets.Menu) swtMenu;
}//getSwtMenu()//
/**
* Gets the parent component for this component.
* @return The view component containing this component. This will not be null, and may be a Component or another Menu instance.
*/
public AbstractComponent getParent() {
return parent;
}//getParent()//
/**
* Gets the component's name.
* @return The name of this component.
*/
public String getName() {
return name;
}//getName()//
/**
* Gets the accelerator character for the menu.
* @return The menu accelerator key.
*/
public int getAccelerator() {
verifyThread();
return (getSwtMenuItem() != null) ? getSwtMenuItem().getAccelerator() : 0;
}//getAccelerator()//
/**
* Sets the accelerator character for the menu.
* @param accelerator The menu accelerator key.
*/
public void setAccelerator(int accelerator) {
verifyThread();
acceleratorValue = accelerator;
if(getSwtMenuItem() != null) {
getSwtMenuItem().setAccelerator(acceleratorValue);
}//if//
}//setAccelerator()//
/**
* Gets the component selection state.
* @return Whether the component is in the selected state.
*/
public Boolean getIsSelected() {
verifyThread();
return (Boolean) this.selection.getDefaultValue();
}//getIsSelected()//
/**
* Sets the menu's default selection state.
* @param isSelected Whether the menu is selected by default.
*/
public void setIsSelected(Boolean isSelected) {
verifyThread();
if(isRadioCheckMenu) {
this.selection.setDefaultValue(isSelected);
}//if//
}//setIsSelected()//
/**
* Sets the selection method called when the menu is pressed (intended for push menus only).
* @param selectionMethod The method called when the menu is selected.
*/
public void setSelectionMethod(IMethodAssociation selectionMethod) {
verifyThread();
if(isPushMenu) {
this.selectionMethod = selectionMethod;
}//if//
}//setSelectionMethod()//
/**
* Adds a link for the selection.
* @param link The local linkage for the selection.
*/
public void addSelectionLink(LinkData link) {
selectionLinkage.add(link);
}//addSelectionLink()//
/**
* Sets an association container used to access the text.
* @param container The text association metadata.
*/
public void setTextAssociation(SingleAssociationContainer container) {
verifyThread();
this.text.setAssociations(container);
}//setTextAssociation()//
/**
* Sets an association container used to access the image.
* @param container The image association metadata.
*/
public void setImageAssociation(SingleAssociationContainer container) {
verifyThread();
this.image.setAssociations(container);
}//setImageAssociation()//
/**
* Sets an association container used to access the selection.
* @param container The selection association metadata.
*/
public void setSelectionAssociation(SingleAssociationContainer container) {
verifyThread();
this.selection.setAssociations(container);
}//setSelectionAssociation()//
/**
* Sets the association container used to access whether the menu is enabled.
* @param container The enabled state association metadata.
*/
public void setIsEnabledAssociation(SingleAssociationContainer container) {
verifyThread();
this.isEnabled.setAssociations(container);
}//setIsEnabledAssociation()//
/**
* Sets the association container used to access whether the menu is visible.
* @param container The visible state association metadata.
*/
public void setIsVisibleAssociation(SingleAssociationContainer container) {
verifyThread();
this.isVisible.setAssociations(container);
}//setIsVisibleAssociation()//
/**
* Sets whether the selection synchronization should wait for a reply before returning control to the user.
* @param synchronousSelection Whether the selection is synchronous.
*/
public void setSynchronousSelection(boolean synchronousSelection) {
verifyThread();
if(isPushMenu) {
this.synchronousSelection = synchronousSelection;
}//if//
}//setSynchronousSelection()//
/**
* Sets the component default text.
* @param text The text that will appear in the component.
*/
public void setText(String text) {
verifyThread();
this.text.setDefaultValue(text);
}//setText()//
/**
* Sets the component's default text resource.
* @param text The text to be displayed by this component.
*/
public void setText(ResourceReference text) {
verifyThread();
this.text.setDefaultValue(text);
}//setText()//
/**
* Sets the component default image.
* @param image The image to be displayed by the component.
*/
public void setImage(JefImage image) {
verifyThread();
this.image.setDefaultValue(image);
}//setImage()//
/**
* Sets the component's default image resource.
* @param image The image to be displayed by this component.
*/
public void setImage(ResourceReference image) {
verifyThread();
this.image.setDefaultValue(image);
}//setImage()//
/**
* Sets whether the menu is visible by default.
* @param isVisible The default visiblity for the menu.
*/
public void setIsVisible(boolean isVisible) {
verifyThread();
this.isVisible.setDefaultValue(isVisible ? Boolean.TRUE : Boolean.FALSE);
}//setIsVisible()//
/**
* Sets the default visibility resource.
* @param isVisible Whether the user can see the component.
*/
public void setIsVisible(ResourceReference isVisible) {
verifyThread();
this.isVisible.setDefaultValue(isVisible);
}//setIsVisible()//
/**
* Sets the default enabled state of the menu.
* @param isEnabled Whether the menu is enabled by default.
*/
public void setIsEnabled(boolean isEnabled) {
verifyThread();
this.isEnabled.setDefaultValue(isEnabled ? Boolean.TRUE : Boolean.FALSE);
}//setIsEnabled()//
/**
* Sets the default enabled state resource.
* @param isEnabled Whether the user can interact with the component.
*/
public void setIsEnabled(ResourceReference isEnabled) {
verifyThread();
this.isEnabled.setDefaultValue(isEnabled);
}//setIsEnabled()//
/**
* Sets the menu location.
* @param x The upper left point's X coordinate.
* @param y The upper left point's Y coordinate.
*/
public void setLocation(int x, int y) {
if(getSwtMenu() != null && !getSwtMenu().isDisposed()) {
getSwtMenu().setLocation(x, y);
}//if//
}//setLocation()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent event) {
widgetSelected(event);
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent event) {
selectionChanged(getSwtMenuItem().getSelection());
}//widgetSelected()//
/**
* Called when the selection is changed in the view control.
* This method updates all bindings and
* @param isSelected Whether the control is selected (stateful controls only).
*/
protected void selectionChanged(boolean isSelected) {
if((isPushMenu) && (selectionMethod != null)) {
selectionMethod.invoke(new Object[] {isSelected ? Boolean.TRUE : Boolean.FALSE}, synchronousSelection); //TODO: Save the array for reuse.//
}//if//
if(isRadioCheckMenu) {
selection.setValue(isSelected ? Boolean.TRUE : Boolean.FALSE);
}//if//
selectionLinkage.invoke(isRadioCheckMenu ? isSelected ? Boolean.TRUE : Boolean.FALSE : null);
}//selectionChanged()//
/* (non-Javadoc)
* @see com.foundation.view.IView#viewInitializeAll()
*/
public void internalViewInitializeAll() {
try {
//Initialize this component.//
internalViewInitialize();
//Initialize sub-menus.//
if((getSubMenus() != null) && (getSubMenus().getSize() > 0)) {
IIterator iterator = getSubMenus().iterator();
while(iterator.hasNext()) {
AbstractComponent next = (AbstractComponent) iterator.next();
next.internalViewInitializeAll();
}//while//
}//if//
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
}//catch//
}//internalViewInitializeAll()//
/* (non-Javadoc)
* @see com.foundation.view.IView#internalViewReleaseAll()
*/
public void internalViewReleaseAll() {
try {
//Release sub-menus.//
if((getSubMenus() != null) && (getSubMenus().getSize() > 0)) {
IIterator iterator = getSubMenus().iterator();
while(iterator.hasNext()) {
AbstractComponent next = (AbstractComponent) iterator.next();
next.internalViewReleaseAll();
}//while//
}//if//
//Release this component.//
internalViewRelease();
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}//internalViewReleaseAll()//
/* (non-Javadoc)
* @see com.foundation.view.IView#viewRefreshAll()
*/
public void internalViewRefreshAll() {
try {
//Refresh this component.//
internalViewRefresh();
//Refresh sub-menus.//
if((getSubMenus() != null) && (getSubMenus().getSize() > 0)) {
IIterator iterator = getSubMenus().iterator();
while(iterator.hasNext()) {
AbstractComponent next = (AbstractComponent) iterator.next();
next.internalViewRefreshAll();
}//while//
}//if//
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}//internalViewRefreshAll()//
/* (non-Javadoc)
* @see com.foundation.view.IView#viewSynchronizeAll()
*/
public void internalViewSynchronizeAll() {
try {
//Synchronize this component.//
internalViewSynchronize();
//Synchronize sub-menus.//
if((getSubMenus() != null) && (getSubMenus().getSize() > 0)) {
IIterator iterator = getSubMenus().iterator();
while(iterator.hasNext()) {
AbstractComponent next = (AbstractComponent) iterator.next();
next.internalViewSynchronizeAll();
}//while//
}//if//
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}//internalViewSynchronizeAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
text.initialize();
image.initialize();
isVisible.initialize();
isEnabled.initialize();
selection.initialize();
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
text.release();
image.release();
isVisible.release();
isEnabled.release();
selection.release();
textHolder.release();
imageHolder.release();
isVisibleHolder.release();
isEnabledHolder.release();
if(imageValue != null && getSwtMenuItem() != null) {
destroyImage(imageValue);
imageValue = null;
}//if//
if(getSwtMenu() != null && !getSwtMenu().isDisposed()) {
getSwtMenu().dispose();
swtMenu = null;
}//if//
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
getSwtMenuItem().removeSelectionListener(this);
getSwtMenuItem().dispose();
swtMenuItem = null;
}//if//
super.internalViewRelease();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
internalViewRefreshSelection();
internalViewRefreshText();
internalViewRefreshImage();
internalViewRefreshIsEnabled();
internalViewRefreshIsVisible();
super.internalViewRefresh();
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
}//internalViewSynchronize()//
/**
* Refreshes the selection.
*/
protected void internalViewRefreshSelection() {
if(selection.refresh()) {
Boolean value = (Boolean) selection.getValue();
isSelectedValue = value.booleanValue();
if(getSwtMenuItem() != null) {
getSwtMenuItem().setSelection(value.booleanValue());
}//if//
selectionLinkage.invoke(value);
}//if//
}//internalViewRefreshSelection()//
/**
* Refreshes the text from the text attribute and the default text.
*/
protected void internalViewRefreshText() {
if(text.refresh()) {
textHolder.setValue(text.getValue());
}//if//
}//internalViewRefreshText()//
/**
* Refreshes the image from the image url attribute and the default image url.
*/
protected void internalViewRefreshImage() {
if(image.refresh()) {
imageHolder.setValue(image.getValue());
}//if//
}//internalViewRefreshImage()//
/**
* Refreshes whether the menu is enabled based on the attribute value or if null the default flag value.
*/
protected void internalViewRefreshIsEnabled() {
if(isEnabled.refresh()) {
isEnabledHolder.setValue(isEnabled.getValue());
}//if//
}//internalViewRefreshIsEnabled()//
/**
* Refreshes whether the menu is visible based on the attribute value or if null the default flag value.
*/
protected void internalViewRefreshIsVisible() {
if(isVisible.refresh()) {
isVisibleHolder.setValue(isVisible.getValue());
}//if//
}//internalViewRefreshIsVisible()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalResourceHolderChanged(com.foundation.view.swt.ResourceHolder, java.lang.Object, java.lang.Object)
*/
protected void internalResourceHolderChanged(ResourceHolder resource, Object oldValue, Object newValue, int flags) {
if(resource == textHolder) {
textValue = newValue == null ? "" : (String) newValue;
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
getSwtMenuItem().setText(textValue);
}//if//
}//if//
else if(resource == imageHolder) {
imageValue = (JefImage) newValue;
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
destroyImage(getSwtMenuItem().getImage());
getSwtMenuItem().setImage(createImage(imageValue));
}//if//
}//else if//
else if(resource == isVisibleHolder) {
isVisibleValue = ((Boolean) newValue).booleanValue();
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
//getSwtMenuItem().setVisible(isVisibleValue);
}//if//
if(getSwtMenu() != null && !getSwtMenu().isDisposed()) {
getSwtMenu().setVisible(isVisibleValue);
}//if//
}//else if//
else if(resource == isEnabledHolder) {
isEnabledValue = ((Boolean) newValue).booleanValue();
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
getSwtMenuItem().setEnabled(isEnabledValue);
}//if//
if(getSwtMenu() != null && !getSwtMenu().isDisposed()) {
getSwtMenu().setEnabled(isEnabledValue);
}//if//
}//else if//
else {
super.internalResourceHolderChanged(resource, oldValue, newValue, flags);
}//else//
}//internalOnAssociationChanged()//
/* (non-Javadoc)
* @see com.foundation.tcv.swt.client.AbstractComponent#internalOnLinkInvoked(int, java.lang.Object)
*/
protected void internalOnLinkInvoked(int linkTarget, Object data) {
switch(linkTarget) {
case LINK_TARGET_IS_VISIBLE: {
isVisibleValue = data != null && data instanceof Boolean ? ((Boolean) data).booleanValue() : false;
if(getSwtMenu() != null && !getSwtMenu().isDisposed()) {
getSwtMenu().setVisible(isVisibleValue);
}//if//
break;
}//case//
case LINK_TARGET_IS_ENABLED: {
isEnabledValue = data != null && data instanceof Boolean ? ((Boolean) data).booleanValue() : false;
if(getSwtMenu() != null && !getSwtMenu().isDisposed()) {
getSwtMenu().setEnabled(isEnabledValue);
}//if//
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
getSwtMenuItem().setEnabled(isEnabledValue);
}//if//
break;
}//case//
case LINK_TARGET_SELECTION: {
isSelectedValue = data instanceof Boolean ? ((Boolean) data).booleanValue() : false;
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
if((isRadioCheckMenu) && (isSelectedValue != getSwtMenuItem().getSelection())) {
getSwtMenuItem().setSelection(isSelectedValue);
selectionChanged(isSelectedValue);
}//if//
else {
selectionChanged(true);
}//else//
}//if//
break;
}//case//
case LINK_TARGET_IMAGE: {
imageValue = (JefImage) data;
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed() && data instanceof JefImage) {
destroyImage(getSwtMenuItem().getImage());
getSwtMenuItem().setImage(createImage(imageValue));
}//if//
break;
}//case//
case LINK_TARGET_TEXT: {
textValue = data instanceof String ? (String) data : "";
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
getSwtMenuItem().setText(textValue);
}//if//
break;
}//case//
default: {
super.internalOnLinkInvoked(linkTarget, data);
break;
}//default//
}//switch//
}//internalOnLinkInvoked()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.ResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == isVisible) {
internalViewRefreshIsVisible();
}//if//
else if(resourceAssociation == isEnabled) {
internalViewRefreshIsEnabled();
}//else if//
else if(resourceAssociation == text) {
internalViewRefreshText();
}//else if//
else if(resourceAssociation == image) {
internalViewRefreshImage();
}//else if//
else if(resourceAssociation == selection) {
internalViewRefreshSelection();
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see #onEventFired()
*/
protected void internalOnEventFired(IEventAssociation eventAssociation, Object[] eventArguments) {
}//internalOnEventFired()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IAbstractMenu#loadMenu()
*/
public void loadMenu() {
internalInitializeControl(style, null);
if(getSwtMenu() != null) {
getSwtMenu().setVisible(isVisibleValue);
getSwtMenu().setEnabled(isEnabledValue);
}//if//
if(getSwtMenuItem() != null) {
getSwtMenuItem().setText(textValue == null ? "" : textValue);
getSwtMenuItem().setImage(createImage(imageValue));
getSwtMenuItem().setSelection(isSelectedValue);
getSwtMenuItem().setEnabled(isEnabledValue);
getSwtMenuItem().setAccelerator(acceleratorValue);
}//if//
}//loadMenu()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IAbstractMenu#unloadMenu()
*/
public void unloadMenu() {
if(getSwtMenuItem() != null && imageValue != null) {
destroyImage(imageValue);
}//if//
if(getSwtMenu() != null && !getSwtMenu().isDisposed()) {
getSwtMenu().dispose();
swtMenu = null;
}//if//
if(getSwtMenuItem() != null && !getSwtMenuItem().isDisposed()) {
getSwtMenuItem().dispose();
swtMenuItem = null;
}//if//
}//loadMenu()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IAbstractMenu#loadMenuChildren()
*/
public void loadMenuChildren() {
if(getSubMenus() != null) {
for(int index = 0; index < getSubMenus().getSize(); index++) {
IAbstractMenu menu = (IAbstractMenu) getSubMenus().get(index);
menu.loadMenu();
menu.loadMenuChildren();
}//for//
}//if//
}//loadMenuChildren()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IAbstractMenu#unloadMenuChildren()
*/
public void unloadMenuChildren() {
if(getSubMenus() != null) {
for(int index = 0; index < getSubMenus().getSize(); index++) {
IAbstractMenu menu = (IAbstractMenu) getSubMenus().get(index);
menu.unloadMenuChildren();
menu.unloadMenu();
}//for//
}//if//
}//unloadMenuChildren()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
return super.toString() + (getName() != null ? " (named: " + getName() + ")" : "");
}//toString()//
}//Menu()//

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 2003,2008 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import com.common.debug.*;
import com.foundation.view.*;
public class MessageDialog extends Dialog {
public static final int STYLE_ICON_ERROR = SWT.ICON_ERROR;
/** The default setting for the dialog if none other is given. */
public static final int STYLE_ICON_INFORMATION = SWT.ICON_INFORMATION;
public static final int STYLE_ICON_QUESTION = SWT.ICON_QUESTION;
public static final int STYLE_ICON_WARNING = SWT.ICON_WARNING;
public static final int STYLE_ICON_WORKING = SWT.ICON_WORKING;
/** The default setting for the dialog if none other is given. */
public static final int STYLE_OK = SWT.OK;
public static final int STYLE_CANCEL = SWT.CANCEL;
public static final int STYLE_YES = SWT.YES;
public static final int STYLE_NO = SWT.NO;
public static final int STYLE_RETRY = SWT.RETRY;
public static final int STYLE_IGNORE = SWT.IGNORE;
public static final int STYLE_ABORT = SWT.ABORT;
public static final int STYLE_PRIMARY_MODAL = SWT.PRIMARY_MODAL;
/** The default setting for the dialog if none other is given. */
public static final int STYLE_APPLICATION_MODAL = SWT.APPLICATION_MODAL;
public static final int STYLE_SYSTEM_MODAL = SWT.SYSTEM_MODAL;
/**
* MessageDialog constructor.
* @param parent The parent view (accessable from the view controller by calling the getView() method).
*/
public MessageDialog(IView parent) {
super();
if(parent instanceof Container) {
org.eclipse.swt.widgets.Shell shell = ((Container) parent).getSwtControl().getShell();
shell.forceFocus();
shell.forceActive();
//shell.setActive();
//shell.setFocus();
setSwtDialog(new org.eclipse.swt.widgets.MessageBox(shell));
}//if//
else {
Debug.log("Error: Cannot create a dialog without a valid SWT parent control.");
}//else//
}//MessageDialog()//
/**
* MessageDialog constructor.
* @param parent The parent view (accessable from the view controller by calling the getView() method).
* @param style One or more of the style properties defined by this class (or'd together).
*/
public MessageDialog(IView parent, int style) {
super();
if(parent instanceof Container) {
org.eclipse.swt.widgets.Shell shell = ((Container) parent).getSwtControl().getShell();
shell.forceFocus();
shell.forceActive();
shell.setActive();
shell.setFocus();
setSwtDialog(new org.eclipse.swt.widgets.MessageBox(((Container) parent).getSwtControl().getShell(), style));
}//if//
else {
Debug.log("Error: Cannot create a dialog without a valid SWT parent control.");
}//else//
}//MessageDialog()//
/**
* Gets the SWT message dialog instance.
* @return The SWT message dialog.
*/
private org.eclipse.swt.widgets.MessageBox getSwtMessageDialog() {
return (org.eclipse.swt.widgets.MessageBox) getSwtDialog();
}//getSwtMessageDialog()//
/**
* Gets the message to be displayed to the user.
* @return The dialog message.
*/
public String getMessage() {
return getSwtMessageDialog().getMessage();
}//getMessage()//
/**
* Sets the message to be displayed to the user.
* @param message The dialog message.
*/
public void setMessage(String message) {
getSwtMessageDialog().setMessage(message);
}//setMessage()//
/**
* Opens the dialog making it visible to the user.
* @return The id of the button used to dismiss the message dialog. For example MessageDialog.STYLE_OK.
*/
public int open() {
return getSwtMessageDialog().open();
}//open()//
}//MessageDialog//

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2006,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.foundation.view.IResourceHolderComponent;
import com.foundation.view.resource.AbstractResourceService;
/*
* Used by components that may receive either a static value or a reference to a resource.
* This resource association will take the value, register listeners if it is a resource, get the actual value if it is a resource, and notify the component when the value is set or is changed.
* <p><b>Note: It is probably a fair bit more efficient to use an AbstractResourceHolder for each element in collecton style control since the resource manager then performs all the indexing instead of having a middle man.</b></p>
*/
public class MultiResourceHolder extends com.foundation.view.AbstractMultiResourceHolder {
/**
* MultiResourceHolder constructor.
* @param component The component that will be notified when the resource value changes.
*/
public MultiResourceHolder(IResourceHolderComponent component) {
super(component);
}//ResourceHolder()//
/* (non-Javadoc)
* @see com.foundation.view.ResourceHolder#getResourceService()
*/
protected AbstractResourceService getResourceService() {
return getComponent().getResourceService();
}//getResourceService()//
}//MultiResourceHolder//

View File

@@ -0,0 +1,348 @@
/*
* 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.view.swt;
import javax.management.RuntimeErrorException;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;
import com.common.util.*;
import com.common.debug.*;
import com.foundation.view.*;
import com.foundation.view.swt.layout.Layout;
import com.foundation.view.swt.layout.LayoutData;
import com.foundation.util.*;
import com.foundation.controller.*;
import com.foundation.event.*;
public class Panel extends Container {
/** The attribute that provides the collection of internal view controllers. */
private IAttributeAssociation internalViewsAssociation = null;
/** A support for receiving collection change events. */
private EventSupport eventSupport = new EventSupport(null);
/** The collection of internal view controllers. */
private ICollection internalViewControllers = null;
/** The collection of internal view controllers currently open. Maintaining this collection is necessary in the event that all view controllers are removed from the collection. */
private LiteList openViewControllers = null;
/** The next location ? */
private int nextLocation = 0;
/** The location increment ? */
private int locationIncrement = 20;
/** The composite used to slide the contents around if the user has requested vertical and/or horizontal scrolling. */
private ScrolledComposite scrolledComposite;
/** The composite used to slide the contents around if the user has requested vertical and/or horizontal scrolling. */
private Composite composite;
/**
* Panel default constructor.
* <p>Warning: This is only for use by the framework. This should never be called to create a useable instance.</p>
*/
public Panel() {
}//Panel()//
/**
* Panel constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_NO_BACKGROUND
* @see #STYLE_NO_FOCUS
* @see #STYLE_NO_MERGE_PAINTS
* @see #STYLE_NO_REDRAW_RESIZE
* @see #STYLE_NO_RADIO_GROUP
* @see #STYLE_EMBEDDED
* @see #STYLE_DOUBLE_BUFFERED
* @see #STYLE_H_SCROLL
* @see #STYLE_V_SCROLL
* @see #STYLE_BORDER
* @see #STYLE_LEFT_TO_RIGHT
* @see #STYLE_RIGHT_TO_LEFT
*/
public Panel(IAbstractContainer parent, String name, int style) {
super(parent, name, style);
}//Panel()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
boolean hScroll = ((style & SWT.H_SCROLL) != 0);
boolean vScroll = ((style & SWT.V_SCROLL) != 0);
if(hScroll || vScroll) {
scrolledComposite = new ScrolledComposite(((IAbstractSwtContainer) getContainer()).getSwtParent(), style);
scrolledComposite.setData(this);
composite = new Composite(scrolledComposite, 0);
composite.setData(this);
scrolledComposite.setTabList(new Control[] {composite});
scrolledComposite.setContent(composite);
setSwtWidget(scrolledComposite);
scrolledComposite.setAlwaysShowScrollBars(false);
scrolledComposite.setExpandHorizontal(true);
scrolledComposite.setExpandVertical(true);
scrolledComposite.setMinSize(0, 0);
if(hScroll) {
getSwtComposite().getHorizontalBar().setVisible(false);
getSwtComposite().getHorizontalBar().setIncrement(20);
}//if//
if(vScroll) {
getSwtComposite().getVerticalBar().setVisible(false);
getSwtComposite().getVerticalBar().setIncrement(20);
}//if//
}//if//
else {
setSwtWidget(new org.eclipse.swt.widgets.Composite(((IAbstractSwtContainer) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//else//
}//initializeControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container#internalLayout()
*/
protected void internalLayout() {
if(scrolledComposite != null) {
composite.setSize(composite.computeSize(-1, -1, true));
}//if//
super.internalLayout();
}//internalLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container#postResize()
*/
public void postResize() {
super.postResize();
if(scrolledComposite != null) {
Rectangle interior = scrolledComposite.getClientArea();
Rectangle interior2 = null;
scrolledComposite.setMinSize(0, 0);
while(!interior.equals(interior2)) {
Point size = null;
composite.computeSize(0, 0, true);
if(composite.getLayout() instanceof com.foundation.view.swt.layout.Layout) {
size = ((com.foundation.view.swt.layout.Layout) composite.getLayout()).computeCurrentSize(composite);
}//if//
else {
Debug.log(new RuntimeException("Only Brainstorm based layouts may be used. The layout must extend " + Layout.class.getName()));
}//else//
if(getSwtComposite().getHorizontalBar() != null) {
scrolledComposite.setMinWidth(size.x);
}//if//
if(getSwtComposite().getVerticalBar() != null) {
scrolledComposite.setMinHeight(size.y);
}//if//
interior2 = interior;
interior = scrolledComposite.getClientArea();
}//while//
}//if//
}//postResize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container#getSwtParent()
*/
public org.eclipse.swt.widgets.Composite getSwtParent() {
return scrolledComposite != null ? composite : getSwtComposite();
}//getSwtParent()//
/**
* Sets the internal view controller collection.
* @param internalViewsAssociation The association containing the collection of view controllers representing views that exist within this panel.
*/
public void setInternalViewsAssociation(IAttributeAssociation internalViewsAssociation) {
this.internalViewsAssociation = internalViewsAssociation;
}//setInternalViewsAssociation()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
if(internalViewsAssociation != null) {
openViewControllers = new LiteList(10, 50);
internalViewsAssociation.register();
}//if//
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
super.internalViewRelease();
if(internalViewsAssociation != null) {
internalViewsAssociation.unregister();
eventSupport.unregisterAll();
closeAllViews();
}//if//
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
if(internalViewsAssociation != null) {
ICollection internalViewControllers = (ICollection) internalViewsAssociation.getAttributeValue();
ICollection copy = null;
if(this.internalViewControllers != internalViewControllers) {
//Unregister the old event hooks.//
if(this.internalViewControllers instanceof IEventEmitter) {
eventSupport.unregisterAll((IEventEmitter) this.internalViewControllers);
}//if//
closeAllViews();
//Save a reference to the current collection in the model.//
this.internalViewControllers = internalViewControllers;
if(internalViewControllers instanceof IManagedCollection) {
//Register the new event hooks.//
synchronized(internalViewControllers) {
eventSupport.register(((IManagedCollection) internalViewControllers), IManagedCollection.EVENT.getNumber(), this, true);
copy = new LiteList(internalViewControllers);
}//synchronized//
}//if//
}//if//
if(copy != null) {
IIterator iterator = copy.iterator();
while(iterator.hasNext()) {
Object next = iterator.next();
if(next instanceof ViewController) {
closeView((ViewController) next);
openViewControllers.add(next);
}//if//
else {
Debug.log("Error: Only view controllers may populate the collection of internal frames attached to the panel.");
}//else//
}//while//
}//if//
}//if//
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
super.internalViewSynchronize();
}//internalViewSynchronize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalEvaluate(com.common.event.IEventEmitter, int, java.lang.Object[])
*/
protected void internalEvaluate(IEventEmitter eventEmitter, int eventNumber, Object[] arguments) {
//Add, remove, or replace items from the list.//
if(eventEmitter == internalViewControllers) {
if(eventNumber == IManagedCollection.EVENT.getNumber()) {
CollectionChangeEvent event = (CollectionChangeEvent) arguments[0];
if(event.hasAdds()) {
if(event.getAddedObjects() != null) {
IIterator iterator = event.getAddedObjects().iterator();
while(iterator.hasNext()) {
Object next = iterator.next();
openView((ViewController) next);
}//while//
}//if//
else {
openView((ViewController) event.getAddedObject());
}//else//
}//if//
if(event.hasRemoves()) {
if(event.getRemovedObjects() != null) {
IIterator iterator = event.getRemovedObjects().iterator();
while(iterator.hasNext()) {
Object next = iterator.next();
openViewControllers.remove(next);
closeView((ViewController) next);
}//while//
}//if//
else {
openViewControllers.remove(event.getRemovedObject());
closeView((ViewController) event.getRemovedObject());
}//else//
}//if//
}//if//
}//if//
else {
super.internalEvaluate(eventEmitter, eventNumber, arguments);
}//else//
}//internalEvaluate()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#onValueChanged(com.foundation.view.swt.IAttributeAssociation)
*/
protected void internalOnValueChanged(IAttributeAssociation attributeAssociation) {
if(attributeAssociation == internalViewsAssociation) {
internalViewRefresh();
}//if//
else {
super.internalOnValueChanged(attributeAssociation);
}//else//
}//internalOnValueChanged()//
/**
* Opens the view for the associated view controller.
* @param viewController The view controller that will provide the view.
*/
private void openView(ViewController viewController) {
IView view = viewController.openPartial(this, null);
if(view instanceof Frame) {
int location = nextLocation;
if(location + ((Frame) view).getSwtControl().getSize().x > getSwtControl().getSize().x) {
location = 0;
}//if//
else if(location + ((Frame) view).getSwtControl().getSize().y > getSwtControl().getSize().y) {
location = 0;
}//else if//
nextLocation = location + locationIncrement;
((Frame) view).setLocation(location, location);
}//if//
else {
//I could at some point wrapper the view component with a frame.//
Debug.log("Error: The view must be a frame for it to be a valid internal view.");
}//else//
}//openView()//
/**
* Closes the view for the associated view controller.
* @param viewController The view controller that provided the view.
*/
private void closeView(ViewController viewController) {
viewController.close();
}//closeView()//
/**
* Closes all the internal views.
*/
private void closeAllViews() {
IIterator iterator = openViewControllers.iterator();
while(iterator.hasNext()) {
closeView((ViewController) iterator.next());
}//while//
openViewControllers.removeAll();
}//closeAllViews()//
}//Panel//

View File

@@ -0,0 +1,157 @@
/*
* Copyright (c) 2005,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Control;
import com.foundation.controller.ViewController;
import com.foundation.view.ResourceAssociation;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
import com.foundation.view.swt.util.SwtUtilities;
public class PanelViewer extends Container {
/** The association that provides a view controller whose view will be displayed in this panel. */
private SingleResourceAssociation controllerAssociation = new SingleResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_OBJECT, false, null);
/** The view controller whose view is currently displayed. */
private ViewController viewController = null;
/** Whether the panel viewer should allow the focus to change when the viewed contents change. */
private boolean changeFocus = true;
/**
* PanelViewer constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_NO_BACKGROUND
* @see #STYLE_NO_FOCUS
* @see #STYLE_NO_MERGE_PAINTS
* @see #STYLE_NO_REDRAW_RESIZE
* @see #STYLE_NO_RADIO_GROUP
* @see #STYLE_H_SCROLL
* @see #STYLE_V_SCROLL
* @see #STYLE_BORDER
* @see #STYLE_LEFT_TO_RIGHT
* @see #STYLE_RIGHT_TO_LEFT
*/
public PanelViewer(Container parent, String name, int style) {
super(parent, name, style);
}//PanelViewer()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.Composite(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
getSwtComposite().setLayout(new FillLayout());
}//initializeControl()//
/**
* Gets the SWT composite that represents this panel.
* @return The SWT composite providing visualization for this panel.
*/
public org.eclipse.swt.widgets.Composite getSwtComposite() {
return (org.eclipse.swt.widgets.Composite) getSwtControl();
}//getSwtComposite()//
/**
* Sets the association container used to access the controller.
* @param container The controller association metadata.
*/
public void setControllerAssociation(SingleAssociationContainer container) {
controllerAssociation.setAssociations(container);
}//setControllerAssociation()//
/**
* Sets whether the focus should be allowed to change to the viewer's component when the contents of the viewer changes.
* @param changeFocus Whether focus changes should be allowed when changing the viewer contents.
*/
public void setChangeFocus(boolean changeFocus) {
this.changeFocus = changeFocus;
}//setChangeFocus()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
controllerAssociation.initialize();
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
super.internalViewRelease();
controllerAssociation.release();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalViewRefreshController();
}//internalViewRefresh()//
/**
* Refreshes the controller association.
*/
protected void internalViewRefreshController() {
if(controllerAssociation.refresh()) {
Object value = controllerAssociation.getValue();
//Close the previous view.//
if(viewController != null) {
viewController.close();
viewController = null;
}//if//
//Open the new view.//
if(value instanceof ViewController) {
Control focusControl = getDisplay().getFocusControl();
stopRendering();
getSwtControl().setRedraw(false);
try {
viewController = (ViewController) value;
viewController.openPartial(this, getViewContext());
resize();
if((!changeFocus) && (focusControl != null)) {
focusControl.forceFocus();
}//if//
if(getComponents().getSize() == 1) {
getSwtComposite().setTabList(new Control[] {((Component) getComponents().getFirst()).getSwtControl()});
}//if//
else {
getSwtComposite().setTabList(null);
}//else//
}//try//
finally {
getSwtControl().setRedraw(true);
startRendering();
//layout();
}//finally//
}//if//
}//if//
}//internalViewRefreshController()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
super.internalViewSynchronize();
}//internalViewSynchronize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == controllerAssociation) {
internalViewRefreshController();
}//if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
}//PanelViewer//

View File

@@ -0,0 +1,238 @@
/*
* 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.view.swt;
import java.math.BigDecimal;
import org.eclipse.swt.SWT;
import com.foundation.view.*;
public class Progress extends Component {
public static final int STYLE_SMOOTH = SWT.SMOOTH;
public static final int STYLE_HORIZONTAL = SWT.HORIZONTAL;
public static final int STYLE_VERTICAL = SWT.VERTICAL;
public static final int STYLE_INDETERMINATE = SWT.INDETERMINATE;
/** The progress' maximum resource which bounds the progress states. */
private SingleResourceAssociation maximum = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, false, new Integer(0));
/** The progress' minimum resource which bounds the progress states. */
private SingleResourceAssociation minimum = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, false, new Integer(0));
/** The progress' progress resource which defines the current progress state. */
private SingleResourceAssociation progress = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_BIG_DECIMAL, false, new Integer(0));
/** The current progress in its original form. */
private BigDecimal currentProgress = null;
/** The multiplier used to generate an integer from the current progress value. */
private BigDecimal multiplier = null;
/**
* Progress constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_SMOOTH
* @see #STYLE_HORIZONTAL
* @see #STYLE_VERTICAL
* @see #STYLE_INDETERMINATE
*/
public Progress(Container parent, String name, int style) {
super(parent, name, style);
}//Progress()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.ProgressBar(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT progress bar that represents this progress.
* @return The SWT progress bar providing visualization for this progress.
*/
public org.eclipse.swt.widgets.ProgressBar getSwtProgress() {
return (org.eclipse.swt.widgets.ProgressBar) getSwtWidget();
}//getSwtProgress()//
/**
* Gets the current progress.
* @return The current progress in its original form.
*/
public BigDecimal getCurrentProgress() {
return currentProgress;
}//getCurrentProgress()//
/**
* Sets the current progress.
* @param currentProgress The current progress in its original form.
*/
public void setCurrentProgress(BigDecimal currentProgress) {
this.currentProgress = currentProgress;
}//setCurrentProgress()//
/**
* Gets the multiplier used to construct an integer from the progress value.
* @return The progress multiplier.
*/
public BigDecimal getMultiplier() {
return multiplier;
}//getMultiplier()//
/**
* Sets the multiplier used to construct an integer from the progress value.
* @param multiplier The progress multiplier.
*/
public void setMultiplier(BigDecimal multiplier) {
this.multiplier = multiplier;
}//setMultiplier()//
/**
* Sets the component maximum progress value.
* @param maximum The maximum value in the progress range.
*/
public void setMaximum(Integer maximum) {
verifyThread();
this.maximum.setDefaultValue(maximum);
}//setMaximum()//
/**
* Sets the component minimum progress value.
* @param minimum The minimum value in the progress range. This must be greater than or equal to zero.
*/
public void setMinimum(Integer minimum) {
verifyThread();
this.minimum.setDefaultValue(minimum);
}//setMinimum()//
/**
* Sets the component progress value.
* @param progress The current progress value. This must be greater than or equal to the minimum and less than or equal to the maximum.
*/
public void setProgress(BigDecimal progress) {
verifyThread();
this.progress.setDefaultValue(progress);
}//setProgress()//
/**
* Sets the association container used to access the maximum value.
* @param container The maximum value association metadata.
*/
public void setMaximumAssociation(SingleAssociationContainer container) {
verifyThread();
this.maximum.setAssociations(container);
}//setMaximumAssociation()//
/**
* Sets the association container used to access the minimum value.
* @param container The minimum value association metadata.
*/
public void setMinimumAssociation(SingleAssociationContainer container) {
verifyThread();
this.minimum.setAssociations(container);
}//setMinimumAssociation()//
/**
* Sets the association container used to access the progress value.
* @param container The progress value association metadata.
*/
public void setProgressAssociation(SingleAssociationContainer container) {
verifyThread();
this.progress.setAssociations(container);
}//setProgressAssociation()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
maximum.initialize();
minimum.initialize();
progress.initialize();
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
super.internalViewRelease();
maximum.release();
minimum.release();
progress.release();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalViewRefreshMaximum();
internalViewRefreshMinimum();
internalViewRefreshProgress();
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
super.internalViewSynchronize();
}//internalViewSynchronize()//
/**
* Refreshes the progress maximum.
*/
protected void internalViewRefreshMaximum() {
if(maximum.refresh()) {
Integer value = (Integer) maximum.getValue();
getSwtProgress().setMaximum(value.intValue());
}//if//
}//internalViewRefreshMaximum()//
/**
* Refreshes the progress maximum.
*/
protected void internalViewRefreshMinimum() {
if(minimum.refresh()) {
Integer value = (Integer) minimum.getValue();
getSwtProgress().setMinimum(value.intValue());
}//if//
}//internalViewRefreshMinimum()//
/**
* Refreshes the current progress.
*/
protected void internalViewRefreshProgress() {
if(progress.refresh()) {
setCurrentProgress((BigDecimal) progress.getValue());
controlUpdateSelection();
}//if//
}//internalViewRefreshProgress()//
/**
* Updates the control's selection.
*/
protected void controlUpdateSelection() {
BigDecimal progress = getCurrentProgress();
BigDecimal multiplier = getMultiplier();
int controlProgress;
if(progress == null) {
controlProgress = getSwtProgress().getMinimum();
}//if//
else if(multiplier == null) {
controlProgress = progress.intValue();
}//else if//
else {
controlProgress = progress.multiply(multiplier).intValue();
}//else//
getSwtProgress().setSelection(controlProgress);
}//controlUpdateSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == maximum) {
internalViewRefreshMaximum();
}//if//
else if(resourceAssociation == minimum) {
internalViewRefreshMinimum();
}//else if//
else if(resourceAssociation == progress) {
internalViewRefreshProgress();
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnEventFired(com.foundation.view.swt.IEventAssociation, java.lang.Object[])
*/
protected void internalOnEventFired(IEventAssociation eventAssociation, Object[] eventArguments) {
}//internalOnEventFired()//
}//Progress//

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2004,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.widgets.Shell;
import com.common.debug.*;
import com.common.thread.*;
/**
* Maintains request information and handles notification of completion.
*/
class Request implements Runnable {
public static final int REQUEST_NONE = 0;
private IInternalAbstractComponent component = null;
private IRunnable runnable = null;
private Object returnValue = null;
/**
* Request constructor.
*/
Request(IRunnable runnable) {
this.runnable = runnable;
}//Request()//
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
public void run() {
Shell shell = component != null ? component.getShell() : null;
if(shell != null) {
//shellSwtUtilities.setRedraw(, false);
shell.setLayoutDeferred(true);
}//if//
try {
if(runnable != null) {
returnValue = runnable.run();
}//if//
else {
//The control was disposed so there is no point in sending the message.//
returnValue = null;
}//else//
}//try//
catch(Throwable e) {
Debug.log("Failed to complete the processing of a local swt view request.", e);
}//catch//
finally {
if(shell != null) {
//shellSwtUtilities.setRedraw(, true);
shell.setLayoutDeferred(false);
}//if//
}//finally//
}//run()//
/**
* Gets the result of the request.
* @return The request result (only valid if the request was processed synchronously).
*/
public Object getReturnValue() {
return returnValue;
}//getReturnValue()//
}//Request//

View File

@@ -0,0 +1,27 @@
/*
* Copyright (c) 2006,2007 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.foundation.view.IResourceHolderComponent;
import com.foundation.view.resource.AbstractResourceService;
public class ResourceHolder extends com.foundation.view.AbstractResourceHolder {
/**
* ResourceHolder constructor.
* @param component The component that will be notified when the resource value changes.
*/
public ResourceHolder(IResourceHolderComponent component) {
super(component);
}//ResourceHolder()//
/* (non-Javadoc)
* @see com.foundation.view.ResourceHolder#getResourceService()
*/
protected AbstractResourceService getResourceService() {
return getComponent().getResourceService();
}//getResourceService()//
}//ResourceHolder//

View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 2007 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
public class RowLayout extends Layout {
public static final int HORIZONTAL = SWT.HORIZONTAL;
public static final int VERTICAL = SWT.VERTICAL;
public static final int CENTER = SWT.CENTER;
public static final int BEGINNING = SWT.BEGINNING;
public static final int END = SWT.END;
public static final int FILL = SWT.FILL;
public int type = SWT.HORIZONTAL;
public int marginWidth = 0;
public int marginHeight = 0;
public int spacing = 3;
public boolean wrap = true;
public boolean pack = true;
public int alignment = SWT.BEGINNING;
public boolean justify = false;
public int marginLeft = 3;
public int marginTop = 3;
public int marginRight = 3;
public int marginBottom = 3;
/**
* RowLayout constructor.
* @param container The container that is using the layout.
*/
public RowLayout(IAbstractSwtContainer container) {
super(container);
}//RowLayout()//
/**
* RowLayout constructor.
* @param container The container that is using the layout.
*/
public RowLayout(ICellContainer container) {
super(container);
}//RowLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#createLayout(java.lang.Object)
*/
public org.eclipse.swt.widgets.Layout createLayout(Object rowObject) {
com.foundation.view.swt.layout.RowLayout result = new com.foundation.view.swt.layout.RowLayout();
result.type = type;
result.marginHeight = marginHeight;
result.marginWidth = marginWidth;
result.spacing = spacing;
result.wrap = wrap;
result.pack = pack;
result.alignment = alignment;
result.justify = justify;
result.marginLeft = marginLeft;
result.marginTop = marginTop;
result.marginRight = marginRight;
result.marginBottom = marginBottom;
return result;
}//createLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#initialize()
*/
public void initialize() {
}//initialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#refresh()
*/
public void refresh() {
}//refresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#synchronize()
*/
public void synchronize() {
}//synchronize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Layout#release()
*/
public void release() {
}//release()//
/**
* Sets the layout type.
* @param type The layout type.
*/
public void setType(int type) {
this.type = type;
}//setType()//
/**
* Sets the layout margin width.
* @param marginWidth The layout margin width.
*/
public void setMarginWidth(int marginWidth) {
this.marginWidth = marginWidth;
}//setMarginWidth()//
/**
* Sets the layout margin height.
* @param marginHeight The layout margin height.
*/
public void setMarginHeight(int marginHeight) {
this.marginHeight = marginHeight;
}//setMarginHeight()//
/**
* Sets the layout spacing.
* @param spacing The layout spacing.
*/
public void setSpacing(int spacing) {
this.spacing = spacing;
}//setSpacing()//
/**
* Sets the layout wrap.
* @param wrap The layout wrap.
*/
public void setWrap(boolean wrap) {
this.wrap = wrap;
}//setWrap()//
/**
* Sets the layout pack.
* @param pack The layout pack.
*/
public void setPack(boolean pack) {
this.pack = pack;
}//setPack()//
/**
* Sets the layout alignment which identifies how to place the components in the axis opposite the type (direction of flow).
* @param alignment The layout alignment.
*/
public void setAlignment(int alignment) {
this.alignment = alignment;
}//setAlignment()//
/**
* Sets the layout justify.
* @param justify The layout justify.
*/
public void setJustify(boolean justify) {
this.justify = justify;
}//setJustify()//
/**
* Sets the layout margin top.
* @param marginTop The layout margin top.
*/
public void setMarginTop(int marginTop) {
this.marginTop = marginTop;
}//setMarginTop()//
/**
* Sets the layout margin bottom.
* @param marginBottom The layout margin bottom.
*/
public void setMarginBottom(int marginBottom) {
this.marginBottom = marginBottom;
}//setMarginBottom()//
/**
* Sets the layout margin right.
* @param marginRight The layout margin right.
*/
public void setMarginRight(int marginRight) {
this.marginRight = marginRight;
}//setMarginRight()//
/**
* Sets the layout margin left.
* @param marginLeft The layout margin left.
*/
public void setMarginLeft(int marginLeft) {
this.marginLeft = marginLeft;
}//setMarginLeft()//
}//RowLayout//

View File

@@ -0,0 +1,136 @@
/*
* 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.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import com.foundation.view.*;
/*
* A very simple sash which can be moveable, adjusting the component above and below or to the left and right.
*/
public class Sash extends Component implements SelectionListener {
public static final int STYLE_HORIZONTAL = SWT.HORIZONTAL;
public static final int STYLE_VERTICAL = SWT.VERTICAL;
private Component attachment1 = null; //TODO: Are these going to be used again? Currently only the form layout is supported (it uses the attachments to resize).
private Component attachment2 = null;
/** Whether the sash is displayed vertically (in which case the components are to the left and right), or horizontallay (in which case the components are above and below). */
private boolean isVertical = false;
/**
* Sash constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_ARROW
* @see #STYLE_CHECK
*/
public Sash(Container parent, String name, int style) {
super(parent, name, style);
isVertical = ((style & STYLE_VERTICAL) > 0);
}//Sash()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.Sash(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT sash reference.
* @return The sash represented in SWT.
*/
protected org.eclipse.swt.widgets.Sash getSwtSash() {
return (org.eclipse.swt.widgets.Sash) getSwtControl();
}//getSwtSash()//
/**
* Sets the components on either side of the sash.
* @param attachment1 The first of two components.
* @param attachment2 The second of two components.
*/
public void setAttachments(Component attachment1, Component attachment2) {
this.attachment1 = attachment1;
this.attachment2 = attachment2;
}//setAttachments()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
getSwtSash().addSelectionListener(this);
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
if((getSwtSash() != null) && (!getSwtSash().isDisposed())) {
getSwtSash().removeSelectionListener(this);
}//if//
super.internalViewRelease();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnEventFired(com.foundation.view.swt.IEventAssociation, java.lang.Object[])
*/
protected void internalOnEventFired(IEventAssociation eventAssociation, Object[] eventArguments) {
}//internalOnEventFired()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent event) {
if(event.detail != SWT.DRAG) {
Point point0 = getSwtSash().getLocation();
//TODO: Allow other layouts?//
if(!isVertical) {
int difference = event.y - point0.y;
if(getSwtSash().getLayoutData() instanceof com.foundation.view.swt.layout.FormData) {
com.foundation.view.swt.layout.FormData formData = (com.foundation.view.swt.layout.FormData) getSwtSash().getLayoutData();
if(formData.top != null) {
formData.top.offset += difference;
}//if//
if(formData.bottom != null) {
formData.bottom.offset += difference;
}//if//
}//if//
}//if//
else {
int difference = event.x - point0.x;
if(getSwtSash().getLayoutData() instanceof com.foundation.view.swt.layout.FormData) {
com.foundation.view.swt.layout.FormData formData = (com.foundation.view.swt.layout.FormData) getSwtSash().getLayoutData();
if(formData.left != null) {
formData.left.offset += difference;
}//if//
if(formData.right != null) {
formData.right.offset += difference;
}//if//
}//if//
}//else//
//TODO: Should I allow for null layouts?//
//getSwtSash().setBounds(event.x, event.y, event.width, event.height);
//Resize the parent container.//
getSwtSash().getParent().layout();
}//if//
}//widgetSelected()//
}//Sash//

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2005,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
/**
* The sash form lays out the contained components and separates them by sashes.
*/
public class SashForm extends Container {
public static final int STYLE_HORIZONTAL = SWT.HORIZONTAL;
public static final int STYLE_VERTICAL = SWT.VERTICAL;
public static final int STYLE_SMOOTH = SWT.SMOOTH;
/**
* SashForm constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_VERTICAL
* @see #STYLE_HORIZONTAL
* @see #STYLE_SMOOTH
*/
public SashForm(Container parent, String name, int style) {
super(parent, name, style);
}//SashForm()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.custom.SashForm(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT sash form that represents this sash form.
* @return The SWT sash form providing visualization for this sash form.
*/
public org.eclipse.swt.custom.SashForm getSwtSashForm() {
return (org.eclipse.swt.custom.SashForm) getSwtControl();
}//getSwtSashForm()//
/**
* Sets the weights for the contained components.
* @param weights The component's weights.
*/
public void setWeights(int[] weights) {
getSwtSashForm().setWeights(weights);
}//setWeights()//
}//SashForm//

View File

@@ -0,0 +1,46 @@
/*
* 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.view.swt;
import org.eclipse.swt.SWT;
import com.foundation.view.IAbstractContainer;
import com.foundation.view.IViewContext;
public abstract class ScrollableComponent extends Component {
public static final int STYLE_H_SCROLL = SWT.H_SCROLL;
public static final int STYLE_V_SCROLL = SWT.V_SCROLL;
public static final int LAST_LINK_TARGET = Component.LAST_LINK_TARGET + 0;
/**
* ScrollableComponent default constructor.
* <p>Warning: This is only for use by the framework. This should never be called to create a useable instance.</p>
*/
public ScrollableComponent() {
}//ScrollableComponent()//
/**
* ScrollableComponent constructor.
* @param parent The parent container for this container.
* @param name The unique component name.
* @param style The style for the control.
*/
public ScrollableComponent(IAbstractContainer parent, String name, int style) {
super(parent, name, style);
}//ScrollableComponent()//
/**
* ScrollableComponent constructor.
* @param parent The parent container for this container.
* @param name The unique component name.
* @param viewContext The context under which this view component operates. For all but the outer most control this can be null.
* @param style The style for the control.
* @param data The optional data passed to the initializeControl(int, java.lang.Object) method.
*/
public ScrollableComponent(IAbstractContainer parent, String name, IViewContext viewContext, int style, Object data) {
super(parent, name, viewContext, style, data);
}//ScrollableComponent()//
}//ScrollableComponent//

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,417 @@
/*
* Copyright (c) 2006,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import com.common.thread.IRunnable;
import com.foundation.view.IEventAssociation;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
public class Slider extends Component implements SelectionListener {
public static final int STYLE_HORIZONTAL = SWT.HORIZONTAL;
public static final int STYLE_VERTICAL = SWT.VERTICAL;
/** The progress' maximum resource which bounds the progress states. */
private SingleResourceAssociation maximum = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, false, new Integer(0));
/** The progress' minimum resource which bounds the progress states. */
private SingleResourceAssociation minimum = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, false, new Integer(0));
/** The progress' progress resource which defines the current progress state. */
private SingleResourceAssociation selection = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, true, new Integer(0));
/** The progress' progress resource which defines the increment state. */
private SingleResourceAssociation increment = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, false, new Integer(0));
/** The progress' progress resource which defines the page increment state. */
private SingleResourceAssociation pageIncrement = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, false, new Integer(0));
/** The progress' progress resource which defines the thumb state. */
private SingleResourceAssociation thumb = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, false, new Integer(0));
/** Whether the value is automatically synchronized as the user edits the value. Otherwise the field must be manually synchronized. */
private boolean autoSynchronizeSelection = false;
/** The delay used when auto synchronizing the value. A zero value means there will be no delay. The value must be on the range of [0..10,000]. */
private long autoSynchronizeSelectionDelay = 500;
/** The task that auto synchronizes the selection after a short delay. */
protected Task autoSynchronizeSelectionTask = null;
/**
* Slider constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_HORIZONTAL
* @see #STYLE_INDETERMINATE
*/
public Slider(Container parent, String name, int style) {
super(parent, name, style);
}//Slider()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.Slider(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT progress bar that represents this progress.
* @return The SWT progress bar providing visualization for this progress.
*/
public org.eclipse.swt.widgets.Slider getSwtSlider() {
return (org.eclipse.swt.widgets.Slider) getSwtWidget();
}//getSwtSlider()//
/**
* Sets the component maximum selection value.
* @param maximum The maximum value in the selection range.
*/
public void setMaximum(Integer maximum) {
verifyThread();
this.maximum.setDefaultValue(maximum);
}//setMaximum()//
/**
* Sets the component minimum selection value.
* @param minimum The minimum value in the progress range. This must be greater than or equal to zero.
*/
public void setMinimum(Integer minimum) {
verifyThread();
this.minimum.setDefaultValue(minimum);
}//setMinimum()//
/**
* Sets the component selection value.
* @param selection The current selection value. This must be greater than or equal to the minimum and less than or equal to the maximum.
*/
public void setSelection(Integer selection) {
verifyThread();
this.selection.setDefaultValue(selection);
}//setSelection()//
/**
* Sets the slider increment.
* @param increment The increment value for the range.
*/
public void setIncrement(Integer increment) {
verifyThread();
this.increment.setDefaultValue(increment);
}//setIncrement()//
/**
* Sets the slider page increment.
* @param pageIncrement The page increment value for the range.
*/
public void setPageIncrement(Integer pageIncrement) {
verifyThread();
this.pageIncrement.setDefaultValue(pageIncrement);
}//setIncrement()//
/**
* Sets the slider thumb size.
* @param thumb The thumb size.
*/
public void setThumb(Integer thumb) {
verifyThread();
this.thumb.setDefaultValue(thumb);
}//setThumb()//
/**
* Sets the association container used to access the maximum value.
* @param container The maximum value association metadata.
*/
public void setMaximumAssociation(SingleAssociationContainer container) {
verifyThread();
this.maximum.setAssociations(container);
}//setMaximumAssociation()//
/**
* Sets the association container used to access the minimum value.
* @param container The minimum value association metadata.
*/
public void setMinimumAssociation(SingleAssociationContainer container) {
verifyThread();
this.minimum.setAssociations(container);
}//setMinimumAssociation()//
/**
* Sets the association container used to access the selected value.
* @param container The selected value association metadata.
*/
public void setSelectionAssociation(SingleAssociationContainer container) {
verifyThread();
this.selection.setAssociations(container);
}//setSelectionAssociation()//
/**
* Sets the association container used to access the increment size.
* @param container The increment size association metadata.
*/
public void setIncrementAssociation(SingleAssociationContainer container) {
verifyThread();
this.increment.setAssociations(container);
}//setIncrementAssociation()//
/**
* Sets the association container used to access the page increment size.
* @param container The page increment size association metadata.
*/
public void setPageIncrementAssociation(SingleAssociationContainer container) {
verifyThread();
this.pageIncrement.setAssociations(container);
}//setPageIncrementAssociation()//
/**
* Sets the association container used to access the thumb size.
* @param container The thumb size association metadata.
*/
public void setThumbAssociation(SingleAssociationContainer container) {
verifyThread();
this.thumb.setAssociations(container);
}//setThumbAssociation()//
/**
* Gets whether the selection will automatically synchronize.
* @return Whether the selection is automatically synchronized from the view to the model when changed, or whether it must be manually synchronized.
*/
protected boolean getAutoSynchronizeSelection() {
return autoSynchronizeSelection;
}//getAutoSynchronizeSelection()//
/**
* Sets whether the selection will automatically synchronize.
* @param autoSynchronizeSelection Whether the selection is automatically synchronized from the view to the model when changed, or whether it must be manually synchronized.
*/
public void setAutoSynchronizeSelection(boolean autoSynchronizeSelection) {
verifyThread();
if(this.autoSynchronizeSelection != autoSynchronizeSelection) {
this.autoSynchronizeSelection = autoSynchronizeSelection;
}//if//
}//setAutoSynchronizeSelection()//
/**
* Gets the number of milliseconds to wait before automatically synchronizing selection changes. This must be a number between zero and ten thousand where zero synchronizes without delay.
* @return The number of milliseconds of delay when auto synchronizing the selection.
*/
protected long getAutoSynchronizeSelectionDelay() {
return autoSynchronizeSelectionDelay;
}//getAutoSynchronizeSelectionDelay()//
/**
* Sets the number of milliseconds to wait before automatically synchronizing selection changes. This must be a number between zero and ten thousand where zero synchronizes without delay.
* @param autoSynchronizeSelectionDelay The number of milliseconds of delay when auto synchronizing the selection.
*/
public void setAutoSynchronizeSelectionDelay(long autoSynchronizeSelectionDelay) {
verifyThread();
if(autoSynchronizeSelectionDelay < 0) {
autoSynchronizeSelectionDelay = 0;
}//if//
else if(autoSynchronizeSelectionDelay > 10000) {
autoSynchronizeSelectionDelay = 10000;
}//else if//
if(this.autoSynchronizeSelectionDelay != autoSynchronizeSelectionDelay) {
this.autoSynchronizeSelectionDelay = autoSynchronizeSelectionDelay;
}//if//
}//setAutoSynchronizeSelectionDelay()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
getSwtSlider().addSelectionListener(this);
maximum.initialize();
minimum.initialize();
selection.initialize();
increment.initialize();
pageIncrement.initialize();
thumb.initialize();
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
if(getSwtSlider() != null && !getSwtSlider().isDisposed()) {
getSwtSlider().removeSelectionListener(this);
}//if//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
autoSynchronizeSelectionTask = null;
}//if//
}//synchronized//
super.internalViewRelease();
maximum.release();
minimum.release();
selection.release();
increment.release();
pageIncrement.release();
thumb.release();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalViewRefreshMaximum();
internalViewRefreshMinimum();
internalViewRefreshSelection();
internalViewRefreshIncrement();
internalViewRefreshPageIncrement();
internalViewRefreshThumb();
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
super.internalViewSynchronize();
if(!getAutoSynchronizeSelection()) {
selection.setValue(new Integer(getSwtSlider().getSelection()));
}//if//
else {
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
autoSynchronizeSelectionTask.execute();
}//if//
}//synchronized//
}//else if//
}//internalViewSynchronize()//
/**
* Synchronizes the selection(s) with the server.
*/
private void internalSynchronizeSelection() {
if(getAutoSynchronizeSelection()) {
if(autoSynchronizeSelectionDelay > 0) {
//Start a task to send the text to the server after a short delay.//
synchronized(this) {
final Integer selection = new Integer(getSwtSlider().getSelection());
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
}//if//
autoSynchronizeSelectionTask = new Task() {
boolean hasRun = false;
public void execute() {
//Make sure that this task is still valid and is not being superceeded.//
synchronized(Slider.this) {
if((autoSynchronizeSelectionTask == this) && (!hasRun)) {
hasRun = true;
//Cleanup after the task.//
autoSynchronizeSelectionTask = null;
getEventLoop().executeAsync(new IRunnable() {
public Object run() {
Slider.this.selection.setValue(selection);
return null;
}//run()//
});
}//if//
}//synchronized//
}//run()//
};
addTask(autoSynchronizeSelectionTask, autoSynchronizeSelectionDelay);
}//synchronized//
}//if//
else {
selection.setValue(new Integer(getSwtSlider().getSelection()));
}//else//
}//if//
}//internalSynchronizeSelection()//
/**
* Refreshes the progress maximum.
*/
protected void internalViewRefreshMaximum() {
if(maximum.refresh()) {
Integer value = (Integer) maximum.getValue();
getSwtSlider().setMaximum(value.intValue());
}//if//
}//internalViewRefreshMaximum()//
/**
* Refreshes the progress maximum.
*/
protected void internalViewRefreshMinimum() {
if(minimum.refresh()) {
Integer value = (Integer) minimum.getValue();
getSwtSlider().setMinimum(value.intValue());
}//if//
}//internalViewRefreshMinimum()//
/**
* Refreshes the current selection.
*/
protected void internalViewRefreshSelection() {
if(selection.refresh()) {
Integer value = (Integer) selection.getValue();
getSwtSlider().setSelection(value.intValue());
}//if//
}//internalViewRefreshSelection()//
/**
* Refreshes the increment.
*/
protected void internalViewRefreshIncrement() {
if(increment.refresh()) {
Integer value = (Integer) increment.getValue();
getSwtSlider().setIncrement(value.intValue());
}//if//
}//internalViewRefreshIncrement()//
/**
* Refreshes the page increment.
*/
protected void internalViewRefreshPageIncrement() {
if(pageIncrement.refresh()) {
Integer value = (Integer) pageIncrement.getValue();
getSwtSlider().setPageIncrement(value.intValue());
}//if//
}//internalViewRefreshPageIncrement()//
/**
* Refreshes the thumb.
*/
protected void internalViewRefreshThumb() {
if(thumb.refresh()) {
Integer value = (Integer) thumb.getValue();
getSwtSlider().setThumb(value.intValue());
}//if//
}//internalViewRefreshThumb()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == maximum) {
internalViewRefreshMaximum();
}//if//
else if(resourceAssociation == minimum) {
internalViewRefreshMinimum();
}//else if//
else if(resourceAssociation == selection) {
internalViewRefreshSelection();
}//else if//
else if(resourceAssociation == increment) {
internalViewRefreshIncrement();
}//else if//
else if(resourceAssociation == pageIncrement) {
internalViewRefreshPageIncrement();
}//else if//
else if(resourceAssociation == thumb) {
internalViewRefreshThumb();
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnEventFired(com.foundation.view.swt.IEventAssociation, java.lang.Object[])
*/
protected void internalOnEventFired(IEventAssociation eventAssociation, Object[] eventArguments) {
}//internalOnEventFired()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent e) {
//TODO: Is there some way to determine exactly what selection or deselection occured given the event object?//
internalSynchronizeSelection();
}//widgetSelected()//
}//Slider//

View File

@@ -0,0 +1,384 @@
/*
* Copyright (c) 2006,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import com.common.thread.IRunnable;
import com.foundation.view.IEventAssociation;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
public class Spinner extends Component implements SelectionListener {
public static final int STYLE_WRAP = SWT.WRAP;
public static final int STYLE_READ_ONLY = SWT.READ_ONLY;
/** The progress' maximum resource which bounds the progress states. */
private SingleResourceAssociation maximum = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, false, new Integer(0));
/** The progress' minimum resource which bounds the progress states. */
private SingleResourceAssociation minimum = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, false, new Integer(0));
/** The progress' progress resource which defines the current progress state. */
private SingleResourceAssociation selection = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, true, new Integer(0));
/** The progress' progress resource which defines the increment state. */
private SingleResourceAssociation increment = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, false, new Integer(0));
/** The progress' progress resource which defines the page increment state. */
private SingleResourceAssociation pageIncrement = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, false, new Integer(0));
/** Whether the value is automatically synchronized as the user edits the value. Otherwise the field must be manually synchronized. */
private boolean autoSynchronizeSelection = false;
/** The delay used when auto synchronizing the value. A zero value means there will be no delay. The value must be on the range of [0..10,000]. */
private long autoSynchronizeSelectionDelay = 500;
/** The task that auto synchronizes the selection after a short delay. */
protected Task autoSynchronizeSelectionTask = null;
/**
* Spinner constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_HORIZONTAL
* @see #STYLE_INDETERMINATE
*/
public Spinner(Container parent, String name, int style) {
super(parent, name, style);
}//Spinner()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.Spinner(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT progress bar that represents this progress.
* @return The SWT progress bar providing visualization for this progress.
*/
public org.eclipse.swt.widgets.Spinner getSwtSpinner() {
return (org.eclipse.swt.widgets.Spinner) getSwtWidget();
}//getSwtSpinner()//
/**
* Sets the component maximum selection value.
* @param maximum The maximum value in the selection range.
*/
public void setMaximum(Integer maximum) {
verifyThread();
this.maximum.setDefaultValue(maximum);
}//setMaximum()//
/**
* Sets the component minimum selection value.
* @param minimum The minimum value in the progress range. This must be greater than or equal to zero.
*/
public void setMinimum(Integer minimum) {
verifyThread();
this.minimum.setDefaultValue(minimum);
}//setMinimum()//
/**
* Sets the component selection value.
* @param selection The current selection value. This must be greater than or equal to the minimum and less than or equal to the maximum.
*/
public void setSelection(Integer selection) {
verifyThread();
this.selection.setDefaultValue(selection);
}//setSelection()//
/**
* Sets the slider increment.
* @param increment The increment value for the range.
*/
public void setIncrement(Integer increment) {
verifyThread();
this.increment.setDefaultValue(increment);
}//setIncrement()//
/**
* Sets the slider page increment.
* @param pageIncrement The page increment value for the range.
*/
public void setPageIncrement(Integer pageIncrement) {
verifyThread();
this.pageIncrement.setDefaultValue(pageIncrement);
}//setIncrement()//
/**
* Sets the association container used to access the maximum value.
* @param container The maximum value association metadata.
*/
public void setMaximumAssociation(SingleAssociationContainer container) {
verifyThread();
this.maximum.setAssociations(container);
}//setMaximumAssociation()//
/**
* Sets the association container used to access the minimum value.
* @param container The minimum value association metadata.
*/
public void setMinimumAssociation(SingleAssociationContainer container) {
verifyThread();
this.minimum.setAssociations(container);
}//setMinimumAssociation()//
/**
* Sets the association container used to access the selected value.
* @param container The selected value association metadata.
*/
public void setSelectionAssociation(SingleAssociationContainer container) {
verifyThread();
this.selection.setAssociations(container);
}//setSelectionAssociation()//
/**
* Sets the association container used to access the increment size.
* @param container The increment size association metadata.
*/
public void setIncrementAssociation(SingleAssociationContainer container) {
verifyThread();
this.increment.setAssociations(container);
}//setIncrementAssociation()//
/**
* Sets the association container used to access the page increment size.
* @param container The page increment size association metadata.
*/
public void setPageIncrementAssociation(SingleAssociationContainer container) {
verifyThread();
this.pageIncrement.setAssociations(container);
}//setPageIncrementAssociation()//
/**
* Gets whether the selection will automatically synchronize.
* @return Whether the selection is automatically synchronized from the view to the model when changed, or whether it must be manually synchronized.
*/
protected boolean getAutoSynchronizeSelection() {
return autoSynchronizeSelection;
}//getAutoSynchronizeSelection()//
/**
* Sets whether the selection will automatically synchronize.
* @param autoSynchronizeSelection Whether the selection is automatically synchronized from the view to the model when changed, or whether it must be manually synchronized.
*/
public void setAutoSynchronizeSelection(boolean autoSynchronizeSelection) {
verifyThread();
if(this.autoSynchronizeSelection != autoSynchronizeSelection) {
this.autoSynchronizeSelection = autoSynchronizeSelection;
}//if//
}//setAutoSynchronizeSelection()//
/**
* Gets the number of milliseconds to wait before automatically synchronizing selection changes. This must be a number between zero and ten thousand where zero synchronizes without delay.
* @return The number of milliseconds of delay when auto synchronizing the selection.
*/
protected long getAutoSynchronizeSelectionDelay() {
return autoSynchronizeSelectionDelay;
}//getAutoSynchronizeSelectionDelay()//
/**
* Sets the number of milliseconds to wait before automatically synchronizing selection changes. This must be a number between zero and ten thousand where zero synchronizes without delay.
* @param autoSynchronizeSelectionDelay The number of milliseconds of delay when auto synchronizing the selection.
*/
public void setAutoSynchronizeSelectionDelay(long autoSynchronizeSelectionDelay) {
verifyThread();
if(autoSynchronizeSelectionDelay < 0) {
autoSynchronizeSelectionDelay = 0;
}//if//
else if(autoSynchronizeSelectionDelay > 10000) {
autoSynchronizeSelectionDelay = 10000;
}//else if//
if(this.autoSynchronizeSelectionDelay != autoSynchronizeSelectionDelay) {
this.autoSynchronizeSelectionDelay = autoSynchronizeSelectionDelay;
}//if//
}//setAutoSynchronizeSelectionDelay()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
getSwtSpinner().addSelectionListener(this);
maximum.initialize();
minimum.initialize();
selection.initialize();
increment.initialize();
pageIncrement.initialize();
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
if(getSwtSpinner() != null && !getSwtSpinner().isDisposed()) {
getSwtSpinner().removeSelectionListener(this);
}//if//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
autoSynchronizeSelectionTask = null;
}//if//
}//synchronized//
super.internalViewRelease();
maximum.release();
minimum.release();
selection.release();
increment.release();
pageIncrement.release();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalViewRefreshMaximum();
internalViewRefreshMinimum();
internalViewRefreshSelection();
internalViewRefreshIncrement();
internalViewRefreshPageIncrement();
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
super.internalViewSynchronize();
if(!getAutoSynchronizeSelection()) {
selection.setValue(new Integer(getSwtSpinner().getSelection()));
}//if//
else {
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
autoSynchronizeSelectionTask.execute();
}//if//
}//synchronized//
}//else if//
}//internalViewSynchronize()//
/**
* Synchronizes the selection(s) with the server.
*/
private void internalSynchronizeSelection() {
if(getAutoSynchronizeSelection()) {
if(autoSynchronizeSelectionDelay > 0) {
//Start a task to send the text to the server after a short delay.//
synchronized(this) {
final Integer selection = new Integer(getSwtSpinner().getSelection());
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
}//if//
autoSynchronizeSelectionTask = new Task() {
boolean hasRun = false;
public void execute() {
//Make sure that this task is still valid and is not being superceeded.//
synchronized(Spinner.this) {
if((autoSynchronizeSelectionTask == this) && (!hasRun)) {
hasRun = true;
//Cleanup after the task.//
autoSynchronizeSelectionTask = null;
getEventLoop().executeAsync(new IRunnable() {
public Object run() {
Spinner.this.selection.setValue(selection);
return null;
}//run()//
});
}//if//
}//synchronized//
}//run()//
};
addTask(autoSynchronizeSelectionTask, autoSynchronizeSelectionDelay);
}//synchronized//
}//if//
else {
selection.setValue(new Integer(getSwtSpinner().getSelection()));
}//else//
}//if//
}//internalSynchronizeSelection()//
/**
* Refreshes the progress maximum.
*/
protected void internalViewRefreshMaximum() {
if(maximum.refresh()) {
Integer value = (Integer) maximum.getValue();
getSwtSpinner().setMaximum(value.intValue());
}//if//
}//internalViewRefreshMaximum()//
/**
* Refreshes the progress maximum.
*/
protected void internalViewRefreshMinimum() {
if(minimum.refresh()) {
Integer value = (Integer) minimum.getValue();
getSwtSpinner().setMinimum(value.intValue());
}//if//
}//internalViewRefreshMinimum()//
/**
* Refreshes the current selection.
*/
protected void internalViewRefreshSelection() {
if(selection.refresh()) {
Integer value = (Integer) selection.getValue();
getSwtSpinner().setSelection(value.intValue());
}//if//
}//internalViewRefreshSelection()//
/**
* Refreshes the increment.
*/
protected void internalViewRefreshIncrement() {
if(increment.refresh()) {
Integer value = (Integer) increment.getValue();
getSwtSpinner().setIncrement(value.intValue());
}//if//
}//internalViewRefreshIncrement()//
/**
* Refreshes the page increment.
*/
protected void internalViewRefreshPageIncrement() {
if(pageIncrement.refresh()) {
Integer value = (Integer) pageIncrement.getValue();
getSwtSpinner().setPageIncrement(value.intValue());
}//if//
}//internalViewRefreshPageIncrement()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == maximum) {
internalViewRefreshMaximum();
}//if//
else if(resourceAssociation == minimum) {
internalViewRefreshMinimum();
}//else if//
else if(resourceAssociation == selection) {
internalViewRefreshSelection();
}//else if//
else if(resourceAssociation == increment) {
internalViewRefreshIncrement();
}//else if//
else if(resourceAssociation == pageIncrement) {
internalViewRefreshPageIncrement();
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnEventFired(com.foundation.view.swt.IEventAssociation, java.lang.Object[])
*/
protected void internalOnEventFired(IEventAssociation eventAssociation, Object[] eventArguments) {
}//internalOnEventFired()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent e) {
//TODO: Is there some way to determine exactly what selection or deselection occured given the event object?//
internalSynchronizeSelection();
}//widgetSelected()//
}//Spinner//

View File

@@ -0,0 +1,314 @@
/*
* Copyright (c) 2005,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.widgets.Layout;
import com.common.util.ICollection;
import com.common.util.IIterator;
import com.common.util.IList;
import com.common.util.LiteList;
import com.foundation.controller.ViewController;
import com.foundation.util.IInlineCollectionObservable;
import com.foundation.util.IInlineCollectionObserver;
import com.foundation.util.IInlineIndexedCollectionObservable;
import com.foundation.util.IInlineIndexedCollectionObserver;
import com.foundation.view.IEventAssociation;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
import com.foundation.view.swt.util.SwtUtilities;
/*
* Displays components in a stack such that only one component is visible at a time.
*/
public class StackViewer extends Container implements IInlineIndexedCollectionObserver, IInlineCollectionObserver {
/** The association that results in a collection of view controllers. */
private SingleResourceAssociation views = null;
/** The association that tracks which view is being displayed. */
private SingleResourceAssociation visibleView = null;
/** The previous collection of view controllers. */
private IList viewControllers = new LiteList(1, 15);
/** Temporarily suspends processing of events fired by registered collections. */
private boolean suspendCollectionEvents = false;
/**
* StackViewer constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_NO_BACKGROUND
* @see #STYLE_NO_FOCUS
* @see #STYLE_NO_MERGE_PAINTS
* @see #STYLE_NO_REDRAW_RESIZE
* @see #STYLE_NO_RADIO_GROUP
* @see #STYLE_H_SCROLL
* @see #STYLE_V_SCROLL
* @see #STYLE_BORDER
* @see #STYLE_LEFT_TO_RIGHT
* @see #STYLE_RIGHT_TO_LEFT
*/
public StackViewer(Container parent, String name, int style) {
super(parent, name, style);
this.views = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_OBJECT, false, null);
this.visibleView = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_OBJECT, false, null);
}//StackViewer()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.Composite(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
getSwtComposite().setLayout(new StackLayout());
}//initializeControl()//
/**
* Gets the stack layout used with the wizard.
* @return The wizard's stack layout.
*/
protected StackLayout getLayout() {
return (StackLayout) getSwtComposite().getLayout();
}//getLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container#setLayout(org.eclipse.swt.widgets.Layout)
*/
public void setLayout(Layout layout) {
//Does nothing. Layouts are not allowed here.//
}//setLayout()//
/**
* Gets the SWT composite that represents this panel.
* @return The SWT composite providing visualization for this panel.
*/
public org.eclipse.swt.widgets.Composite getSwtComposite() {
return (org.eclipse.swt.widgets.Composite) getSwtControl();
}//getSwtComposite()//
/**
* Sets the association container used to access the views in the stack.
* @param container The views association metadata.
*/
public void setViewsAssociation(SingleAssociationContainer container) {
verifyThread();
this.views.setAssociations(container);
}//setViewsAssociation()//
/**
* Sets the association container used to access the visible view.
* @param container The visible view association metadata.
*/
public void setVisibleViewAssociation(SingleAssociationContainer container) {
verifyThread();
this.visibleView.setAssociations(container);
}//setVisibleViewAssociation()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnEventFired(com.foundation.view.swt.IEventAssociation, java.lang.Object[])
*/
protected void internalOnEventFired(IEventAssociation eventAssociation, Object[] eventArguments) {
}//internalOnEventFired()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
views.initialize();
visibleView.initialize();
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
super.internalViewRelease();
views.release();
visibleView.release();
for(int index = 0; index < viewControllers.getSize(); index++) {
((ViewController) viewControllers.get(index)).close();
}//for//
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalRefreshViews();
internalRefreshVisibleView();
}//internalViewRefresh()//
/**
* Refreshes the currently visible component.
*/
protected void internalRefreshViews() {
Object oldValue = views.getValue();
if(views.refresh()) {
stopRendering();
try {
Object newValue = views.getValue();
//Remove listeners from the old value.//
if(oldValue instanceof IInlineIndexedCollectionObservable) {
((IInlineIndexedCollectionObservable) oldValue).removeCollectionObserver(this);
}//if//
else if(oldValue instanceof IInlineCollectionObservable) {
((IInlineCollectionObservable) oldValue).removeCollectionObserver(this);
}//else if//
//Close the old view controllers.//
for(int index = 0; index < viewControllers.getSize(); index++) {
((ViewController) viewControllers.get(index)).close();
}//for//
viewControllers.removeAll();
//If the new value is a collection or object then add and remove pages as required, and add listeners as required.//
if(newValue instanceof ICollection) {
IIterator iterator = ((ICollection) newValue).iterator();
//Add tabs for all the view controllers.//
while(iterator.hasNext()) {
Object next = iterator.next();
//Ignore non-view controller objects.//
if(next instanceof ViewController) {
ViewController controller = (ViewController) next;
controller.openPartial(this, getViewContext());
}//if//
else {
throw new RuntimeException("Expecting a view controller.");
}//else//
}//while//
//Add the controllers to the list of view controllers.//
viewControllers.addAll((ICollection) newValue);
//Prevent collection events from notifying us of existing items in the collection.//
suspendCollectionEvents = true;
//Add a listener to the collection so we get change events.//
if(newValue instanceof IInlineIndexedCollectionObservable) {
((IInlineIndexedCollectionObservable) newValue).addCollectionObserver(this);
}//if//
else if(newValue instanceof IInlineCollectionObservable) {
((IInlineCollectionObservable) newValue).addCollectionObserver(this);
}//else if//
//Re-enable the collection events.//
suspendCollectionEvents = false;
}//if//
else if(newValue instanceof ViewController) {
ViewController controller = (ViewController) newValue;
controller.openPartial(this, getViewContext());
//Add the one controller to the list of view controllers.//
viewControllers.add(controller);
}//else if//
}//try//
finally {
startRendering();
}//finally//
}//if//
}//internalRefreshViews()//
/**
* Refreshes the currently visible component.
*/
protected void internalRefreshVisibleView() {
if(visibleView.refresh()) {
Object view = (Object) visibleView.getValue();
int index = viewControllers.getIndexOf(view);
if(index >= 0) {
((StackLayout) getSwtComposite().getLayout()).topControl = getSwtComposite().getChildren()[index];
getSwtComposite().layout(true, false);
}//if//
}//if//
}//internalRefreshVisibleView()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
//Since the page can only be set manually, this method should do nothing.//
super.internalViewSynchronize();
}//internalViewSynchronize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#internalOnValueChanged(com.foundation.view.SingleResourceAssociation, int)
*/
protected void internalOnValueChanged(SingleResourceAssociation association, int flags) {
if(association == visibleView) {
internalRefreshVisibleView();
}//if//
else if(association == views) {
internalRefreshViews();
}//else if//
else {
super.internalOnValueChanged(association, flags);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#startChanges(int)
*/
public void startChanges(int changeCount) {
startRendering();
}//startChanges()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#stopChanges()
*/
public void stopChanges() {
stopRendering();
}//stopChanges()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineCollectionObserver#valueAdded(java.lang.Object)
*/
public void valueAdded(Object value) {
if((!suspendCollectionEvents) && (value instanceof ViewController)) {
viewControllers.add(value);
((ViewController) value).openPartial(this, getViewContext());
}//if//
}//valueAdded()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#valueAdded(java.lang.Object, int)
*/
public void valueAdded(Object value, int index) {
valueAdded(value);
}//valueAdded()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineCollectionObserver#valueRemoved(java.lang.Object)
*/
public void valueRemoved(Object value) {
if((!suspendCollectionEvents) && (viewControllers.remove(value))) {
((ViewController) value).close();
}//if//
}//valueRemoved()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#valueRemoved(java.lang.Object, int)
*/
public void valueRemoved(Object value, int index) {
valueRemoved(value);
}//valueRemoved()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#removingAll()
*/
public void removingAll() {
if(!suspendCollectionEvents) {
IIterator iterator = viewControllers.iterator();
startChanges(viewControllers.getSize());
try {
while(iterator.hasNext()) {
valueRemoved(iterator.next());
}//while//
}//try//
finally {
stopChanges();
}//finally//
}//if//
}//removingAll()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#valuesSorted(int[])
*/
public void valuesSorted(int[] mapping) {
//Does nothing.//
}//valuesSorted()//
}//StackViewer//

View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 2006 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.custom.ST;
import com.common.comparison.Comparator;
import com.foundation.metadata.Attribute;
import com.foundation.model.Model;
/*
* An external structure for specifying bullet metadata for a section of text in the styled text control.
* <p>If the text represented by this info instance contains a mix of style settings then only the common styles will be set in this info object. The attributes for which there is a mix of data will be assigned a null value.</p>
*/
public class StyleBulletInfo extends Model {
public static final Integer TYPE_DOT = new Integer(ST.BULLET_DOT);
public static final Integer TYPE_NUMBER = new Integer(ST.BULLET_NUMBER);
public static final Integer TYPE_LETTER_LOWER = new Integer(ST.BULLET_LETTER_LOWER);
public static final Integer TYPE_LETTER_UPPER = new Integer(ST.BULLET_LETTER_UPPER);
/** The type of bullet as an ST constant. */
public static final Attribute TYPE = registerAttribute(StyleBulletInfo.class, "type");
/** The text used only if one of the type constants is ST.TEXT. */
public static final Attribute TEXT = registerAttribute(StyleBulletInfo.class, "text");
public static final Attribute STYLE = registerAttribute(StyleBulletInfo.class, "style");
/**
* StyleBulletInfo constructor.
*/
public StyleBulletInfo() {
super();
setStyle(new StyleTextInfo());
setText("");
setType(new Integer(0));
}//StyleBulletInfo()//
/**
* Gets the bullet style type.
* <p>This can be one of the type constants defined by this class.</p>
* @return The type of bullet.
* @see #TYPE_DOT
* @see #TYPE_NUMBER
* @see #TYPE_LETTER_LOWER
* @see #TYPE_LETTER_UPPER
*/
public Integer getType() {
return (Integer) getAttributeValue(TYPE);
}//getType()//
/**
* Sets the bullet style type.
* <p>This can be one of the type constants defined by this class.</p>
* @param type The type of bullet.
* @see #TYPE_DOT
* @see #TYPE_NUMBER
* @see #TYPE_LETTER_LOWER
* @see #TYPE_LETTER_UPPER
*/
public void setType(Integer type) {
setAttributeValue(TYPE, type);
}//setType()//
/**
* Gets the bullet style text.
* <p>If text has greater than zero length then it will appear after the bullet type's graphic.</p>
* @return The text of bullet.
*/
public String getText() {
return (String) getAttributeValue(TEXT);
}//getText()//
/**
* Sets the bullet style text.
* <p>If text has greater than zero length then it will appear after the bullet type's graphic.</p>
* @param text The text of bullet.
*/
public void setText(String text) {
setAttributeValue(TEXT, text);
}//setText()//
/**
* Gets the bullet style.
* @return The style data for the bullet.
*/
public StyleTextInfo getStyle() {
return (StyleTextInfo) getAttributeValue(STYLE);
}//getStyle()//
/**
* Sets the bullet style
* @param style The style data for the bullet.
*/
private void setStyle(StyleTextInfo style) {
setAttributeValue(STYLE, style);
}//setStyle()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
return "Bullet Style";
}//toString()//
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object object) {
return (object instanceof StyleBulletInfo) &&
Comparator.equals(getStyle(), ((StyleBulletInfo) object).getStyle()) &&
Comparator.equals(getType(), ((StyleBulletInfo) object).getType()) &&
Comparator.equals(getText(), ((StyleBulletInfo) object).getText());
}//equals()//
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return (getStyle() == null ? 0 : getStyle().hashCode()) ^ (getText() == null ? 0 : getText().hashCode()) ^ (getType() == null ? 0 : getType().hashCode());
}//hashCode()//
}//StyleBulletInfo//

View File

@@ -0,0 +1,156 @@
/*
* Copyright (c) 2006 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.comparison.Comparator;
import com.foundation.metadata.Attribute;
import com.foundation.metadata.Event;
import com.foundation.model.Model;
/*
* An external structure for specifying line metadata for a section of text in the styled text control.
* A null bullet reference indicates that there is no bulleting for the lines. If some lines have bulleting then the attribute will reference a bullet info instance.
* <p>If the text represented by this info instance contains a mix of style settings then only the common styles will be set in this info object. The attributes for which there is a mix of data will be assigned a null value.</p>
*/
public class StyleLineInfo extends Model {
/** The updated event is fired by the StyledTextManager after the styles have been updated due to a change in the selection. */
public static final Event EVENT_UPDATED = registerEvent(StyleLineInfo.class, "eventUpdated");
public static final Attribute ALIGNMENT = registerAttribute(StyleLineInfo.class, "alignment");
public static final Attribute INDENT = registerAttribute(StyleLineInfo.class, "indent");
public static final Attribute JUSTIFY = registerAttribute(StyleLineInfo.class, "justify");
public static final Attribute STYLE = registerAttribute(StyleLineInfo.class, "style");
public static final Attribute IS_BULLETED = registerAttribute(StyleLineInfo.class, "isBulleted");
public static final Attribute BULLET = registerAttribute(StyleLineInfo.class, "bullet");
/**
* StyleLineInfo constructor.
*/
public StyleLineInfo() {
super();
setStyle(new StyleTextInfo());
}//StyleLineInfo()//
/**
* Fires the updated event notifying listeners that the styled text manager has finished updating the style data due to a selection or cursor position change.
* This event does not provide any information about what if anything has been changed. The change flags for the object are not currently utilized to provide this information either.
*/
protected void fireUpdated() {
getEventSupport().fireEvent(EVENT_UPDATED);
}//fireUpdated()//
/**
* Gets the alignment for the lines the style is associated with.
* @return The alignment for all the text in the associated lines.
*/
public Integer getAlignment() {
return (Integer) getAttributeValue(ALIGNMENT);
}//getAlignment()//
/**
* Sets the alignment for the lines the style is associated with.
* @param alignment The alignment for all the text in the associated lines.
*/
public void setAlignment(Integer alignment) {
setAttributeValue(ALIGNMENT, alignment);
}//setAlignment()//
/**
* Gets the indent for the lines the style is associated with.
* @return The indent for all the text in the associated lines.
*/
public Integer getIndent() {
return (Integer) getAttributeValue(INDENT);
}//getIndent()//
/**
* Sets the indent for the lines the style is associated with.
* @param indent The indent for all the text in the associated lines.
*/
public void setIndent(Integer indent) {
setAttributeValue(INDENT, indent);
}//setIndent()//
/**
* Gets whether the lines the style is associated with are justified.
* @return Whether all the text in the associated lines are justified.
*/
public Boolean getJustify() {
return (Boolean) getAttributeValue(JUSTIFY);
}//getJustify()//
/**
* Sets whether the lines the style is associated with are justified.
* @param justify Whether all the text in the associated lines are justified.
*/
public void setJustify(Boolean justify) {
setAttributeValue(JUSTIFY, justify);
}//setJustify()//
/**
* Gets the text style metadata for the represented text.
* @return The style data for the represented text.
*/
public StyleTextInfo getStyle() {
return (StyleTextInfo) getAttributeValue(STYLE);
}//getStyle()//
/**
* Sets the text style metadata for the represented text.
* @param style The style data for the represented text.
*/
private void setStyle(StyleTextInfo style) {
setAttributeValue(STYLE, style);
}//setStyle()//
/**
* Gets whether the lines are bulleted or not.
* <p>This will be null if some lines are bulleted. If this is null then the bullet reference will be ignored when applying styles to the text.</p>
* @return Whether all lines are bulleted or not.
*/
public Boolean getIsBulleted() {
return (Boolean) getAttributeValue(IS_BULLETED);
}//getIsBulleted()//
/**
* Sets whether the lines are bulleted or not.
* <p>This will be null if some lines are bulleted. If this is null then the bullet reference will be ignored when applying styles to the text.</p>
* @param isBulleted Whether all lines are bulleted or not.
*/
public void setIsBulleted(Boolean isBulleted) {
setAttributeValue(IS_BULLETED, isBulleted);
}//setIsBulleted()//
/**
* Gets the bullet metadata for the represented lines.
* @return The bullet data which will be non-null if any of the represented lines have bullets.
*/
public StyleBulletInfo getBullet() {
return (StyleBulletInfo) getAttributeValue(BULLET);
}//getBullet()//
/**
* Sets the bullet metadata for the represented lines.
* @param bullet The bullet data which will be non-null if any of the represented lines have bullets.
*/
public void setBullet(StyleBulletInfo bullet) {
setAttributeValue(BULLET, bullet);
}//setBullet()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
return "Line Style";
}//toString()//
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object object) {
return (object instanceof StyleLineInfo) &&
Comparator.equals(getAlignment(), ((StyleLineInfo) object).getAlignment()) &&
Comparator.equals(getIndent(), ((StyleLineInfo) object).getIndent()) &&
Comparator.equals(getJustify(), ((StyleLineInfo) object).getJustify()) &&
Comparator.equals(getBullet(), ((StyleLineInfo) object).getBullet()) &&
Comparator.equals(getStyle(), ((StyleLineInfo) object).getStyle());
}//equals()//
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return (getAlignment() == null ? 0 : getAlignment().hashCode()) ^
(getIndent() == null ? 0 : getIndent().hashCode()) ^
(getJustify() == null ? 0 : getJustify().hashCode()) ^
(getBullet() == null ? 0 : getBullet().hashCode()) ^
(getStyle() == null ? 0 : getStyle().hashCode());
}//hashCode()//
}//StyleLineInfo//

View File

@@ -0,0 +1,247 @@
/*
* Copyright (c) 2006 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.comparison.Comparator;
import com.foundation.metadata.Attribute;
import com.foundation.model.Model;
import com.foundation.view.JefColor;
/*
* An external structure for specifying text style metadata.
* <p>If the text represented by this info instance contains a mix of style settings then only the common styles will be set in this info object. The attributes for which there is a mix of data will be assigned a null value.</p>
*/
public class StyleTextInfo extends Model {
public static final Attribute FONT_NAME = registerAttribute(StyleTextInfo.class, "fontName");
public static final Attribute FONT_HEIGHT = registerAttribute(StyleTextInfo.class, "fontHeight");
public static final Attribute FOREGROUND_COLOR = registerAttribute(StyleTextInfo.class, "foregroundColor");
public static final Attribute BACKGROUND_COLOR = registerAttribute(StyleTextInfo.class, "backgroundColor");
public static final Attribute BOLD = registerAttribute(StyleTextInfo.class, "bold");
public static final Attribute ITALIC = registerAttribute(StyleTextInfo.class, "italic");
public static final Attribute UNDERLINE = registerAttribute(StyleTextInfo.class, "underline");
public static final Attribute STRIKEOUT = registerAttribute(StyleTextInfo.class, "strikeout");
public static final Attribute RISE = registerAttribute(StyleTextInfo.class, "rise");
public static final Attribute GLYPH_ASCENT = registerAttribute(StyleTextInfo.class, "glyphAscent");
public static final Attribute GLYPH_DESCENT = registerAttribute(StyleTextInfo.class, "glyphDescent");
public static final Attribute GLYPH_WIDTH = registerAttribute(StyleTextInfo.class, "glyphWidth");
/**
* StyleTextInfo constructor.
*/
public StyleTextInfo() {
super();
}//StyleTextInfo()//
/**
* Gets the font name for the related text.
* @return The text's font name.
*/
public String getFontName() {
return (String) getAttributeValue(FONT_NAME);
}//getFontName()//
/**
* Sets the font name for the related text.
* @param fontName The text's font name.
*/
public void setFontName(String fontName) {
setAttributeValue(FONT_NAME, fontName);
}//setFontName()//
/**
* Gets whether the font is bolded
* @return The text's style flags.
*/
public Boolean getBold() {
return (Boolean) getAttributeValue(BOLD);
}//getBold()//
/**
* Sets whether the font is bolded.
* @param bold The text's style flags.
*/
public void setBold(Boolean bold) {
setAttributeValue(BOLD, bold);
}//setBold()//
/**
* Gets whether the font is italicized.
* @return The text's style flags.
*/
public Boolean getItalic() {
return (Boolean) getAttributeValue(ITALIC);
}//getItalic()//
/**
* Sets whether the font is italicized.
* @param italic The text's style flags.
*/
public void setItalic(Boolean italic) {
setAttributeValue(ITALIC, italic);
}//setItalic()//
/**
* Gets the height of the related text's font.
* @return The text's font height.
*/
public Integer getFontHeight() {
return (Integer) getAttributeValue(FONT_HEIGHT);
}//getFontHeight()//
/**
* Sets the height of the related text's font.
* @param fontHeight The text's font height.
*/
public void setFontHeight(Integer fontHeight) {
setAttributeValue(FONT_HEIGHT, fontHeight);
}//setFontHeight()//
/**
* Gets the background color for the related text.
* @return The text's background color.
*/
public JefColor getBackgroundColor() {
return (JefColor) getAttributeValue(BACKGROUND_COLOR);
}//getBackgroundColor()//
/**
* Sets the background color for the related text.
* @param backgroundColor The text's background color.
*/
public void setBackgroundColor(JefColor backgroundColor) {
setAttributeValue(BACKGROUND_COLOR, backgroundColor);
}//setBackgroundColor()//
/**
* Gets the foreground color for the related text.
* @return The text's foreground color.
*/
public JefColor getForegroundColor() {
return (JefColor) getAttributeValue(FOREGROUND_COLOR);
}//getForegroundColor()//
/**
* Sets the foreground color for the related text.
* @param foregroundColor The text's foreground color.
*/
public void setForegroundColor(JefColor foregroundColor) {
setAttributeValue(FOREGROUND_COLOR, foregroundColor);
}//setForegroundColor()//
/**
* Gets whether the text is underlined.
* @return Whether the text is underlined.
*/
public Boolean getUnderline() {
return (Boolean) getAttributeValue(UNDERLINE);
}//getUnderline()//
/**
* Sets whether the text is underlined.
* @param underline Whether the text is underlined.
*/
public void setUnderline(Boolean underline) {
setAttributeValue(UNDERLINE, underline);
}//setUnderline()//
/**
* Gets whether the text is striked out.
* @return Whether the text is striked out.
*/
public Boolean getStrikeout() {
return (Boolean) getAttributeValue(STRIKEOUT);
}//getStrikeout()//
/**
* Sets whether the text is striked out.
* @param strikeout Whether the text is striked out.
*/
public void setStrikeout(Boolean strikeout) {
setAttributeValue(STRIKEOUT, strikeout);
}//setStrikeout()//
/**
* Gets the rise for the text.
* @return The text rise.
*/
public Integer getRise() {
return (Integer) getAttributeValue(RISE);
}//getRise()//
/**
* Sets the rise for the text.
* @param rise The text rise.
*/
public void setRise(Integer rise) {
setAttributeValue(RISE, rise);
}//setRise()//
/**
* Gets the glyph ascent for the text.
* @return The glyph ascent for the text. The default is zero.
*/
public Integer getGlyphAscent() {
return (Integer) getAttributeValue(GLYPH_ASCENT);
}//getGlyphAscent()//
/**
* Sets the glyph ascent for the text.
* @param glyphAscent The glyph ascent for the text. The default is zero.
*/
public void setGlyphAscent(Integer glyphAscent) {
setAttributeValue(GLYPH_ASCENT, glyphAscent);
}//setGlyphAscent()//
/**
* Gets the glyph descent for the text.
* @return The glyph descent for the text. The default is zero.
*/
public Integer getGlyphDescent() {
return (Integer) getAttributeValue(GLYPH_DESCENT);
}//getGlyphDescent()//
/**
* Sets the glyph descent for the text.
* @param glyphDescent The glyph descent for the text. The default is zero.
*/
public void setGlyphDescent(Integer glyphDescent) {
setAttributeValue(GLYPH_DESCENT, glyphDescent);
}//setGlyphDescent()//
/**
* Gets the glyph width for the text.
* @return The glyph width for the text. The default is zero.
*/
public Integer getGlyphWidth() {
return (Integer) getAttributeValue(GLYPH_WIDTH);
}//getGlyphWidth()//
/**
* Sets the glyph width for the text.
* @param glyphWidth The glyph width for the text. The default is zero.
*/
public void setGlyphWidth(Integer glyphWidth) {
setAttributeValue(GLYPH_WIDTH, glyphWidth);
}//setGlyphWidth()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
return "Text Style";
}//toString()//
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object object) {
return (object instanceof StyleTextInfo) &&
Comparator.equals(getFontName(), ((StyleTextInfo) object).getFontName()) &&
Comparator.equals(getFontHeight(), ((StyleTextInfo) object).getFontHeight()) &&
Comparator.equals(getBold(), ((StyleTextInfo) object).getBold()) &&
Comparator.equals(getItalic(), ((StyleTextInfo) object).getItalic()) &&
Comparator.equals(getBackgroundColor(), ((StyleTextInfo) object).getBackgroundColor()) &&
Comparator.equals(getForegroundColor(), ((StyleTextInfo) object).getForegroundColor()) &&
Comparator.equals(getGlyphAscent(), ((StyleTextInfo) object).getGlyphAscent()) &&
Comparator.equals(getGlyphDescent(), ((StyleTextInfo) object).getGlyphDescent()) &&
Comparator.equals(getGlyphWidth(), ((StyleTextInfo) object).getGlyphWidth()) &&
Comparator.equals(getRise(), ((StyleTextInfo) object).getRise()) &&
Comparator.equals(getUnderline(), ((StyleTextInfo) object).getUnderline()) &&
Comparator.equals(getStrikeout(), ((StyleTextInfo) object).getStrikeout());
}//equals()//
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return (getFontName() == null ? 0 : getFontName().hashCode()) ^
(getFontHeight() == null ? 0 : getFontHeight().hashCode()) ^
(getBold() == null ? 0 : getBold().hashCode()) ^
(getItalic() == null ? 0 : getItalic().hashCode()) ^
(getBackgroundColor() == null ? 0 : getBackgroundColor().hashCode()) ^
(getForegroundColor() == null ? 0 : getForegroundColor().hashCode()) ^
(getGlyphAscent() == null ? 0 : getGlyphAscent().hashCode()) ^
(getGlyphDescent() == null ? 0 : getGlyphDescent().hashCode()) ^
(getGlyphWidth() == null ? 0 : getGlyphWidth().hashCode()) ^
(getRise() == null ? 0 : getRise().hashCode()) ^
(getUnderline() == null ? 0 : getUnderline().hashCode()) ^
(getStrikeout() == null ? 0 : getStrikeout().hashCode());
}//hashCode()//
}//StyleTextInfo//

View File

@@ -0,0 +1,499 @@
/*
* Copyright (c) 2006,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.LineStyleListener;
import org.eclipse.swt.custom.StyledTextContent;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Point;
import com.foundation.event.EventSupport;
import com.foundation.event.IEventEmitter;
import com.foundation.event.IEventHandler;
import com.foundation.view.JefColor;
import com.foundation.view.LinkData;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
public class StyledText extends Container implements SelectionListener, KeyListener, MouseListener {
public static final int STYLE_FULL_SELECTION = SWT.FULL_SELECTION;
public static final int STYLE_MULTI_LINE = SWT.MULTI;
public static final int STYLE_SINGLE_LINE = SWT.SINGLE;
public static final int STYLE_READ_ONLY = SWT.READ_ONLY;
public static final int STYLE_WRAP = SWT.WRAP;
public static final int LINK_TARGET_BOLD_TEXT = Container.LAST_LINK_TARGET + 1;
public static final int LINK_TARGET_ITALIC_TEXT = Container.LAST_LINK_TARGET + 2;
public static final int LINK_TARGET_UNDERLINE_TEXT = Container.LAST_LINK_TARGET + 3;
public static final int LINK_TARGET_STRIKEOUT_TEXT = Container.LAST_LINK_TARGET + 4;
public static final int LINK_TARGET_TEXT_FONT_NAME = Container.LAST_LINK_TARGET + 5;
public static final int LINK_TARGET_TEXT_FONT_SIZE = Container.LAST_LINK_TARGET + 6;
public static final int LINK_TARGET_TEXT_FOREGROUND_COLOR = Container.LAST_LINK_TARGET + 7;
public static final int LINK_TARGET_TEXT_BACKGROUND_COLOR = Container.LAST_LINK_TARGET + 8;
public static final int LINK_TARGET_TEXT_RISE = Container.LAST_LINK_TARGET + 9;
public static final int LINK_TARGET_TEXT_GLYPH_ASCENT = Container.LAST_LINK_TARGET + 10;
public static final int LINK_TARGET_TEXT_GLYPH_DESCENT = Container.LAST_LINK_TARGET + 11;
public static final int LINK_TARGET_TEXT_GLYPH_WIDTH = Container.LAST_LINK_TARGET + 12;
public static final int LINK_TARGET_LINE_ALIGNMENT = Container.LAST_LINK_TARGET + 13;
public static final int LINK_TARGET_LINE_INDENT = Container.LAST_LINK_TARGET + 14;
public static final int LINK_TARGET_LINE_JUSTIFY = Container.LAST_LINK_TARGET + 15;
public static final int LAST_LINK_TARGET = Container.LAST_LINK_TARGET + 15;
/** The text displayed in the styled text editor. */
private SingleResourceAssociation text = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_TEXT, true, null);
/** Whether the text is non-editable. */
private final boolean isReadOnly;
/** The document manager. */
private IStyledTextManager manager = new StyledTextManager();
/** The event support used to listen to the StyledLineInfo update event. */
private EventSupport eventSupport = new EventSupport(null);
/** The character offset of the first character in the range selected, or if length is zero then it is the cursor location. */
private int currentRangeOffset = -1;
/** The number of selected characters in the current range. */
private int currentRangeLength = 0;
/** Whether the linkage updates should be ignored. This should only be true if the control is in the process of updating the links and doesn't want feedback. */
private boolean suspendLinkInvocations = false;
/** The linkage for the text selection. */
private Linkage boldTextLinkage = new Linkage();
/** The linkage for the text selection. */
private Linkage italicTextLinkage = new Linkage();
/** The linkage for the text selection. */
private Linkage underlineTextLinkage = new Linkage();
/** The linkage for the text selection. */
private Linkage strikeoutTextLinkage = new Linkage();
/** The linkage for the text selection. */
private Linkage textFontNameLinkage = new Linkage();
/** The linkage for the text selection. */
private Linkage textFontSizeLinkage = new Linkage();
/** The linkage for the text selection. */
private Linkage textBackgroundColorLinkage = new Linkage();
/** The linkage for the text selection. */
private Linkage textForegroundColorLinkage = new Linkage();
public interface IStyledTextManager extends StyledTextContent, LineStyleListener {
//TODO: Add methods to allow the selection or the cursor to change styles.
//TODO: Add methods to allow cut and paste of text using the clipboard.
/**
* Gets the style data for the current range.
* @return The style data for the range set.
* @see #setCurrentRange(int, int)
*/
public StyleLineInfo getCurrentRangeStyle();
/**
* Changes the range of characters the range style model represents.
* @param offset The offset in the text to begin the range.
* @param length The number of characters in the range, or zero if the styles at the cursor are desired.
*/
public void setCurrentRange(int offset, int length);
}//IStyledTextManager//
/**
* StyledText constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #FULL_SELECTION, MULTI, READ_ONLY, SINGLE, WRAP
*/
public StyledText(Container parent, String name, int style) {
super(parent, name, style);
isReadOnly = (style & STYLE_READ_ONLY) > 0;
}//StyledText()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.custom.StyledText(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT styled text that represents this styled text.
* @return The SWT styled text providing visualization for this styled text.
*/
public org.eclipse.swt.custom.StyledText getSwtStyledText() {
return (org.eclipse.swt.custom.StyledText) getSwtControl();
}//getSwtStyledText()//
/**
* Sets the text.
* @param text The text that will appear in the component.
*/
public void setText(String text) {
verifyThread();
this.text.setDefaultValue(text);
}//setText()//
/**
* Sets the association container used to access the text.
* @param container The text association metadata.
*/
public void setTextAssociation(SingleAssociationContainer container) {
verifyThread();
this.text.setAssociations(container);
}//setTextAssociation()//
/**
* Adds a bold text link associated with the selected text.
* @param link The local linkage.
*/
public void addBoldTextLink(LinkData link) {
boldTextLinkage.add(link);
}//addBoldTextLink()//
/**
* Adds an italic text link associated with the selected text.
* @param link The local linkage.
*/
public void addItalicTextLink(LinkData link) {
italicTextLinkage.add(link);
}//addItalicTextLink()//
/**
* Adds an underline text link associated with the selected text.
* @param link The local linkage.
*/
public void addUnderlineTextLink(LinkData link) {
underlineTextLinkage.add(link);
}//addUnderlineTextLink()//
/**
* Adds a strikeout text link associated with the selected text.
* @param link The local linkage.
*/
public void addStrikeoutTextLink(LinkData link) {
strikeoutTextLinkage.add(link);
}//addStrikeoutTextLink()//
/**
* Adds a font name link associated with the selected text.
* @param link The local linkage.
*/
public void addTextFontNameLink(LinkData link) {
textFontNameLinkage.add(link);
}//addTextFontNameLink()//
/**
* Adds a font size link associated with the selected text.
* @param link The local linkage.
*/
public void addTextFontSizeLink(LinkData link) {
textFontSizeLinkage.add(link);
}//addTextFontSizeLink()//
/**
* Adds a foreground color link associated with the selected text.
* @param link The local linkage.
*/
public void addTextForegroundColorLink(LinkData link) {
textForegroundColorLinkage.add(link);
}//addTextForegroundColorLink()//
/**
* Adds a background color link associated with the selected text.
* @param link The local linkage.
*/
public void addTextBackgroundColorLink(LinkData link) {
textBackgroundColorLinkage.add(link);
}//addTextBackgroundColorLink()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
getSwtStyledText().addSelectionListener(this);
getSwtStyledText().addKeyListener(this);
getSwtStyledText().addMouseListener(this);
getSwtStyledText().addLineStyleListener(manager);
getSwtStyledText().setContent(manager);
text.initialize();
eventSupport.register(manager.getCurrentRangeStyle(), StyleLineInfo.EVENT_UPDATED, new IEventHandler() {
public void evaluate(int eventNumber, Object[] eventParameters, int flags) {
//Never called.//
}//evaluate()//
public void evaluate(IEventEmitter eventEmitter, int eventNumber, Object[] eventParameters, int flags) {
updateLinks((StyleLineInfo) eventEmitter);
}//evaluate()//
}, true);
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
if(!getSwtStyledText().isDisposed()) {
getSwtStyledText().removeSelectionListener(this);
getSwtStyledText().removeKeyListener(this);
getSwtStyledText().removeMouseListener(this);
getSwtStyledText().removeLineStyleListener(manager);
}//if//
super.internalViewRelease();
text.release();
eventSupport.unregisterAll();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalViewRefreshText();
}//internalViewRefresh()//
/**
* Refreshes the styled text.
*/
protected void internalViewRefreshText() {
if(text.refresh()) {
convertText((String) text.getValue());
resize();
}//if//
}//internalViewRefreshText()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnLinkInvoked(int, java.lang.Object)
*/
protected void internalOnLinkInvoked(int linkTarget, Object data) {
if(!suspendLinkInvocations) {
switch(linkTarget) {
case LINK_TARGET_BOLD_TEXT: {
StyleTextInfo info = manager.getCurrentRangeStyle().getStyle();
Boolean value = data instanceof Boolean ? (Boolean) data : info.getBold() == null || !info.getBold().booleanValue() ? Boolean.TRUE : Boolean.FALSE;
info.setBold(value);
break;
}//case//
case LINK_TARGET_ITALIC_TEXT: {
StyleTextInfo info = manager.getCurrentRangeStyle().getStyle();
Boolean value = data instanceof Boolean ? (Boolean) data : info.getItalic() == null || !info.getItalic().booleanValue() ? Boolean.TRUE : Boolean.FALSE;
info.setItalic(value);
break;
}//case//
case LINK_TARGET_UNDERLINE_TEXT: {
StyleTextInfo info = manager.getCurrentRangeStyle().getStyle();
Boolean value = data instanceof Boolean ? (Boolean) data : info.getBold() == null || !info.getBold().booleanValue() ? Boolean.TRUE : Boolean.FALSE;
info.setUnderline(value);
break;
}//case//
case LINK_TARGET_STRIKEOUT_TEXT: {
StyleTextInfo info = manager.getCurrentRangeStyle().getStyle();
Boolean value = data instanceof Boolean ? (Boolean) data : info.getItalic() == null || !info.getItalic().booleanValue() ? Boolean.TRUE : Boolean.FALSE;
info.setStrikeout(value);
break;
}//case//
case LINK_TARGET_TEXT_FONT_NAME: {
StyleTextInfo info = manager.getCurrentRangeStyle().getStyle();
String value = data instanceof String ? (String) data : info.getFontName() != null ? info.getFontName() : null;
info.setFontName(value);
break;
}//case//
case LINK_TARGET_TEXT_FONT_SIZE: {
StyleTextInfo info = manager.getCurrentRangeStyle().getStyle();
Integer value = data instanceof Integer ? (Integer) data : info.getFontHeight() != null ? info.getFontHeight() : null;
info.setFontHeight(value);
break;
}//case//
case LINK_TARGET_TEXT_FOREGROUND_COLOR: {
StyleTextInfo info = manager.getCurrentRangeStyle().getStyle();
JefColor value = data instanceof JefColor ? (JefColor) data : info.getForegroundColor() != null ? info.getForegroundColor() : null;
info.setForegroundColor(value);
break;
}//case//
case LINK_TARGET_TEXT_BACKGROUND_COLOR: {
StyleTextInfo info = manager.getCurrentRangeStyle().getStyle();
JefColor value = data instanceof JefColor ? (JefColor) data : info.getBackgroundColor() != null ? info.getBackgroundColor() : null;
info.setBackgroundColor(value);
break;
}//case//
}//switch//
//Force the selection to be restored in the swt styled text control.//
getSwtStyledText().setSelection(currentRangeOffset, currentRangeOffset + currentRangeLength);
}//if//
}//internalOnLinkInvoked()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == text) {
internalViewRefreshText();
}//if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/**
* Updates the linkages related to the selection or cursor style info.
* @param line The line info for the selected text's stylings.
*/
private void updateLinks(StyleLineInfo line) {
suspendLinkInvocations = true;
boldTextLinkage.invoke(line.getStyle().getBold());
italicTextLinkage.invoke(line.getStyle().getItalic());
underlineTextLinkage.invoke(line.getStyle().getUnderline());
strikeoutTextLinkage.invoke(line.getStyle().getStrikeout());
textFontNameLinkage.invoke(line.getStyle().getFontName());
textFontSizeLinkage.invoke(line.getStyle().getFontHeight());
textForegroundColorLinkage.invoke(line.getStyle().getForegroundColor());
textBackgroundColorLinkage.invoke(line.getStyle().getBackgroundColor());
suspendLinkInvocations = false;
}//updateLinks()//
/**
* Converts the text from the external formatting to the styled text control formatting.
* @param text The text to be converted.
*/
protected void convertText(String text) {
//TODO: Convert.
getSwtStyledText().setText(text);
}//convertText()//
/**
* Sets the currently selected range for the styled text control.
* <p>This is used to restore the selected range after applying styling changes to the range.</p>
* @param offset The character offset of the first character in the range selected, or if length is zero then it is the cursor location.
* @param length The number of selected characters.
*/
public void setCurrentRange(int offset, int length) {
if((currentRangeOffset != offset) || (currentRangeLength != length)) {
currentRangeOffset = offset;
currentRangeLength = length;
manager.setCurrentRange(offset, length);
}//if//
}//setCurrentRange()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent event) {
widgetSelected(event);
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent event) {
//Point selection = getSwtStyledText().getSelectionRange();
//Give the manager the current range for the selection or the cursor position.//
//manager.setCurrentRange(selection.x, selection.y);
}//widgetSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
*/
public void keyPressed(KeyEvent eevent) {
}//keyPressed()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
*/
public void keyReleased(KeyEvent event) {
if(getSwtStyledText().getSelectionCount() > 0) {
Point selection = getSwtStyledText().getSelectionRange();
setCurrentRange(selection.x, selection.y);
}//if//
else {
setCurrentRange(getSwtStyledText().getCaretOffset(), 0);
}//else//
}//keyReleased()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
*/
public void mouseDoubleClick(MouseEvent event) {
if(getSwtStyledText().getSelectionCount() > 0) {
Point selection = getSwtStyledText().getSelectionRange();
setCurrentRange(selection.x, selection.y);
}//if//
else {
setCurrentRange(getSwtStyledText().getCaretOffset(), 0);
}//else//
}//mouseDoubleClick()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
*/
public void mouseDown(MouseEvent event) {
}//mouseDown()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
*/
public void mouseUp(MouseEvent event) {
if(getSwtStyledText().getSelectionCount() > 0) {
Point selection = getSwtStyledText().getSelectionRange();
setCurrentRange(selection.x, selection.y);
}//if//
else {
setCurrentRange(getSwtStyledText().getCaretOffset(), 0);
}//else//
}//mouseUp()//
}//StyledText//
/*
/*
* Converts the text from an XHTML Basic formatting (a subset of XHTML Basic is supported) to the styled text control formatting.
* @param text The text to be converted.
*
protected void convertTextFromXHtmlBasic(String text) {
StringBuffer rawText = new StringBuffer(text);
try {
IDocument xmlDocument = new DocumentBuilder().readDocument(text);
IIterator iterator = xmlDocument.getElements().iterator();
while(iterator.hasNext()) {
IElement next = (IElement) iterator.next();
if(next.isNode()) {
if(((INode) next).getName().equalsIgnoreCase("html")) {
iterator = ((INode) next).getElements().iterator();
}//if//
else if(((INode) next).getName().equalsIgnoreCase("body")) {
convertTextFromXHtmlBasic((INode) next, rawText);
}//else if//
}//if//
}//while//
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}//convertTextFromHtml()//
/*
* An internal method for converting text to XHtml Basic.
* @param node
* @param buffer
*
private void convertTextFromXHtmlBasic(INode node, StringBuffer buffer) {
for(int index = 0; index < node.getElements().getSize(); index++) {
IElement next = (IElement) node.getElements().get(index);
if(next.isText()) {
int startIndex = buffer.length();
int endIndex;
buffer.append(((IText) next).getText());
endIndex = buffer.length();
}//if//
else if(next.isNode()) {
String nodeName = ((INode) next).getName();
if(nodeName.equals("b")) {
}//if//
}//else if//
}//for//
}//convertTextFromXHtmlBasic()//
/*
* Converts the text from the styled text control to XHTML Basic formatting.
* @return The converted text.
*
protected String convertXHtmlBasicFromText() {
StringBuffer output = new StringBuffer(1000);
try {
IDocument xmlDocument = new DocumentBuilder().createDocument();
xmlDocument.setDocType(new DocType("HTML", "PUBLIC", "-//W3C//DTD XHTML Basic 1.0 Strict//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"));
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
return output.toString();
}//convertXHtmlBasicFromText()//
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,372 @@
/*
* Copyright (c) 2007,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import com.common.comparison.Comparator;
import com.common.util.LiteHashMap;
import com.common.util.StringSupport;
import com.foundation.view.*;
import com.foundation.view.swt.util.SwtUtilities;
public class SwtResourceManager {
private static final boolean DEBUG = false;
private static final SwtResourceManager singleton = new SwtResourceManager();
private LiteHashMap imageMap = new LiteHashMap(100, Comparator.getIdentityComparator(), Comparator.getIdentityComparator());
private LiteHashMap colorMap = new LiteHashMap(100, Comparator.getIdentityComparator(), Comparator.getIdentityComparator());
private LiteHashMap fontMap = new LiteHashMap(100, Comparator.getIdentityComparator(), Comparator.getIdentityComparator());
private static class ImageData {
private JefImage jefImage;
private Image image;
private int counter = 1;
public ImageData(Display display, JefImage jefImage) {
this.jefImage = jefImage;
this.image = SwtUtilities.getImage(display, jefImage);
}//ImageData()//
}//ImageData//
private static class ColorData {
private JefColor jefColor;
private Color color;
private int counter = 1;
public ColorData(Display display, JefColor jefColor) {
this.jefColor = jefColor;
this.color = SwtUtilities.getColor(display, jefColor);
}//ColorData()//
}//ColorData//
private static class FontData {
private JefFont[] jefFont;
private Font font;
private int counter = 1;
public FontData(Display display, JefFont[] jefFont) {
this.jefFont = jefFont;
this.font = SwtUtilities.getFont(display, jefFont);
}//FontData()//
}//FontData//
/**
* Gets the one and only instance of the SwtResourceManager class.
* @return The single instance of this class.
*/
public static SwtResourceManager getSingleton() {
return singleton;
}//getSingleton()//
/**
* SwtResourceManager constructor.
*/
public SwtResourceManager() {
super();
}//SwtResourceManager()//
/**
* Creates or reuses an image given the image data.
* <p>Warning: A single call must be made to destroyImage(..) for each call to this method.</p>
* @param image The data from which the image will be derived.
* @return The swt image.
*/
public Image createImage(Display display, JefImage image) {
ImageData result = null;
if(image != null) {
result = (ImageData) imageMap.get(image);
if(result == null) {
result = new ImageData(display, image);
//Index the ImageData by both the JefImage and the Image.//
imageMap.put(image, result);
imageMap.put(result.image, result);
if(DEBUG) {
System.out.println("Adding " + StringSupport.toHexString(result.jefImage.hashCode()));
}//if//
}//if//
else {
result.counter++;
}//else//
}//if//
return result != null ? result.image : null;
}//createImage()//
/**
* Creates or reuses images given the image data.
* <p>Warning: A single call must be made to destroyImages(..) for each call to this method.</p>
* @param images The data from which the images will be derived.
* @return The swt images.
*/
public Image[] createImages(Display display, JefImage[] images) {
Image[] result = null;
if(images != null) {
result = new Image[images.length];
for(int index = 0; index < images.length; index++) {
JefImage image = images[index];
ImageData data = (ImageData) imageMap.get(image);
if(data == null) {
data = new ImageData(display, image);
//Index the ImageData by both the JefImage and the Image.//
imageMap.put(image, data);
imageMap.put(data.image, data);
if(DEBUG) {
System.out.println("Adding " + StringSupport.toHexString(data.jefImage.hashCode()));
}//if//
}//if//
else {
data.counter++;
}//else//
if(data != null) {
result[index] = data.image;
}//if//
}//for//
}//if//
return result;
}//createImage()//
/**
* Destroys an image resource, or decrements the useage count.
* @param image The image to destroy.
*/
public void destroyImage(Image image) {
if(image != null) {
ImageData imageData = (ImageData) imageMap.get(image);
if(imageData != null) {
if(--imageData.counter == 0) {
imageMap.remove(imageData.image);
imageMap.remove(imageData.jefImage);
if(!imageData.image.isDisposed()) {
imageData.image.dispose();
if(DEBUG) {
System.out.println("Disposing " + StringSupport.toHexString(imageData.jefImage.hashCode()));
}//if//
}//if//
}//if//
}//if//
}//if//
}//destroyImage()//
/**
* Destroys an image resource, or decrements the useage count.
* @param image The image to destroy.
*/
public void destroyImages(Image[] images) {
if(images != null) {
for(int index = 0; index < images.length; index++) {
Image image = images[index];
ImageData imageData = (ImageData) imageMap.get(image);
if(imageData != null) {
if(--imageData.counter == 0) {
imageMap.remove(imageData.image);
imageMap.remove(imageData.jefImage);
if(!imageData.image.isDisposed()) {
imageData.image.dispose();
if(DEBUG) {
System.out.println("Disposing " + StringSupport.toHexString(imageData.jefImage.hashCode()));
}//if//
}//if//
}//if//
}//if//
}//for//
}//if//
}//destroyImages()//
/**
* Destroys an image resource, or decrements the useage count.
* @param image The image to destroy.
*/
public void destroyImage(JefImage image) {
if(image != null) {
ImageData imageData = (ImageData) imageMap.get(image);
if(imageData != null) {
if(--imageData.counter == 0) {
imageMap.remove(imageData.image);
imageMap.remove(imageData.jefImage);
if(!imageData.image.isDisposed()) {
imageData.image.dispose();
if(DEBUG) {
System.out.println("Disposing " + StringSupport.toHexString(imageData.jefImage.hashCode()));
}//if//
}//if//
}//if//
}//if//
}//if//
}//destroyImage()//
/**
* Destroys an image resource, or decrements the useage count.
* @param image The image to destroy.
*/
public void destroyImages(JefImage[] images) {
if(images != null) {
for(int index = 0; index < images.length; index++) {
JefImage image = images[index];
ImageData imageData = (ImageData) imageMap.get(image);
if(imageData != null) {
if(--imageData.counter == 0) {
imageMap.remove(imageData.image);
imageMap.remove(imageData.jefImage);
if(!imageData.image.isDisposed()) {
imageData.image.dispose();
if(DEBUG) {
System.out.println("Disposing " + StringSupport.toHexString(imageData.jefImage.hashCode()));
}//if//
}//if//
}//if//
}//if//
}//for//
}//if//
}//destroyImage()//
/**
* Creates or reuses an color given the color data.
* <p>Warning: A single call must be made to destroyColor(..) for each call to this method.</p>
* @param colorData The data from which the color will be derived.
* @return The swt color resource.
*/
public Color createColor(Display display, JefColor color) {
ColorData result = null;
if(color != null) {
result = (ColorData) colorMap.get(color);
if(result == null) {
result = new ColorData(display, color);
//Index the ColorData by both the JefColor and the Color.//
colorMap.put(color, result);
colorMap.put(result.color, result);
}//if//
else {
result.counter++;
}//else//
}//if//
return result != null ? result.color : null;
}//createColor()//
/**
* Destroys an color resource, or decrements the useage count.
* @param color The color to destroy.
*/
public void destroyColor(Color color) {
if(color != null) {
ColorData colorData = (ColorData) colorMap.get(color);
if(colorData != null) {
if(--colorData.counter == 0) {
colorMap.remove(colorData.color);
colorMap.remove(colorData.jefColor);
if(!colorData.jefColor.isColorConstant() && !colorData.color.isDisposed()) {
colorData.color.dispose();
}//if//
}//if//
}//if//
}//if//
}//destroyColor()//
/**
* Destroys an color resource, or decrements the useage count.
* @param color The color to destroy.
*/
public void destroyColor(JefColor color) {
if(color != null) {
ColorData colorData = (ColorData) colorMap.get(color);
if(colorData != null) {
if(--colorData.counter == 0) {
colorMap.remove(colorData.color);
colorMap.remove(colorData.jefColor);
if(!colorData.jefColor.isColorConstant() && !colorData.color.isDisposed()) {
colorData.color.dispose();
}//if//
}//if//
}//if//
}//if//
}//destroyColor()//
/**
* Creates or reuses an font given the font data.
* <p>Warning: A single call must be made to destroyFont(..) for each call to this method.</p>
* @param fontData The data from which the font will be derived.
* @return The swt font resource.
*/
public Font createFont(Display display, JefFont[] font) {
FontData result = null;
if(font != null) {
result = (FontData) fontMap.get(font);
if(result == null) {
result = new FontData(display, font);
//Index the FontData by both the JefFont and the Font.//
fontMap.put(font, result);
fontMap.put(result.font, result);
}//if//
else {
result.counter++;
}//else//
}//if//
return result != null ? result.font : null;
}//createFont()//
/**
* Destroys an font resource, or decrements the useage count.
* @param font The font to destroy.
*/
public void destroyFont(Font font) {
if(font != null) {
FontData fontData = (FontData) fontMap.get(font);
if(fontData != null) {
if(--fontData.counter == 0) {
fontMap.remove(fontData.font);
fontMap.remove(fontData.jefFont);
if(!fontData.font.isDisposed()) {
fontData.font.dispose();
}//if//
}//if//
}//if//
}//if//
}//destroyFont()//
/**
* Destroys an font resource, or decrements the useage count.
* @param font The font to destroy.
*/
public void destroyFont(JefFont[] font) {
if(font != null) {
FontData fontData = (FontData) fontMap.get(font);
if(fontData != null) {
if(--fontData.counter == 0) {
fontMap.remove(fontData.font);
fontMap.remove(fontData.jefFont);
if(!fontData.font.isDisposed()) {
fontData.font.dispose();
}//if//
}//if//
}//if//
}//if//
}//destroyFont()//
}//SwtResourceManager//

View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 2005,2006 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import com.common.comparison.Comparator;
import com.common.util.LiteHashMap;
import com.foundation.view.DisplayMetadata;
import com.foundation.view.IViewContext;
import com.foundation.view.IViewRequestHandler;
import com.foundation.view.ViewSystemMetadata;
/**
* This class provides access to the non-view specific view system functionality.
*/
public class SwtViewContext implements IViewContext {
/** The one and only SWT view context object. */
private static final SwtViewContext singleton = new SwtViewContext();
/** An application data map that allows the application to store key value pairs associated with the view context. */
private LiteHashMap applicationDataMap = null;
/** The application specific context data. */
private Object applicationData = null;
/**
* SwtViewContext constructor.
*/
private SwtViewContext() {
super();
}//SwtViewContext()//
/**
* Gets the one and only instance of the swt view context.
* @return The view context which provides access to the non-view specific view system functionality.
*/
public static SwtViewContext getSingleton() {
return singleton;
}//getSingleton()//
/**
* Gets the display for the swt view context.
* @return The swt view display.
*/
public Display getDisplay() {
return EventLoop.getSingleton().getDisplay();
}//getDisplay()//
/* (non-Javadoc)
* @see com.foundation.view.IViewContext#getViewSystemMetadata()
*/
public ViewSystemMetadata getViewSystemMetadata() {
org.eclipse.swt.widgets.Monitor[] monitors = getDisplay().getMonitors();
DisplayMetadata[] displayMetadata = new DisplayMetadata[monitors.length];
ViewSystemMetadata viewSystemMetadata = new ViewSystemMetadata(displayMetadata);
//Collect information about each monitor.//
for(int monitorIndex = 0; monitorIndex < monitors.length; monitorIndex++) {
Rectangle bounds = monitors[monitorIndex].getBounds();
Rectangle clientArea = monitors[monitorIndex].getClientArea();
displayMetadata[monitorIndex] = new DisplayMetadata(new int[] {bounds.x, bounds.y, bounds.width, bounds.height}, new int[] {clientArea.x, clientArea.y, clientArea.width, clientArea.height});
}//for//
return viewSystemMetadata;
}//getViewSystemMetadata()//
/* (non-Javadoc)
* @see com.foundation.view.IViewContext#getRequestHandler()
*/
public IViewRequestHandler getRequestHandler() {
return EventLoop.getSingleton();
}//getRequestHandler()//
/* (non-Javadoc)
* @see com.foundation.view.IViewContext#getApplicationData()
*/
public Object getApplicationData() {
return applicationData;
}//getApplicationData()//
/* (non-Javadoc)
* @see com.foundation.view.IViewContext#setApplicationData(java.lang.Object)
*/
public void setApplicationData(Object applicationData) {
this.applicationData = applicationData;
}//setApplicationData()//
/* (non-Javadoc)
* @see com.foundation.view.IViewContext#getApplicationData(java.lang.Object)
*/
public Object getApplicationData(Object key) {
return applicationDataMap == null ? null : applicationDataMap.get(key);
}//getApplicationData()//
/* (non-Javadoc)
* @see com.foundation.view.IViewContext#setApplicationData(java.lang.Object, java.lang.Object)
*/
public void setApplicationData(Object key, Object applicationData) {
if(applicationDataMap == null) {
applicationDataMap = new LiteHashMap(10, Comparator.getLogicalComparator(), Comparator.getLogicalComparator());
}//if//
applicationDataMap.put(key, applicationData);
}//setApplicationData()//
/**
* Shuts down the swt event loop, freeing the thread and allowing the application to close gracefully.
*/
public void shutdown() {
new Thread(new Runnable() {
public void run() {
EventLoop.getSingleton().stop();
}//run()//
}).start();
}//shutdown()//
}//SwtViewContext//

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2005,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.widgets.Composite;
import com.foundation.controller.AbstractViewController;
import com.foundation.view.IViewContext;
public class SwtWrapperContainer extends Container {
/** The view context used to interact with the view system. */
private IViewContext viewContext = null;
/**
* SwtWrapperContainer constructor.
* @param composite The swt composite that this container wrappers.
*/
public SwtWrapperContainer(Composite composite, IViewContext viewContext, AbstractViewController controller) {
super(null, "SWT Composite Wrapper", 0);
this.viewContext = viewContext;
setSwtWidget(composite);
setController(controller);
}//SwtWrapperContainer()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
}//initializeControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalGetViewContext()
*/
protected IViewContext internalGetViewContext() {
return viewContext;
}//internalGetViewContext()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitializeAll()
*/
public void internalViewInitializeAll() {
super.internalViewInitializeAll();
getSwtComposite().setTabList(getSwtComposite().getChildren());
}//internalViewInitializeAll()//
}//SwtWrapperContainer//

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 2005,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import com.common.thread.*;
import org.eclipse.swt.widgets.Display;
/*
* Wrappers an swt event loop but doesn't actually start an event processing thread.
*/
public class SwtWrapperRequestHandler implements ISwtViewRequestHandler, ISingleThreadedContext {
/** The display being supported. */
private Display display = null;
/**
* SwtWrapperRequestHandler constructor.
* @param display The display that is supported.
*/
protected SwtWrapperRequestHandler(Display display) {
this.display = display;
//Mark the swt thread as being in a single threaded context since it is the only thread allowed access to the models, views, and view components displayed by it.//
display.syncExec(new Runnable() {
public void run() {
ThreadService.setIsInSingleThreadedContext(SwtWrapperRequestHandler.this);
}//run()//
});
display.disposeExec(new Runnable() {
public void run() {
ThreadService.setIsInSingleThreadedContext(null);
}//run()//
});
}//SwtWrapperRequestHandler()//
/* (non-Javadoc)
* @see com.foundation.view.swt.ISwtViewRequestHandler#getDisplay()
*/
public Display getDisplay() {
return display;
}//getDisplay()//
/**
* Processes a request through the event thread. This is required to access any SWT method due to the design of SWT.
* @param request The object that will be run when the request is processed.
* @param synchronous Whether the thread should block until the request has been processed (should be true if a result is desired).
*/
public void processRequest(Runnable request, boolean synchronous) {
if(synchronous) {
getDisplay().syncExec(request);
}//if//
else {
getDisplay().asyncExec(request);
}//else//
}//processRequest()//
/* (non-Javadoc)
* @see com.foundation.event.IRequestHandler#isRunning()
*/
public boolean isRunning() {
return true;
}//isRunning()//
/* (non-Javadoc)
* @see com.foundation.event.IRequestHandler#isRequestThread()
*/
public boolean isRequestThread() {
return Thread.currentThread() == getDisplay().getThread();
}//isRequestThread()//
/* (non-Javadoc)
* @see com.foundation.event.IRequestHandler#execute(com.common.thread.IRunnable, boolean)
*/
public Object execute(IRunnable runnable, boolean synchronous) {
Object result = null;
if(isRunning()) {
//Make sure we don't have the event thread creating requests since it would deadlock the system.//
if(!synchronous || !isRequestThread()) {
Request request = new Request(runnable);
processRequest(request, synchronous);
if(synchronous) {
result = request.getReturnValue();
}//if//
}//if//
else {
//The calling thread is the event thread, so there is no need to pass the request through the event thread!.//
result = runnable.run();
}//else//
}//if//
return result;
}//execute()//
/* (non-Javadoc)
* @see com.foundation.event.IRequestHandler#execute(com.common.thread.IRunnable)
*/
public Object execute(IRunnable runnable) {
return execute(runnable, true);
}//execute()//
/* (non-Javadoc)
* @see com.foundation.event.IRequestHandler#executeAsync(com.common.thread.IRunnable)
*/
public void executeAsync(IRunnable runnable) {
execute(runnable, false);
}//executeAsync()//
}//EventLoopRunnable//

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2005,2006 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import com.common.comparison.Comparator;
import com.common.util.LiteHashMap;
import com.foundation.view.DisplayMetadata;
import com.foundation.view.IViewContext;
import com.foundation.view.IViewRequestHandler;
import com.foundation.view.ViewSystemMetadata;
/*
* This class provides access to the non-view specific view system functionality.
*/
public class SwtWrapperViewContext implements IViewContext {
/** The one and only SWT view context object. */
private SwtWrapperRequestHandler requestHandler = null;
/** An application data map that allows the application to store key value pairs associated with the view context. */
private LiteHashMap applicationDataMap = null;
/** The application specific context data. */
private Object applicationData = null;
/**
* SwtWrapperViewContext constructor.
* @param display The display that is supported.
*/
public SwtWrapperViewContext(Display display) {
super();
requestHandler = new SwtWrapperRequestHandler(display);
}//SwtWrapperViewContext()//
/* (non-Javadoc)
* @see com.foundation.view.IViewContext#getViewSystemMetadata()
*/
public ViewSystemMetadata getViewSystemMetadata() {
org.eclipse.swt.widgets.Monitor[] monitors = ((SwtWrapperRequestHandler) getRequestHandler()).getDisplay().getMonitors();
DisplayMetadata[] displayMetadata = new DisplayMetadata[monitors.length];
ViewSystemMetadata viewSystemMetadata = new ViewSystemMetadata(displayMetadata);
//Collect information about each monitor.//
for(int monitorIndex = 0; monitorIndex < monitors.length; monitorIndex++) {
Rectangle bounds = monitors[monitorIndex].getBounds();
Rectangle clientArea = monitors[monitorIndex].getClientArea();
displayMetadata[monitorIndex] = new DisplayMetadata(new int[] {bounds.x, bounds.y, bounds.width, bounds.height}, new int[] {clientArea.x, clientArea.y, clientArea.width, clientArea.height});
}//for//
return viewSystemMetadata;
}//getViewSystemMetadata()//
/* (non-Javadoc)
* @see com.foundation.view.IViewContext#getRequestHandler()
*/
public IViewRequestHandler getRequestHandler() {
return requestHandler;
}//getRequestHandler()//
/* (non-Javadoc)
* @see com.foundation.view.IViewContext#getApplicationData()
*/
public Object getApplicationData() {
return applicationData;
}//getApplicationData()//
/* (non-Javadoc)
* @see com.foundation.view.IViewContext#setApplicationData(java.lang.Object)
*/
public void setApplicationData(Object applicationData) {
this.applicationData = applicationData;
}//setApplicationData()//
/* (non-Javadoc)
* @see com.foundation.view.IViewContext#getApplicationData(java.lang.Object)
*/
public Object getApplicationData(Object key) {
return applicationDataMap == null ? null : applicationDataMap.get(key);
}//getApplicationData()//
/* (non-Javadoc)
* @see com.foundation.view.IViewContext#setApplicationData(java.lang.Object, java.lang.Object)
*/
public void setApplicationData(Object key, Object applicationData) {
if(applicationDataMap == null) {
applicationDataMap = new LiteHashMap(10, Comparator.getLogicalComparator(), Comparator.getLogicalComparator());
}//if//
applicationDataMap.put(key, applicationData);
}//setApplicationData()//
}//SwtWrapperViewContext//

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2006,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.widgets.Shell;
import com.foundation.view.IViewContext;
public class SwtWrapperWindow extends Window {
private IViewContext viewContext = null;
/**
* SwtWrapperWindow constructor.
* @param parent The parent shell. This is optional.
* @param style The style for the new shell.
* @param viewContext The window's view context.
*/
public SwtWrapperWindow(Shell parent, int style, IViewContext viewContext) {
super();
this.viewContext = viewContext;
setSwtWidget(new Shell(parent, style));
isInitialized(true);
}//SwtWrapperWindow()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
}//initializeControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalGetViewContext()
*/
protected IViewContext internalGetViewContext() {
return viewContext;
}//internalGetViewContext()//
}//SwtWrapperWindow//

View File

@@ -0,0 +1,844 @@
/*
* Copyright (c) 2005,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.TabItem;
import com.common.util.*;
import com.common.debug.*;
import com.foundation.controller.*;
import com.foundation.util.IInlineCollectionObservable;
import com.foundation.util.IInlineCollectionObserver;
import com.foundation.util.IInlineIndexedCollectionObservable;
import com.foundation.util.IInlineIndexedCollectionObserver;
import com.foundation.view.*;
import com.foundation.view.resource.AbstractResourceService;
import com.foundation.view.swt.util.SwtUtilities;
/*
* This tab panel allows for static pages and dynamic pages where dynamic pages are tied to the model which supplies the view controller's for each dynamic page.
* The panel was designed such that any ordering of static and dynamic pages can be given. The dynamic page is created by calling the addPages() method which allows associations to be added.
* The PagesHolder (returned by addPages()) then manages the page or collection of page view controllers.
* <p>TODO: Add some way of sending the selected page to the view controller, and some way for the view controller to programatically select a page.</p>
*/
public class TabPanel extends Container implements Component.IComponentListener {
public static final int STYLE_TOP = SWT.TOP;
public static final int STYLE_BOTTOM = SWT.BOTTOM;
/** A collection of Component and PagesHolder instances which define the tabs in this tab folder. */
private IList pages = new LiteList(10, 50);
/** A mapping of TabItem's indexed by the related component. */
private LiteHashMap tabItemsByComponentMap = new LiteHashMap(15);
/** A flag to suspend the customized behavior when adding a control. This lets the page holder add and remove tabs without the tab panel attempting to add and remove tabs also. */
private boolean suspendCustomComponentBehavior = false;
/**
* The public interface for interacting with the pages holder.
*/
public interface IPagesHolder {
/**
* Sets the association container used to access the tab pages.
* @param container The tab pages association metadata.
*/
public void setPagesAssociation(SingleAssociationContainer container);
}//IPagesHolder//
/**
* A place holder for zero or more pages which are set based on a resource association which can return a view controller or a list of view controllers, one for each page.
*/
private class PagesHolder implements IPagesHolder, ISingleResourceAssociationChangeListener, IInlineIndexedCollectionObserver, IInlineCollectionObserver, Component.IComponentListener {
/** Allows one association to return either a collection of controllers, or one controller which will be turned into a tab page. */
private SingleResourceAssociation pages = new SingleResourceAssociation(TabPanel.this, this, getViewContext(), SingleResourceAssociation.TYPE_OBJECT, false, null);
/** The PagesHolder or Component which the pages in this PagesHolder follow in the tab order. */
private Object followsComponent = null;
/** The previous collection of view controllers. */
private IList viewControllers = new LiteList(1, 15);
/** TabItem instances mapped by their corresponding view controllers. */
private LiteHashMap tabItemsByViewControllerMap = new LiteHashMap(15);
/** A two way (one to one) mapping between the Component instances and their ViewController instances. */
private LiteHashMap componentControllerMapping = new LiteHashMap(30);
/** Temporarily suspends processing of events fired by registered collections. */
private boolean suspendCollectionEvents = false;
public PagesHolder(Object followsComponent) {
this.followsComponent = followsComponent;
}//PagesHolder()//
/* (non-Javadoc)
* @see com.foundation.view.swt.TabPanel.IPagesHolder#setPagesAssociation(com.foundation.view.SingleAssociationContainer)
*/
public void setPagesAssociation(SingleAssociationContainer container) {
verifyThread();
this.pages.setAssociations(container);
}//setPagesAssociation()//
/**
* Initializes the pages.
*/
public void initialize() {
pages.initialize();
}//initialize()//
/**
* Releases the pages.
*/
public void release() {
IIterator iterator = new LiteList(viewControllers).iterator();
pages.release();
//Release the tab resources and cleanup the mappings and listeners.//
while(iterator.hasNext()) {
ViewController next = (ViewController) iterator.next();
internalRemoveTab(next);
next.close();
}//while//
componentControllerMapping.removeAll();
componentControllerMapping = null;
tabItemsByViewControllerMap.removeAll();
tabItemsByViewControllerMap = null;
viewControllers.removeAll();
viewControllers = null;
followsComponent = null;
pages = null;
}//release()//
/**
* Refreshes the pages.
*/
public void refresh() {
//Not necessary since it is handled by the Container base class.//
//for(int index = 0; index < viewControllers.getSize(); index++) {
// ((AbstractComponent) ((ViewController) viewControllers.get(index)).getView()).internalViewRefreshAll();
//}//for//
refreshPages();
}//initialize()//
/**
* Synchronizes the pages.
*/
public void synchronize() {
//Not necessary since it is handled by the Container base class.//
//for(int index = 0; index < viewControllers.getSize(); index++) {
// ((AbstractComponent) ((ViewController) viewControllers.get(index)).getView()).internalViewSynchronizeAll();
//}//for//
}//initialize()//
/**
* Gets the TabItem that the pages of this holder follow.
* @return The tab item that the tab items related to this holder follow in the tab item ordering.
*/
public TabItem getPreviousTabItem() {
TabItem result = null;
if(followsComponent instanceof PagesHolder) {
result = ((PagesHolder) followsComponent).getLastTabItem();
}//if//
else if(followsComponent instanceof Component) {
result = (TabItem) tabItemsByComponentMap.get(followsComponent);
}//else if//
return result;
}//getPreviousTabItem()//
/**
* Gets the last tab item for this holder.
* @return The last TabItem instance which can be used as the previous TabItem for the component that follows this holder. This will only be null if there are no pages in this holder and there are no pages in front of this holder.
*/
public TabItem getLastTabItem() {
TabItem result = null;
if(viewControllers.getSize() > 0) {
result = (TabItem) tabItemsByViewControllerMap.get(viewControllers.getLast());
}//if//
else {
result = getPreviousTabItem();
}//else//
return result;
}//getLastTabItem()//
/**
* Refreshes the pages represented by this holder.
*/
protected void refreshPages() {
Object oldValue = pages.getValue();
if(pages.refresh()) {
startChanges(0);
try {
Object newValue = pages.getValue();
TabItem previous = getPreviousTabItem();
int previousIndex = previous != null ? getSwtTabFolder().indexOf(previous) + 1 : 0;
//Remove listeners from the old value.//
if(oldValue instanceof IInlineIndexedCollectionObservable) {
((IInlineIndexedCollectionObservable) oldValue).removeCollectionObserver(this);
}//if//
else if(oldValue instanceof IInlineCollectionObservable) {
((IInlineCollectionObservable) oldValue).removeCollectionObserver(this);
}//else if//
//If the new value is a collection or object then add and remove pages as required, and add listeners as required.//
if(newValue instanceof ICollection) {
IIterator iterator = ((ICollection) newValue).iterator();
LiteList newViewControllers = new LiteList(((ICollection) newValue).getSize());
//Add tabs for all the view controllers.//
while(iterator.hasNext()) {
Object next = iterator.next();
//Ignore non-view controller objects.//
if(next instanceof ViewController) {
ViewController controller = (ViewController) next;
int index = viewControllers != null ? viewControllers.getIndexOf(controller) : -1;
if(index != -1) {
TabItem newTabItem = internalRecreateTab(controller, previousIndex);
viewControllers.remove(index);
//Note we don't just increment the index since they could get moved by the changes made by updating the tabs.//
if(newTabItem != null) {
previousIndex = getSwtTabFolder().indexOf(newTabItem) + 1;
}//if//
}//if//
else {
TabItem newTabItem = internalAddTab(controller, previousIndex);
//Note we don't just increment the index since they could get moved by the changes made by updating the tabs.//
if(newTabItem != null) {
previousIndex = getSwtTabFolder().indexOf(newTabItem) + 1;
}//if//
}//else//
newViewControllers.add(controller);
}//if//
else {
//Don't allow non-view controller objects since it will mess up the valuesSorted(..) method.//
throw new RuntimeException("Expecting a view controller.");
}//else//
}//while//
//Remove the previous view controller(s).//
removeOldPages(viewControllers);
//Add the controllers to the list of view controllers.//
viewControllers.addAll(newViewControllers);
//Prevent collection events from notifying us of existing items in the collection.//
suspendCollectionEvents = true;
//Add a listener to the collection so we get change events.//
if(newValue instanceof IInlineIndexedCollectionObservable) {
((IInlineIndexedCollectionObservable) newValue).addCollectionObserver(this);
}//if//
else if(newValue instanceof IInlineCollectionObservable) {
((IInlineCollectionObservable) newValue).addCollectionObserver(this);
}//else if//
//Re-enable the collection events.//
suspendCollectionEvents = false;
}//if//
else if(newValue instanceof ViewController) {
ViewController controller = (ViewController) newValue;
int index = viewControllers != null ? viewControllers.getIndexOf(controller) : -1;
if(index != -1) {
internalRecreateTab(controller, previousIndex);
viewControllers.remove(index);
}//if//
else {
internalAddTab(controller, previousIndex);
}//else//
//Remove the previous view controller(s).//
removeOldPages(viewControllers);
//Add the one controller to the list of view controllers.//
viewControllers.add(controller);
}//else if//
else {
removeOldPages(viewControllers);
}//else//
}//try//
finally {
stopChanges();
}//finally//
}//if//
}//refreshPages()//
/**
* Removes the old pages from the tab panel.
* @param viewControllers The collection of view controllers no longer in the tab panel.
* @param oldValue The previous value
*/
private void removeOldPages(IList viewControllers) {
while(viewControllers.getSize() > 0) {
ViewController controller = (ViewController) viewControllers.remove(viewControllers.getSize() - 1);
//Remove each controller's page and close the controller.//
internalRemoveTab(controller);
controller.close();
}//while//
}//removeOldPages()//
/**
* Adds a tab to the panel for the given view controller.
* @param viewController The view controller whose view component will be displayed in the tab.
* @param index The index of this tab item, which will be used to set the tab item ordering.
* @return The new tab item.
*/
protected TabItem internalAddTab(ViewController viewController, int index) {
TabItem tabItem = null;
suspendCustomComponentBehavior = true;
try {
if(viewController != null) {
Component component;
viewController.openPartial(TabPanel.this, getViewContext());
component = (Component) viewController.getView();
tabItem = new org.eclipse.swt.widgets.TabItem(getSwtTabFolder(), 0, index);
if(component instanceof Container) {
Image image = component.getContainerImage();
tabItem.setText(component.getContainerTitle() == null ? "" : component.getContainerTitle());
tabItem.setImage(image);
}//if//
else {
tabItem.setText("");
}//else//
tabItem.setToolTipText(component.getToolTipText());
tabItem.setControl(component.getSwtControl());
tabItem.setData(component);
component.registerListener(this);
tabItemsByViewControllerMap.put(viewController, tabItem);
componentControllerMapping.put(viewController, component);
componentControllerMapping.put(component, viewController);
}//if//
else {
Debug.log("Error: Invalid component. Unable to add the component as a tab in the tab panel.");
}//else//
}//try//
finally {
suspendCustomComponentBehavior = false;
}//finally//
return tabItem;
}//internalAddTab()//
/**
* Removes a tab from the panel for the given related view component.
* @param viewController The view controller whose view component's tab will be removed.
*/
protected void internalRemoveTab(ViewController viewController) {
suspendCustomComponentBehavior = true;
try {
TabItem tabItem = (TabItem) tabItemsByViewControllerMap.remove(viewController);
Component component = (Component) viewController.getView();
if(component == null) {
component = (Component) componentControllerMapping.get(viewController);
}//if//
//Unregister the component data listener.//
if(component != null) {
component.unregisterListener(this);
componentControllerMapping.remove(component);
}//if//
//Dispose of the old tab item.//
if(tabItem != null) {
//Note: Don't dispose of the image because it comes from the component's container-image property whose lifecycle is managed by the component.//
tabItem.dispose();
}//if//
componentControllerMapping.remove(viewController);
}//try//
finally {
suspendCustomComponentBehavior = false;
}//finally//
}//internalRemoveTab()//
/**
* Recreates the view controller's tab by removing the old tab and adding a new one at the given index.
* @param viewController The view controller whose view component's tab will be removed and re-added.
* @param index The index of the recreated tab item.
* @return The new tab item.
*/
protected TabItem internalRecreateTab(ViewController viewController, int index) {
TabItem oldTabItem = (TabItem) tabItemsByViewControllerMap.remove(viewController);
TabItem tabItem = null;
if((oldTabItem != null) && (viewController != null) && (((Component) viewController.getView()).getSwtControl() != null)) {
tabItem = new org.eclipse.swt.widgets.TabItem(getSwtTabFolder(), 0, index);
tabItem.setText(oldTabItem.getText());
tabItem.setImage(oldTabItem.getImage());
tabItem.setToolTipText(oldTabItem.getToolTipText());
tabItem.setControl(oldTabItem.getControl());
tabItem.setData(oldTabItem.getData());
//Replace the tab item in the mapping by view controller.//
tabItemsByViewControllerMap.put(viewController, tabItem);
}//if//
else {
Debug.log("Error: Invalid component. Unable to recreate the component as a tab in the tab panel.");
//Attempt to cleanup after the controller.//
if(oldTabItem != null) {
internalRemoveTab(viewController);
}//if//
}//else//
//Dispose of the old tab item.//
oldTabItem.dispose();
return tabItem;
}//internalRecreateTab()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#onValueChanged(com.foundation.view.ResourceAssociation, int)
*/
public void onValueChanged(ResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == pages) {
refreshPages();
}//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) {
}//onModelExternallyChanged()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#addMessageHold()
*/
public void addMessageHold() {
}//addMessageHold()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#removeMessageHold()
*/
public void removeMessageHold() {
}//removeMessageHold()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#startChanges(int)
*/
public void startChanges(int changeCount) {
startRendering();
}//startChanges()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#stopChanges()
*/
public void stopChanges() {
stopRendering();
}//stopChanges()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineCollectionObserver#valueAdded(java.lang.Object)
*/
public void valueAdded(Object value) {
if((!suspendCollectionEvents) && (value instanceof ViewController)) {
TabItem last = getLastTabItem();
int tabIndex = last == null ? 0 : getSwtTabFolder().indexOf(last) + 1;
internalAddTab((ViewController) value, tabIndex);
viewControllers.add(tabIndex, value);
}//if//
}//valueAdded()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#valueAdded(java.lang.Object, int)
*/
public void valueAdded(Object value, int index) {
if((!suspendCollectionEvents) && (value instanceof ViewController)) {
TabItem previous = getPreviousTabItem();
int tabIndex = (previous == null ? 0 : getSwtTabFolder().indexOf(previous) + 1) + index;
internalAddTab((ViewController) value, tabIndex);
viewControllers.add(tabIndex, value);
}//if//
}//valueAdded()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineCollectionObserver#valueRemoved(java.lang.Object)
*/
public void valueRemoved(Object value) {
if((!suspendCollectionEvents) && (value instanceof ViewController)) {
internalRemoveTab((ViewController) value);
viewControllers.remove(value);
((ViewController) value).close();
}//if//
}//valueRemoved()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#valueRemoved(java.lang.Object, int)
*/
public void valueRemoved(Object value, int index) {
valueRemoved(value);
}//valueRemoved()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#removingAll()
*/
public void removingAll() {
if(!suspendCollectionEvents) {
IIterator iterator = viewControllers.iterator();
startChanges(viewControllers.getSize());
try {
while(iterator.hasNext()) {
valueRemoved(iterator.next());
}//while//
}//try//
finally {
stopChanges();
}//finally//
}//if//
}//removingAll()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#valuesSorted(int[])
*/
public void valuesSorted(int[] mapping) {
if(!suspendCollectionEvents) {
TabItem previousTabItem = getPreviousTabItem();
int nextIndex = previousTabItem == null ? 0 : getSwtTabFolder().indexOf(previousTabItem) + 1;
TabItem[] oldTabItems = new TabItem[mapping.length];
LiteList newViewControllers = new LiteList(viewControllers.getSize());
startChanges(0);
//Reorder the tab items by adding new tab items before the old ones.//
for(int index = 0; index < mapping.length; index++) {
int oldIndex = nextIndex + index + mapping[index];
TabItem oldTabItem = getSwtTabFolder().getItem(oldIndex);
TabItem tabItem = new org.eclipse.swt.widgets.TabItem(getSwtTabFolder(), 0, nextIndex);
ViewController controller = (ViewController) componentControllerMapping.get(oldTabItem.getData());
newViewControllers.add(viewControllers.get(mapping[index]));
tabItem.setText(oldTabItem.getText());
tabItem.setImage(oldTabItem.getImage());
tabItem.setToolTipText(oldTabItem.getToolTipText());
tabItem.setControl(oldTabItem.getControl());
tabItem.setData(oldTabItem.getData());
nextIndex++;
oldTabItems[index] = oldTabItem;
//Replace the tab item in the mapping by view controller.//
tabItemsByViewControllerMap.put(controller, tabItem);
}//for//
//Remove the old tab items.//
for(int index = 0; index < oldTabItems.length; index++) {
oldTabItems[index].dispose();
}//for//
viewControllers.replaceAll(newViewControllers);
stopChanges();
}//if//
}//valuesSorted()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component.IComponentListener#imageChanged(com.foundation.view.swt.Component, org.eclipse.swt.graphics.Image)
*/
public void imageChanged(Component component, Image newImage) {
ViewController controller = (ViewController) componentControllerMapping.get(component);
if(controller != null) {
TabItem tabItem = (TabItem) tabItemsByViewControllerMap.get(controller);
if(tabItem != null) {
tabItem.setImage(newImage);
}//if//
}//if//
}//imageChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component.IComponentListener#titleChanged(com.foundation.view.swt.Component, java.lang.String)
*/
public void titleChanged(Component component, String newTitle) {
ViewController controller = (ViewController) componentControllerMapping.get(component);
if(controller != null) {
TabItem tabItem = (TabItem) tabItemsByViewControllerMap.get(controller);
if(tabItem != null) {
tabItem.setText(newTitle == null ? "" : newTitle);
}//if//
}//if//
}//titleChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component.IComponentListener#toolTipTextChanged(com.foundation.view.swt.Component, java.lang.String)
*/
public void toolTipTextChanged(Component component, String newToolTipText) {
ViewController controller = (ViewController) componentControllerMapping.get(component);
if(controller != null) {
TabItem tabItem = (TabItem) tabItemsByViewControllerMap.get(controller);
if(tabItem != null) {
tabItem.setToolTipText(newToolTipText);
}//if//
}//if//
}//toolTipTextChanged()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#getResourceService()
*/
public AbstractResourceService getResourceService() {
return TabPanel.this.getResourceService();
}//getResourceService()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#getDecorationManager()
*/
public DecorationManager getDecorationManager() {
return TabPanel.this.getDecorationManager();
}//getDecorationManager()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#addDecoration(com.foundation.view.AbstractDecoration)
*/
public void addDecoration(AbstractDecoration decoration) {
//Never used.//
}//addDecoration()//
/* (non-Javadoc)
* @see com.foundation.view.ISingleResourceAssociationChangeListener#removeDecoration(com.foundation.view.AbstractDecoration)
*/
public void removeDecoration(AbstractDecoration decoration) {
//Never used.//
}//removeDecoration()//
}//PagesHolder//
/**
* TabPanel constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_NO_BACKGROUND
* @see #STYLE_NO_FOCUS
* @see #STYLE_NO_MERGE_PAINTS
* @see #STYLE_NO_REDRAW_RESIZE
* @see #STYLE_NO_RADIO_GROUP
* @see #STYLE_H_SCROLL
* @see #STYLE_V_SCROLL
* @see #STYLE_BORDER
* @see #STYLE_LEFT_TO_RIGHT
* @see #STYLE_RIGHT_TO_LEFT
* @see #STYLE_TOP
* @see #STYLE_BOTTOM
*/
public TabPanel(Container parent, String name, int style) {
super(parent, name, style);
}//TabPanel()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.TabFolder(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT tab folder that represents this tab panel.
* @return The SWT tab folder providing visualization for this tab panel.
*/
public org.eclipse.swt.widgets.TabFolder getSwtTabFolder() {
return (org.eclipse.swt.widgets.TabFolder) getSwtControl();
}//getSwtTabFolder()//
/**
* Adds N pages to the tab panel, where the pages come from an association with the model.
* @return The page holder which can be used to add associations.
*/
public IPagesHolder addPages() {
PagesHolder holder = new PagesHolder(pages.getSize() > 0 ? pages.getLast() : null);
pages.add(holder);
return holder;
}//addPages()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container#addComponent(com.foundation.view.IAbstractComponent)
*/
public void addComponent(IAbstractComponent component) {
super.addComponent(component);
if(component instanceof Component && !suspendCustomComponentBehavior) {
pages.add(component);
if(isInitialized()) {
internalAddTab((Component) component);
}//if//
}//if//
}//addComponent()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container#removeComponent(com.foundation.view.IAbstractComponent)
*/
public void removeComponent(IAbstractComponent component) {
if(component instanceof Component && !suspendCustomComponentBehavior) {
internalRemoveTab((Component) component);
pages.remove(component);
}//if//
super.removeComponent(component);
}//removeComponent()//
/**
* Adds a tab to the panel for the given view component.
* <p>Tabs displaying a view controller's view should set the tab item's data to be the view controller instead of the view component.</p>
* @param component The view component that will be displayed in the tab.
*/
protected void internalAddTab(Component component) {
if((component != null) && (component.getSwtControl() != null)) {
TabItem tabItem = new org.eclipse.swt.widgets.TabItem(getSwtTabFolder(), 0);
if(component instanceof Container) {
Image image = component.getContainerImage();
tabItem.setText(component.getContainerTitle() == null ? "" : component.getContainerTitle());
tabItem.setImage(image);
}//if//
else {
tabItem.setText("");
}//else//
tabItem.setToolTipText(component.getToolTipText());
tabItem.setControl(component.getSwtControl());
tabItem.setData(component);
tabItemsByComponentMap.put(component, tabItem);
component.registerListener(this);
}//if//
else {
Debug.log("Error: Invalid component. Unable to add the component as a tab in the tab panel.");
}//else//
}//internalAddTab()//
/**
* Removes a tab from the panel for the given related view component.
* @param component The view component associated with the tab to be removed.
*/
protected void internalRemoveTab(Component component) {
TabItem tabItem = (TabItem) tabItemsByComponentMap.remove(component);
//Dispose of the old tab item.//
if(tabItem != null) {
tabItem.dispose();
}//if//
component.unregisterListener(this);
}//internalRemoveTab()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitializeAll()
*/
public void internalViewInitializeAll() {
IIterator iterator = null;
//Note: We are using the initialize all to setup the tabs so that they can be released before releasing the children.//
super.internalViewInitializeAll();
iterator = pages.iterator();
//Initialize the tabs.//
while(iterator.hasNext()) {
Object page = iterator.next();
if(page instanceof PagesHolder) {
((PagesHolder) page).initialize();
}//if//
else {
//Not necessary since it is handled by the Container base class.//
//((Component) page).internalViewInitializeAll();
internalAddTab((Component) page);
}//else//
}//for//
}//internalViewInitializeAll()//
/* (non-Javadoc)
* @see com.foundation.view.IView#viewReleaseAll()
*/
public void internalViewReleaseAll() {
IIterator iterator = pages.iterator();
//Note: We are using the release all to release the tabs so that they can be released before releasing the children.//
while(iterator.hasNext()) {
Object page = iterator.next();
if(page instanceof Component) {
//Not necessary since it is handled by the Container base class.//
//((Component) page).internalViewReleaseAll();
internalRemoveTab((Component) page);
}//if//
else {
((PagesHolder) page).release();
}//else//
}//for//
super.internalViewReleaseAll();
}//internalViewReleaseAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container#internalViewRefreshAll()
*/
public void internalViewRefreshAll() {
for(int index = 0; index < pages.getSize(); index++) {
Object page = pages.get(index);
if(page instanceof PagesHolder) {
((PagesHolder) page).refresh();
}//if//
else if(page instanceof Component) {
//Not necessary since it is handled by the Container base class.//
//((Component) page).internalViewRefreshAll();
}//else//
}//for//
super.internalViewRefreshAll();
}//internalViewRefreshAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container#internalViewSynchronizeAll()
*/
public void internalViewSynchronizeAll() {
for(int index = 0; index < pages.getSize(); index++) {
Object page = pages.get(index);
if(page instanceof PagesHolder) {
((PagesHolder) page).synchronize();
}//if//
else if(page instanceof Component) {
//Not necessary since it is handled by the Container base class.//
//((Component) page).internalViewSynchronizeAll();
}//else//
}//for//
super.internalViewSynchronizeAll();
}//internalViewSynchronizeAll()//
/* (non-Javadoc)
* @see #onEventFired()
*/
protected void internalOnEventFired(IEventAssociation eventAssociation, Object[] eventArguments) {
}//internalOnEventFired()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#onValueChanged(com.foundation.view.swt.IAttributeAssociation)
*/
protected void internalOnValueChanged(IAttributeAssociation attributeAssociation) {
super.internalOnValueChanged(attributeAssociation);
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component.IComponentListener#imageChanged(com.foundation.view.swt.Component, org.eclipse.swt.graphics.Image)
*/
public void imageChanged(Component component, Image newImage) {
TabItem tabItem = (TabItem) tabItemsByComponentMap.get(component);
if(tabItem != null) {
tabItem.setImage(newImage);
}//if//
else {
component.unregisterListener(this);
}//else//
}//imageChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component.IComponentListener#titleChanged(com.foundation.view.swt.Component, java.lang.String)
*/
public void titleChanged(Component component, String newTitle) {
TabItem tabItem = (TabItem) tabItemsByComponentMap.get(component);
if(tabItem != null) {
tabItem.setText(newTitle);
}//if//
else {
component.unregisterListener(this);
}//else//
}//titleChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component.IComponentListener#toolTipTextChanged(com.foundation.view.swt.Component, java.lang.String)
*/
public void toolTipTextChanged(Component component, String newToolTipText) {
TabItem tabItem = (TabItem) tabItemsByComponentMap.get(component);
if(tabItem != null) {
tabItem.setToolTipText(newToolTipText);
}//if//
else {
component.unregisterListener(this);
}//else//
}//toolTipTextChanged()//
}//TabPanel//

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,951 @@
/*
* Copyright (c) 2006,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import com.common.thread.IRunnable;
import com.common.util.LiteList;
import com.foundation.view.IMethodAssociation;
import com.foundation.view.JefImage;
import com.foundation.view.LinkData;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
import com.foundation.view.resource.ResourceReference;
import com.foundation.view.swt.util.SwtUtilities;
public class ToolBar extends Container {
public static final int STYLE_FLAT = SWT.FLAT;
public static final int STYLE_RIGHT = SWT.RIGHT;
public static final int STYLE_WRAP = SWT.WRAP;
public static final int STYLE_HORIZONTAL = SWT.HORIZONTAL;
public static final int STYLE_VERTICAL = SWT.VERTICAL;
public static final int STYLE_SHADOW_OUT = SWT.SHADOW_OUT;
/** The collection of ToolItem instances contained by the tool bar. */
private LiteList toolItems = new LiteList(10, 20);
/** The collection of Menu instances associated with tool items. */
private LiteList menus = new LiteList(10, 20);
/**
* This tool item can be extended to provide customized tool item behavior.
*/
public static abstract class AbstractToolItem extends AbstractComponent {
public static final int STYLE_DROP_DOWN = SWT.DROP_DOWN;
public static final int STYLE_CHECK = SWT.CHECK;
public static final int STYLE_PUSH = SWT.PUSH;
public static final int STYLE_RADIO = SWT.RADIO;
public static final int STYLE_SEPARATOR = SWT.SEPARATOR;
public static final int LINK_TARGET_TOOL_TIP_TEXT = AbstractComponent.LAST_LINK_TARGET + 1;
public static final int LINK_TARGET_IS_ENABLED = AbstractComponent.LAST_LINK_TARGET + 2;
public static final int LAST_LINK_TARGET = AbstractComponent.LAST_LINK_TARGET + 2;
/** The item's tool tip text resource. */
private SingleResourceAssociation toolTipText = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_TEXT, false, null);
/** The resource defining the enabled state for the component. */
private SingleResourceAssociation isEnabled = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_BOOLEAN, false, Boolean.TRUE);
/** A counter tracking the number of times the component has been told to be disabled. This allows us to disable a container which in turn disables all components. */
private int disabledCounter = 0;
/** Whether this is a stateful item. */
protected final boolean isStateful;
/** Whether this is a separator. */
protected final boolean isSeparator;
/** Whether this is a drop down control. */
protected final boolean isDropDown;
/**
* AbstractToolItem constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_DROP_DOWN
* @see #STYLE_CHECK
* @see #STYLE_PUSH
* @see #STYLE_RADIO
* @see #STYLE_SEPARATOR
*/
protected AbstractToolItem(Container parent, int style) {
super(parent, style);
isStateful = ((style & STYLE_RADIO) > 0) || ((style & STYLE_CHECK) > 0);
isSeparator = ((style & STYLE_SEPARATOR) > 0);
isDropDown = ((style & STYLE_DROP_DOWN) > 0);
((ToolBar) parent).addToolItem(this);
}//AbstractToolItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IInternalAbstractComponent#getShell()
*/
public Shell getShell() {
return ((Container) getContainer()).getShell();
}//getShell()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.ToolItem(((ToolBar) getContainer()).getSwtToolBar(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the swt tool item for this tool item.
* @return The SWT tool item providing visualization for this tool item.
*/
public org.eclipse.swt.widgets.ToolItem getSwtToolItem() {
return (org.eclipse.swt.widgets.ToolItem) getSwtWidget();
}//getSwtToolItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
toolTipText.initialize();
isEnabled.initialize();
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
toolTipText.release();
isEnabled.release();
if(!getSwtToolItem().isDisposed()) {
getSwtToolItem().dispose();
}//if//
super.internalViewRelease();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
internalViewRefreshToolTipText();
internalViewRefreshIsEnabled();
super.internalViewRefresh();
}//internalViewRefresh()//
/**
* Refreshes the item tool tip text.
*/
protected void internalViewRefreshToolTipText() {
if(toolTipText.refresh()) {
getSwtToolItem().setToolTipText((String) toolTipText.getValue());
}//if//
}//internalViewRefreshToolTipText()//
/**
* Refreshes whether the component is enabled based on the attribute value or if null the default flag value.
*/
protected void internalViewRefreshIsEnabled() {
if(isEnabled.refresh()) {
internalSetEnabledState(isEnabled.getValue() == null ? true : ((Boolean) isEnabled.getValue()).booleanValue());
}//if//
}//internalViewRefreshIsEnabled()//
/**
* Performs the actual work of enable or disabling the component.
* @param isEnabled Whether the enabled state should be altered to be enabled, otherwise it is altered to be disabled.
*/
protected void internalSetEnabledState(boolean isEnabled) {
//Some components may not have controls, such as value holders.//
if(getSwtToolItem() != null) {
if(!isEnabled || disabledCounter > 0) {
disabledCounter += !isEnabled ? 1 : -1;
}//if//
if(isEnabled && disabledCounter == 0) {
getSwtToolItem().setEnabled(true);
}//if//
else if(!isEnabled && disabledCounter == 1) {
getSwtToolItem().setEnabled(false);
}//else if//
}//if//
}//internalSetEnabledState()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == toolTipText) {
internalViewRefreshToolTipText();
}//if//
else if(resourceAssociation == isEnabled) {
internalViewRefreshIsEnabled();
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/**
* Forces the component to resize and requests that the window layout.
*/
public void resize() {
if(isInitialized()) {
getSwtToolItem().getParent().pack(true);
getSwtToolItem().getParent().getShell().layout(true, true);
}//if//
}//resize()//
/**
* Sets the association container used to access the tool tip.
* @param container The tool tip association metadata.
*/
public void setToolTipTextAssociation(SingleAssociationContainer container) {
verifyThread();
this.toolTipText.setAssociations(container);
}//setToolTipTextAssociation()//
/**
* Sets the association container used to access the enabled state.
* @param container The enabled state association metadata.
*/
public void setIsEnabledAssociation(SingleAssociationContainer container) {
verifyThread();
this.isEnabled.setAssociations(container);
}//setIsEnabledAssociation()//
/**
* Sets the component's default tool tip text.
* @param toolTipText The tool tip text to be displayed by this component.
*/
public void setToolTipText(String toolTipText) {
verifyThread();
this.toolTipText.setDefaultValue(toolTipText);
}//setToolTipText()//
/**
* Sets the component's default tool tip text resource.
* @return The tool tip text to be displayed by this component.
*/
public void setToolTipText(ResourceReference toolTipText) {
verifyThread();
this.toolTipText.setDefaultValue(toolTipText);
}//setToolTipText()//
/**
* Sets whether the component is enabled (by default if an attribute is bound to this value).
* @param isEnabled Whether the user can interact with the component.
*/
public void setIsEnabled(boolean isEnabled) {
verifyThread();
this.isEnabled.setDefaultValue(isEnabled ? Boolean.TRUE : Boolean.FALSE);
}//setIsEnabled()//
/**
* Sets the default enabled state resource.
* @param isEnabled Whether the user can interact with the component.
*/
public void setIsEnabled(ResourceReference isEnabled) {
verifyThread();
this.isEnabled.setDefaultValue(isEnabled);
}//setIsEnabled()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnLinkInvoked(int, java.lang.Object)
*/
protected void internalOnLinkInvoked(int linkTarget, Object data) {
switch(linkTarget) {
case LINK_TARGET_IS_ENABLED: {
internalSetEnabledState(data != null && data instanceof Boolean ? ((Boolean) data).booleanValue() : false);
break;
}//case//
case LINK_TARGET_TOOL_TIP_TEXT: {
getSwtToolItem().setToolTipText(data instanceof String ? (String) data : "");
break;
}//case//
default: {
super.internalOnLinkInvoked(linkTarget, data);
break;
}//default//
}//switch//
}//internalOnLinkInvoked()//
}//AbstractToolItem//
/**
* Encapsulates an item in the bar.
*/
public static class ToolItem extends AbstractToolItem implements SelectionListener {
public static final int LINK_TARGET_SELECTION = AbstractToolItem.LAST_LINK_TARGET + 1;
public static final int LINK_TARGET_TEXT = AbstractToolItem.LAST_LINK_TARGET + 2;
public static final int LINK_TARGET_IMAGE = AbstractToolItem.LAST_LINK_TARGET + 3;
public static final int LINK_TARGET_DISABLED_IMAGE = AbstractToolItem.LAST_LINK_TARGET + 4;
public static final int LINK_TARGET_ROLLOVER_IMAGE = AbstractToolItem.LAST_LINK_TARGET + 5;
public static final int LAST_LINK_TARGET = AbstractToolItem.LAST_LINK_TARGET + 5;
/** Whether the item has a custom width. */
private boolean customWidth = false;
/** Called when the button is pressed (only used for push items). */
private IMethodAssociation selectionMethod = null;
/** The item's selection state resource. */
private SingleResourceAssociation selection = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_BOOLEAN, true, Boolean.FALSE);
/** The linkage for the selection. */
private Linkage selectionLinkage = new Linkage();
/** The item's text resource. */
private SingleResourceAssociation text = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_TEXT, false, "");
/** The item's image resource. */
private SingleResourceAssociation image = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_IMAGE, false, null);
/** The item's image resource. */
private SingleResourceAssociation disabledImage = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_IMAGE, false, null);
/** The item's hot image resource. */
private SingleResourceAssociation hotImage = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_IMAGE, false, null);
/** Whether the selection state is auto synchronized. */
private boolean autoSynchronizeSelection = true;
/** The delay to be used when auto synchronizing changes to the text. */
private long autoSynchronizeSelectionDelay = 0;
/** The task that auto synchronizes the selection after a short delay. */
private Task autoSynchronizeSelectionTask = null;
/** The custom control associated with the item. */
private Component control = null;
/** The popup menu associated with the item. */
private Menu menu = null;
/** A holder for the value of the text. */
private ResourceHolder textHolder = new ResourceHolder(this);
/** A holder for the value of the image. */
private ResourceHolder imageHolder = new ResourceHolder(this);
/** A holder for the value of the hot image. */
private ResourceHolder hotImageHolder = new ResourceHolder(this);
/** A holder for the value of the disabled image. */
private ResourceHolder disabledImageHolder = new ResourceHolder(this);
/**
* ToolItem constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_DROP_DOWN
* @see #STYLE_CHECK
* @see #STYLE_PUSH
* @see #STYLE_RADIO
* @see #STYLE_SEPARATOR
*/
public ToolItem(Container parent, String name, int style) {
super(parent, style);
}//ToolItem()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractComponent#getName()
*/
public String getName() {
return "__ToolItem__";
}//getName()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
getSwtToolItem().addSelectionListener(this);
super.internalViewInitialize();
text.initialize();
image.initialize();
hotImage.initialize();
disabledImage.initialize();
selection.initialize();
if(control != null) {
getSwtToolItem().setControl(control.getSwtControl());
}//if//
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
destroyImage((JefImage) imageHolder.getValue());
destroyImage((JefImage) hotImageHolder.getValue());
destroyImage((JefImage) disabledImageHolder.getValue());
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
autoSynchronizeSelectionTask = null;
}//if//
}//synchronized//
if(!getSwtToolItem().isDisposed()) {
getSwtToolItem().removeSelectionListener(this);
getSwtToolItem().setControl(null);
}//if//
text.release();
image.release();
hotImage.release();
disabledImage.release();
selection.release();
textHolder.release();
imageHolder.release();
hotImageHolder.release();
disabledImageHolder.release();
super.internalViewRelease();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalViewRefreshSelection();
internalViewRefreshText();
internalViewRefreshImage();
internalViewRefreshHotImage();
internalViewRefreshDisabledImage();
//Auto calculate the width based on the packed size of the control.//
//TODO: Should we set the control's height to the bar's height?
if(!customWidth && isSeparator && control != null) {
Point size;
control.getSwtControl().pack();
size = control.getSwtControl().computeSize(SWT.DEFAULT, SWT.DEFAULT);
getSwtToolItem().setWidth(size.x);
}//if//
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
super.internalViewSynchronize();
if((isStateful) && (!autoSynchronizeSelection)) {
selection.setValue(getSwtToolItem().getSelection() ? Boolean.TRUE : Boolean.FALSE);
}//if//
}//internalViewSynchronize()//
/**
* Refreshes the item selection.
*/
protected void internalViewRefreshSelection() {
if((isStateful) && (selection.refresh())) {
Boolean selectionState = (Boolean) selection.getValue();
selectionState = selectionState == null ? Boolean.FALSE : selectionState;
if(getSwtToolItem().getSelection() != selectionState.booleanValue()) {
getSwtToolItem().setSelection(selectionState.booleanValue());
selectionLinkage.invoke(selectionState);
}//if//
}//if//
}//internalViewRefreshSelection()//
/**
* Refreshes the item hot image.
*/
protected void internalViewRefreshHotImage() {
if(hotImage.refresh()) {
hotImageHolder.setValue(hotImage.getValue());
}//if//
}//internalViewRefreshHotImage()//
/**
* Refreshes the item disabled image.
*/
protected void internalViewRefreshDisabledImage() {
if(disabledImage.refresh()) {
disabledImageHolder.setValue(disabledImage.getValue());
}//if//
}//internalViewRefreshDisabledImage()//
/**
* Refreshes the item image.
*/
protected void internalViewRefreshImage() {
if(image.refresh()) {
imageHolder.setValue(image.getValue());
}//if//
}//internalViewRefreshImage()//
/**
* Refreshes the item text.
*/
protected void internalViewRefreshText() {
if(text.refresh()) {
textHolder.setValue(text.getValue());
}//if//
}//internalViewRefreshText()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalResourceHolderChanged(com.foundation.view.swt.ResourceHolder, java.lang.Object, java.lang.Object)
*/
protected void internalResourceHolderChanged(ResourceHolder resource, Object oldValue, Object newValue, int flags) {
if(resource == textHolder) {
getSwtToolItem().setText((String) newValue);
resize();
}//if//
else if(resource == imageHolder) {
destroyImage(getSwtToolItem().getImage());
getSwtToolItem().setImage(createImage((JefImage) newValue));
resize();
}//else if//
else if(resource == hotImageHolder) {
destroyImage(getSwtToolItem().getHotImage());
getSwtToolItem().setHotImage(createImage((JefImage) newValue));
resize();
}//else if//
else if(resource == disabledImageHolder) {
destroyImage(getSwtToolItem().getDisabledImage());
getSwtToolItem().setDisabledImage(createImage((JefImage) newValue));
resize();
}//else if//
else {
super.internalResourceHolderChanged(resource, oldValue, newValue, flags);
}//else//
}//internalOnAssociationChanged()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent event) {
widgetSelected(event);
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent event) {
if(isSeparator && control != null) {
//Do nothing.//
//TODO: Do we need to pass this even to the control? Will we even get the event?
}//if//
else if(isDropDown && event.detail == SWT.ARROW) {
Rectangle rect = getSwtToolItem().getBounds();
Point point = new Point(rect.x, rect.y + rect.height);
//Show the drop down menu.//
point = getSwtToolItem().getParent().toDisplay(point);
if(menu != null) {
menu.getSwtMenu().setLocation(point.x, point.y);
menu.getSwtMenu().setVisible(true);
}//if//
}//else if//
else if(isSeparator) {
//Ignore//
}//else if//
else {
selectionChanged(getSwtToolItem().getSelection());
}//else//
}//widgetSelected()//
/**
* Called when the selection is changed in the view control.
* This method updates all bindings and
* @param isSelected Whether the control is selected (stateful controls only).
*/
protected void selectionChanged(final boolean isSelected) {
if(!isSeparator && !isDropDown) {
//Handle the button selection.//
if((selectionMethod != null) || (autoSynchronizeSelection)) {
if((selectionMethod == null) && (autoSynchronizeSelectionDelay > 0)) {
//Start a task to send the text to the server after a short delay. This will reduce the overhead of auto synchronizing the selection.//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
}//if//
autoSynchronizeSelectionTask = new Task() {
public void execute() {
//Make sure that this task is still valid and is not being superceeded.//
synchronized(ToolItem.this) {
if(autoSynchronizeSelectionTask == this) {
//Cleanup after the task.//
autoSynchronizeSelectionTask = null;
getEventLoop().executeAsync(new IRunnable() {
public Object run() {
selection.setValue(isSelected ? Boolean.TRUE : Boolean.FALSE);
return null;
}//run()//
});
}//if//
}//synchronized//
}//run()//
};
addTask(autoSynchronizeSelectionTask, autoSynchronizeSelectionDelay);
}//synchronized//
}//if//
else {
if(selectionMethod != null) {
selectionMethod.invoke(new Object[] {isSelected ? Boolean.TRUE : Boolean.FALSE}, true); //TODO: Save the array for reuse.//
}//if//
else {
selection.setValue(isSelected ? Boolean.TRUE : Boolean.FALSE);
}//else//
}//else//
}//if//
selectionLinkage.invoke(isStateful ? isSelected ? Boolean.TRUE : Boolean.FALSE : null);
}//if//
}//selectionChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == text) {
internalViewRefreshText();
}//if//
else if(resourceAssociation == image) {
internalViewRefreshImage();
}//else if//
else if(resourceAssociation == selection) {
internalViewRefreshSelection();
}//else if//
else if(resourceAssociation == hotImage) {
internalViewRefreshHotImage();
}//else if//
else if(resourceAssociation == disabledImage) {
internalViewRefreshDisabledImage();
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/**
* Sets the tool item width.
* @param width The width of the tool item. This should be ignored unless this is a custom or separator item.
*/
public void setWidth(int width) {
customWidth = true;
getSwtToolItem().setWidth(width);
}//setWidth()//
/**
* Sets the component default selection state.
* @param isSelected Whether the component is in the selected state.
*/
public void setIsSelected(Boolean isSelected) {
verifyThread();
if(isStateful) {
selection.setDefaultValue(isSelected);
}//if//
}//setIsSelected()//
/**
* Sets the association container used to access the text.
* @param container The text association metadata.
*/
public void setTextAssociation(SingleAssociationContainer container) {
verifyThread();
this.text.setAssociations(container);
}//setTextAssociation()//
/**
* Sets the association container used to access the image.
* @param container The image association metadata.
*/
public void setImageAssociation(SingleAssociationContainer container) {
verifyThread();
this.image.setAssociations(container);
}//setImageAssociation()//
/**
* Sets the association container used to access the hot image.
* @param container The hot image association metadata.
*/
public void setHotImageAssociation(SingleAssociationContainer container) {
verifyThread();
this.hotImage.setAssociations(container);
}//setHotImageAssociation()//
/**
* Sets the association container used to access the disabled image.
* @param container The disabled image association metadata.
*/
public void setDisabledImageAssociation(SingleAssociationContainer container) {
verifyThread();
this.disabledImage.setAssociations(container);
}//setDisabledImageAssociation()//
/**
* Sets the association container used to access the selection.
* @param container The selection association metadata.
*/
public void setSelectionAssociation(SingleAssociationContainer container) {
verifyThread();
this.selection.setAssociations(container);
}//setSelectionAssociation()//
/**
* Adds a link for the selection.
* @param link The local linkage for the selection.
*/
public void addSelectionLink(LinkData link) {
selectionLinkage.add(link);
}//addSelectionLink()//
/**
* Sets the selection method called when the button is pressed (intended only for push buttons).
* @param selectionMethod The method called when the button is pressed.
*/
public void setSelectionMethod(IMethodAssociation selectionMethod) {
verifyThread();
if(!isStateful) {
this.selectionMethod = selectionMethod;
}//if//
}//setSelectionMethod()//
/**
* Sets the component text.
* @param text The text that will appear in the component.
*/
public void setText(String text) {
verifyThread();
this.text.setDefaultValue(text);
}//setText()//
/**
* Sets the component's default text resource.
* @param text The text to be displayed by this component.
*/
public void setText(ResourceReference text) {
verifyThread();
this.text.setDefaultValue(text);
}//setText()//
/**
* Sets the component image.
* @param image The image to be displayed by the component.
*/
public void setImage(JefImage image) {
verifyThread();
this.image.setDefaultValue(image);
}//setImage()//
/**
* Sets the component's default image resource.
* @param image The image to be displayed by this component.
*/
public void setImage(ResourceReference image) {
verifyThread();
this.image.setDefaultValue(image);
}//setImage()//
/**
* Sets the component's disabled image.
* @param image The disabled image to be displayed by the component.
*/
public void setDisabledImage(JefImage image) {
verifyThread();
this.disabledImage.setDefaultValue(image);
}//setDisabledImage()//
/**
* Sets the component's default disabled image resource.
* @param image The disabled image to be displayed by this component.
*/
public void setDisabledImage(ResourceReference image) {
verifyThread();
this.disabledImage.setDefaultValue(image);
}//setDisabledImage()//
/**
* Sets the component's hot image.
* @param image The hot image to be displayed by the component.
*/
public void setHotImage(JefImage image) {
verifyThread();
this.hotImage.setDefaultValue(image);
}//setHotImage()//
/**
* Sets the component's default hot image resource.
* @param image The hot image to be displayed by this component.
*/
public void setHotImage(ResourceReference image) {
verifyThread();
this.hotImage.setDefaultValue(image);
}//setHotImage()//
/**
* Sets whether the control auto synchronizes the selected state of the button.
* @param autoSynchronizeSelection Whether the button state is automatically synchronized.
*/
public void setAutoSynchronizeSelection(boolean autoSynchronizeSelection) {
if(isStateful) {
this.autoSynchronizeSelection = autoSynchronizeSelection;
}//if//
}//setAutoSynchronizeSelection()//
/**
* Sets the delay for the auto synchronize selection.
* @param autoSynchronizeSelectionDelay The delay in terms of milliseconds between the value of zero and ten thousand. A zero value has no delay.
*/
public void setAutoSynchronizeSelectionDelay(long autoSynchronizeSelectionDelay) {
if(autoSynchronizeSelectionDelay < 0) {
autoSynchronizeSelectionDelay = 0;
}//if//
else if(autoSynchronizeSelectionDelay > 10000) {
autoSynchronizeSelectionDelay = 10000;
}//else if//
this.autoSynchronizeSelectionDelay = autoSynchronizeSelectionDelay;
}//setAutoSynchronizeSelectionDelay()//
/**
* Sets the control used by the tool item.
* @param control The tool item's control.
*/
public void setControl(Component control) {
this.control = control;
}//setControl()//
/**
* Sets the popup menu used by the tool item.
* @param menu The tool item's popup menu.
*/
public void setMenu(Menu menu) {
this.menu = menu;
}//setMenu()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnLinkInvoked(int, java.lang.Object)
*/
protected void internalOnLinkInvoked(int linkTarget, Object data) {
switch(linkTarget) {
case LINK_TARGET_SELECTION: {
boolean isSelected = data instanceof Boolean ? ((Boolean) data).booleanValue() : false;
if(isStateful) {
if(isSelected != getSwtToolItem().getSelection()) {
getSwtToolItem().setSelection(isSelected);
selectionChanged(isSelected);
}//if//
}//if//
else {
selectionChanged(true);
}//else//
break;
}//case//
case LINK_TARGET_IMAGE: {
if(getSwtToolItem().getImage() != null) {
getSwtToolItem().getImage().dispose();
}//if//
getSwtToolItem().setImage(data instanceof JefImage ? SwtUtilities.getImage(getSwtToolItem().getDisplay(), (JefImage) data) : null);
resize();
break;
}//case//
case LINK_TARGET_DISABLED_IMAGE: {
if(getSwtToolItem().getDisabledImage() != null) {
getSwtToolItem().getDisabledImage().dispose();
}//if//
getSwtToolItem().setDisabledImage(data instanceof JefImage ? SwtUtilities.getImage(getSwtToolItem().getDisplay(), (JefImage) data) : null);
resize();
break;
}//case//
case LINK_TARGET_ROLLOVER_IMAGE: {
if(getSwtToolItem().getHotImage() != null) {
getSwtToolItem().getHotImage().dispose();
}//if//
getSwtToolItem().setHotImage(data instanceof JefImage ? SwtUtilities.getImage(getSwtToolItem().getDisplay(), (JefImage) data) : null);
resize();
break;
}//case//
case LINK_TARGET_TEXT: {
getSwtToolItem().setText(data instanceof String ? (String) data : "");
resize();
break;
}//case//
default: {
super.internalOnLinkInvoked(linkTarget, data);
break;
}//default//
}//switch//
}//internalOnLinkInvoked()//
}//ToolItem//
/**
* ToolBar constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_FLAT
*/
public ToolBar(Container parent, String name, int style) {
super(parent, name, style);
}//ToolBar()//
/**
* Adds a tool item to the bar.
* @param toolItem The item to be added.
*/
protected void addToolItem(AbstractToolItem toolItem) {
toolItems.add(toolItem);
if(isInitialized()) {
//TODO: Initialize the tool item.
//Will the tool item's component already be initilialized?
//Would this ever occur?
}//if//
}//addToolItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.ToolBar(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT tool bar that represents this tool bar.
* @return The SWT tool bar providing visualization for this tool bar.
*/
public org.eclipse.swt.widgets.ToolBar getSwtToolBar() {
return (org.eclipse.swt.widgets.ToolBar) getSwtControl();
}//getSwtToolBar()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
//Add a listener to force the view to re-layout when the toolbar changes sizes (expands or contracts).//
getSwtToolBar().addListener(SWT.Resize, new Listener() {
public void handleEvent(Event event) {
getSwtToolBar().getParent().layout(true, true);
getSwtToolBar().getParent().redraw();
}//handleEvent()//
});
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitializeAll()
*/
public void internalViewInitializeAll() {
super.internalViewInitializeAll();
//Initialize all the tool items.//
for(int index = 0; index < toolItems.getSize(); index++) {
((AbstractToolItem) toolItems.get(index)).internalViewInitialize();
}//for//
//Initialize all the menus.//
for(int index = 0; index < menus.getSize(); index++) {
((Menu) menus.get(index)).internalViewInitializeAll();
}//for//
}//internalViewInitializeAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewReleaseAll()
*/
public void internalViewReleaseAll() {
//Release all the tool items.//
for(int index = 0; index < toolItems.getSize(); index++) {
((AbstractToolItem) toolItems.get(index)).internalViewRelease();
}//for//
//Release all the menus.//
for(int index = 0; index < menus.getSize(); index++) {
((Menu) menus.get(index)).internalViewReleaseAll();
}//for//
super.internalViewReleaseAll();
}//internalViewReleaseAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefreshAll()
*/
public void internalViewRefreshAll() {
super.internalViewRefreshAll();
//Refresh all the tool items.//
for(int index = 0; index < toolItems.getSize(); index++) {
((AbstractToolItem) toolItems.get(index)).internalViewRefresh();
}//for//
//Refresh all the menus.//
for(int index = 0; index < menus.getSize(); index++) {
((Menu) menus.get(index)).internalViewRefreshAll();
}//for//
}//internalViewRefreshAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronizeAll()
*/
public void internalViewSynchronizeAll() {
//Synchronize all the tool items.//
for(int index = 0; index < toolItems.getSize(); index++) {
((AbstractToolItem) toolItems.get(index)).internalViewSynchronize();
}//for//
//Synchronize all the menus.//
for(int index = 0; index < menus.getSize(); index++) {
((Menu) menus.get(index)).internalViewSynchronizeAll();
}//for//
super.internalViewSynchronizeAll();
}//internalViewSynchronizeAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#setMenu(com.foundation.view.swt.Menu)
*/
public void setMenu(Menu menu) {
verifyThread();
menus.add(menu);
//A tool bar can have multiple menus associated with it. Each menu is tied to a drop down tool item. Since the tool item is not a control, the menu is linked to the bar instead.//
if((isInitialized()) && (menu != null)) {
menu.internalViewInitializeAll();
}//if//
}//setMenu()//
}//ToolBar//

View File

@@ -0,0 +1,832 @@
/*
* Copyright (c) 2006,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import com.foundation.view.swt.layout.GridData;
import com.foundation.view.swt.layout.GridLayout;
import org.eclipse.swt.widgets.ColorDialog;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import com.common.comparison.Comparator;
import com.foundation.view.JefColor;
import com.foundation.view.LinkData;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
import com.foundation.view.resource.ResourceReference;
import com.foundation.view.swt.ToolBar.AbstractToolItem;
import com.foundation.view.swt.util.SwtUtilities;
public class ToolItemDropColor extends AbstractToolItem implements SelectionListener {
public static final int LINK_TARGET_SELECTION = AbstractToolItem.LAST_LINK_TARGET + 1;
public static final int LINK_TARGET_TEXT = AbstractToolItem.LAST_LINK_TARGET + 2;
public static final int LINK_TARGET_IMAGE = AbstractToolItem.LAST_LINK_TARGET + 3;
public static final int LINK_TARGET_DISABLED_IMAGE = AbstractToolItem.LAST_LINK_TARGET + 4;
public static final int LINK_TARGET_ROLLOVER_IMAGE = AbstractToolItem.LAST_LINK_TARGET + 5;
public static final int LAST_LINK_TARGET = AbstractToolItem.LAST_LINK_TARGET + 5;
/** The item's selection state resource. */
private SingleResourceAssociation selection = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_COLOR, true, null);
/** The linkage for the selected color. */
private Linkage colorLinkage = new Linkage();
/** Whether the selection state is auto synchronized. */
private boolean autoSynchronizeSelection = true;
/** The width for the color swatch image. */
private int width = 17;
/** The height for the color swatch image. */
private int height = 17;
/** The color used if no color is selected. This should be null if no color is a valid option. */
private JefColor defaultColor = null;
/** The currently selected color. */
private JefColor selectedColor = null;
/** The currently selected color image. */
private Image selectedColorImage = null;
/** The drop down display. */
private DropDown dropDown = null;
/**
* The drop down display allowing the user to select from a palette of colors.
*/
private class DropDown implements MouseTrackListener, MouseListener, ShellListener {
private static final String STANDARD = "standard";
private static final String SELECTED = "selected";
private static final String HOVER = "hover";
private static final String COLOR = "color";
private static final int imageSize = 10;
private static final int labelSize = 16; //(labelSize - imageSize) must be evenly dividable by 2.//
private static final int imageBorder = (labelSize - imageSize) >> 1;
private static final int columns = 8;
private static final int rows = 5;
private final JefColor[][] colors = new JefColor[][] {
{new JefColor(0, 0, 0), new JefColor(128, 0, 0), new JefColor(255, 0, 0), new JefColor(255, 0, 255), new JefColor(255, 153, 204)},
{new JefColor(153, 51, 0), new JefColor(255, 102, 0), new JefColor(255, 153, 0), new JefColor(255, 204, 0), new JefColor(255, 204, 153)},
{new JefColor(51, 51, 0), new JefColor(128, 128, 0), new JefColor(0, 153, 204), new JefColor(255, 255, 0), new JefColor(255, 255, 203)},
{new JefColor(0, 51, 0), new JefColor(0, 128, 0), new JefColor(51, 153, 102), new JefColor(0, 255, 0), new JefColor(204, 255, 204)},
{new JefColor(0, 51, 102), new JefColor(0, 128, 128), new JefColor(51, 204, 204), new JefColor(0, 255, 255), new JefColor(204, 255, 255)},
{new JefColor(0, 0, 128), new JefColor(0, 0, 255), new JefColor(51, 102, 255), new JefColor(0, 204, 255), new JefColor(153, 204, 255)},
{new JefColor(51, 51, 153), new JefColor(102, 102, 153), new JefColor(128, 0, 128), new JefColor(153, 51, 102), new JefColor(204, 153, 255)},
{new JefColor(51, 51, 51), new JefColor(128, 128, 128), new JefColor(153, 153, 153), new JefColor(192, 192, 192), new JefColor(255, 255, 255)},
};
private final JefColor outerBorderColor = new JefColor(0, 0, 255, 255);
private final JefColor innerBorderColor = new JefColor(92, 92, 92);
private final JefColor hoverFillColor = new JefColor(0, 0, 255, 42);
private final JefColor selectedFillColor = new JefColor(0, 0, 255, 72);
private final JefColor noColor = new JefColor(255, 255, 255, 0);
private Shell dropShell = new Shell(SWT.NO_TRIM | SWT.TOOL | SWT.ON_TOP | SWT.NO_FOCUS);
private Label noColorLabel = null;
private Label moreLabel = null;
private Label[][] colorLabels = new Label[columns][rows];
private JefColor selectedColor = null;
private boolean isMouseDown = false;
private Label mouseDownLabel = null;
private Label mouseOverLabel = null;
private Label selectedLabel = null;
/**
* DropDown constructor.
*/
public DropDown() {
GridLayout gridLayout = new GridLayout(8, false);
GridData gridData;
int totalWidth = columns * labelSize;
gridLayout.horizontalSpacing = 0;
gridLayout.verticalSpacing = 0;
gridLayout.marginHeight = 0;
gridLayout.marginWidth = 0;
gridLayout.marginRight = 0;
gridLayout.marginBottom = 0;
dropShell.setLayout(gridLayout);
dropShell.setBackgroundMode(SWT.INHERIT_FORCE);
dropShell.setBackground(SwtUtilities.getColor(dropShell.getDisplay(), noColor));
if(defaultColor == null) {
gridData = new GridData(SWT.FILL, SWT.CENTER, false, false, 8, 1);
gridData.minimumHeight = labelSize;
gridData.heightHint = labelSize;
noColorLabel = new Label(dropShell, SWT.NONE);
noColorLabel.setText("None");
noColorLabel.setAlignment(SWT.CENTER);
noColorLabel.setLayoutData(gridData);
noColorLabel.setVisible(true);
noColorLabel.setData(STANDARD, createColorImage(totalWidth, labelSize, imageBorder, noColor, null, null, null));
noColorLabel.setData(HOVER, createColorImage(totalWidth, labelSize, imageBorder, hoverFillColor, null, outerBorderColor, hoverFillColor));
noColorLabel.setData(SELECTED, createColorImage(totalWidth, labelSize, imageBorder, selectedFillColor, null, outerBorderColor, selectedFillColor));
noColorLabel.setData(COLOR, null);
noColorLabel.addMouseListener(this);
noColorLabel.addMouseTrackListener(this);
}//if//
for(int y = 0; y < rows; y++) {
for(int x = 0; x < columns; x++) {
Label colorLabel = new Label(dropShell, SWT.NONE);
gridData = new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1);
gridData.minimumWidth = labelSize;
gridData.minimumHeight = labelSize;
colorLabel.setLayoutData(gridData);
colorLabel.setData(STANDARD, createColorImage(labelSize, labelSize, imageBorder, colors[x][y], innerBorderColor, null, null));
colorLabel.setData(HOVER, createColorImage(labelSize, labelSize, imageBorder, colors[x][y], innerBorderColor, outerBorderColor, hoverFillColor));
colorLabel.setData(SELECTED, createColorImage(labelSize, labelSize, imageBorder, colors[x][y], innerBorderColor, outerBorderColor, selectedFillColor));
colorLabel.setData(COLOR, colors[x][y]);
colorLabel.setImage((Image) colorLabel.getData(STANDARD));
colorLabels[x][y] = colorLabel;
colorLabel.addMouseListener(this);
colorLabel.addMouseTrackListener(this);
}//for//
}//for//
gridData = new GridData(SWT.FILL, SWT.CENTER, false, false, 8, 1);
gridData.minimumHeight = labelSize;
gridData.heightHint = labelSize;
moreLabel = new Label(dropShell, SWT.NONE);
moreLabel.setBackground(SwtUtilities.getColor(dropShell.getDisplay(), noColor));
moreLabel.setText("More...");
moreLabel.setAlignment(SWT.CENTER);
moreLabel.setLayoutData(gridData);
moreLabel.setData(STANDARD, createColorImage(totalWidth, labelSize, imageBorder, noColor, null, null, null));
moreLabel.setData(HOVER, createColorImage(totalWidth, labelSize, imageBorder, hoverFillColor, null, outerBorderColor, hoverFillColor));
moreLabel.setData(SELECTED, createColorImage(totalWidth, labelSize, imageBorder, selectedFillColor, null, outerBorderColor, selectedFillColor));
moreLabel.setData(COLOR, null);
moreLabel.addMouseListener(this);
moreLabel.addMouseTrackListener(this);
dropShell.addMouseTrackListener(this);
dropShell.addMouseListener(this);
dropShell.addShellListener(this);
dropShell.layout(true, true);
dropShell.pack(true);
}//DropDown()//
/**
* Disposes of all resources associated with this drop down.
*/
public void dispose() {
if((noColorLabel != null) && (!noColorLabel.isDisposed())) {
((Image) noColorLabel.getData(SELECTED)).dispose();
((Image) noColorLabel.getData(HOVER)).dispose();
((Image) noColorLabel.getData(STANDARD)).dispose();
noColorLabel.dispose();
}//if//
for(int y = 0; y < rows; y++) {
for(int x = 0; x < columns; x++) {
if((colorLabels[x][y] != null) && (!colorLabels[x][y].isDisposed())) {
((Image) colorLabels[x][y].getData(SELECTED)).dispose();
((Image) colorLabels[x][y].getData(HOVER)).dispose();
((Image) colorLabels[x][y].getData(STANDARD)).dispose();
colorLabels[x][y].dispose();
}//if//
}//for//
}//for//
if((moreLabel != null) && (!moreLabel.isDisposed())) {
((Image) moreLabel.getData(SELECTED)).dispose();
((Image) moreLabel.getData(HOVER)).dispose();
((Image) moreLabel.getData(STANDARD)).dispose();
moreLabel.dispose();
}//if//
if((dropShell != null) && (!dropShell.isDisposed())) {
dropShell.dispose();
}//if//
}//dispose()//
/**
* Opens the color dialog allowing the user to choose from a wider range of colors.
*/
protected void openColorDialog() {
ColorDialog dialog = new ColorDialog(getShell(), 0);
RGB result = null;
dialog.setText("Colors");
dialog.setRGB(selectedColor != null ? new RGB(selectedColor.getRed() & 0xFF, selectedColor.getGreen() & 0xFF, selectedColor.getBlue() & 0xFF) : new RGB(255, 255, 255));
result = dialog.open();
if(result != null) {
setSelectedColor(new JefColor(result.red, result.green, result.blue), true);
}//if//
}//openColorDialog()//
/**
* Shows the drop down at the given location with the given color selected.
* @param location The location to display the shell in screen coordinates.
* @param selectedColor The color to be selected.
*/
public void show(Point location, JefColor selectedColor) {
//Set the initial selection.//
this.selectedColor = selectedColor;
//Reset the images for the labels.//
setLabelImage(noColorLabel, (Image) noColorLabel.getData(STANDARD));
setLabelImage(moreLabel, (Image) moreLabel.getData(STANDARD));
//Reset the images for the color labels.//
for(int y = 0; y < rows; y++) {
for(int x = 0; x < columns; x++) {
setLabelImage(colorLabels[x][y], (Image) colorLabels[x][y].getData(STANDARD));
}//for//
}//for//
//Select the currently selected label if there is one.//
if(selectedColor == null) {
noColorLabel.setBackgroundImage((Image) noColorLabel.getData(SELECTED));
selectedLabel = noColorLabel;
}//if//
else {
selectedLabel = null;
for(int y = 0; (selectedLabel == null) && (y < rows); y++) {
for(int x = 0; (selectedLabel == null) && (x < columns); x++) {
if(Comparator.equals(selectedColor, colors[x][y])) {
colorLabels[x][y].setImage((Image) colorLabels[x][y].getData(SELECTED));
selectedLabel = colorLabels[x][y];
}//if//
}//for//
}//for//
}//else//
dropShell.setLocation(location);
dropShell.setVisible(true);
dropShell.setActive();
}//show()//
/**
* Hides the drop down shell.
* @param synchronize Whether the selection changes should be synchronized.
*/
public void hide(boolean synchronize) {
if(synchronize) {
setSelectedColor(selectedColor, true);
}//if//
dropShell.setVisible(false);
}//hide()//
/**
* Sets the image for the label.
* @param label The label.
* @param image The label's image.
*/
private void setLabelImage(Label label, Image image) {
if((label == moreLabel) || (label == noColorLabel)) {
label.setBackgroundImage(image);
}//if//
else {
label.setImage(image);
}//else//
}//setLabelImage()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseTrackListener#mouseHover(org.eclipse.swt.events.MouseEvent)
*/
public void mouseHover(MouseEvent event) {
}//mouseHover()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseTrackListener#mouseExit(org.eclipse.swt.events.MouseEvent)
*/
public void mouseExit(MouseEvent event) {
if(event.widget instanceof Label) {
Label label = (Label) event.widget;
if(mouseOverLabel == label) {
if(selectedLabel != label) {
//Change the control's image back to the standard image.//
setLabelImage(label, (Image) label.getData(STANDARD));
}//if//
mouseOverLabel = null;
}//if//
}//if//
}//mouseExit()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseTrackListener#mouseEnter(org.eclipse.swt.events.MouseEvent)
*/
public void mouseEnter(MouseEvent event) {
if(!isMouseDown) {
if(event.widget instanceof Label) {
Label label = (Label) event.widget;
if(mouseOverLabel != label) {
if(mouseOverLabel != null) {
if(selectedLabel != mouseOverLabel) {
setLabelImage(mouseOverLabel, (Image) mouseOverLabel.getData(STANDARD));
}//if//
mouseOverLabel = null;
}//if//
if(selectedLabel != label) {
//Change the control's image to the hover image.//
setLabelImage(label, (Image) label.getData(HOVER));
mouseOverLabel = label;
}//if//
}//if//
}//if//
}//if//
}//mouseEnter()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
*/
public void mouseUp(MouseEvent event) {
if(event.widget instanceof Label) {
Label label = (Label) event.widget;
if(label == mouseDownLabel) {
if(label == moreLabel) {
setLabelImage(label, (Image) label.getData(HOVER));
//Open the more dialog.//
hide(false);
openColorDialog();
}//if//
else {
if(label != selectedLabel) {
if(selectedLabel != null) {
setLabelImage(selectedLabel, (Image) selectedLabel.getData(STANDARD));
}//if//
selectedColor = (JefColor) label.getData(COLOR);
selectedLabel = label;
}//if//
}//else//
}//if//
}//if//
isMouseDown = false;
mouseDownLabel = null;
}//mouseUp()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
*/
public void mouseDown(MouseEvent event) {
isMouseDown = true;
if(event.widget instanceof Label) {
Label label = (Label) event.widget;
if((label != selectedLabel) || (label == moreLabel)) {
//Set the selection, but don't close the view.//
setLabelImage(label, (Image) label.getData(SELECTED));
}//if//
mouseDownLabel = label;
}//if//
}//mouseDown()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
*/
public void mouseDoubleClick(MouseEvent event) {
if(event.widget instanceof Label) {
Label label = (Label) event.widget;
//Clear the selected label's highlighting.//
if(selectedLabel != label) {
setLabelImage(selectedLabel, (Image) selectedLabel.getData(STANDARD));
}//if//
if(label == moreLabel) {
label.setBackgroundImage((Image) label.getData(HOVER));
//Open the more dialog.//
hide(false);
openColorDialog();
}//if//
else {
selectedColor = (JefColor) label.getData(COLOR);
hide(true);
}//else//
}//if//
}//mouseDoubleClick()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellActivated(org.eclipse.swt.events.ShellEvent)
*/
public void shellActivated(ShellEvent event) {
}//shellActivated()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellClosed(org.eclipse.swt.events.ShellEvent)
*/
public void shellClosed(ShellEvent event) {
}//shellClosed()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellDeactivated(org.eclipse.swt.events.ShellEvent)
*/
public void shellDeactivated(ShellEvent event) {
hide(true);
}//shellDeactivated()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellDeiconified(org.eclipse.swt.events.ShellEvent)
*/
public void shellDeiconified(ShellEvent event) {
}//shellDeiconified()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellIconified(org.eclipse.swt.events.ShellEvent)
*/
public void shellIconified(ShellEvent event) {
}//shellIconified()//
}//DropDown//
/**
* ToolItemDropColor constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
*/
public ToolItemDropColor(Container parent, String name, int style) {
super(parent, style);
}//ToolItemDropColor()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractComponent#getName()
*/
public String getName() {
return "__ToolItem:DropColor__";
}//getName()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
getSwtToolItem().addSelectionListener(this);
super.internalViewInitialize();
selection.initialize();
dropDown = new DropDown();
//Set an initial image.//
selectedColorImage = createColorImage(selectedColor);
getSwtToolItem().setImage(selectedColorImage);
//Setup listeners to close the drop down when appropriate.//
TraverseListener traverseListener = new TraverseListener() {
public void keyTraversed(TraverseEvent event) {
switch(event.detail) {
case SWT.TRAVERSE_RETURN:
case SWT.TRAVERSE_TAB_PREVIOUS:
case SWT.TRAVERSE_TAB_NEXT:
case SWT.TRAVERSE_ARROW_PREVIOUS:
case SWT.TRAVERSE_PAGE_PREVIOUS:
case SWT.TRAVERSE_PAGE_NEXT:
if(isShowingDrop()) {
hideDrop(true);
event.doit = true;
}//if//
break;
case SWT.TRAVERSE_ESCAPE:
if(isShowingDrop()) {
hideDrop(false);
event.doit = false;
}//if//
break;
default:
break;
}//switch//
}//keyTraversed()//
};
//Add a listener to the shells to hide the drop down shell if a traveral event occurs.//
getShell().addTraverseListener(traverseListener);
dropDown.dropShell.addTraverseListener(traverseListener);
//Hide the drop shell if the user clicks outside of the drop down.//
getShell().getDisplay().addFilter(SWT.MouseDown, new Listener() {
public void handleEvent(Event event) {
if(isShowingDrop()) {
if(event.widget instanceof Control) {
Control control = (Control) event.widget;
//If the mouse event occured outside the drop shell then close the drop shell.//
if(!dropDown.dropShell.getBounds().contains(getShell().getDisplay().map(control, null, event.x, event.y))) {
hideDrop(true);
event.type = 0;
}//if//
}//if//
}//if//
}//handleEvent//
});
//if the outer most shell is deactivated or iconified, then stop showing the drop down shell.//
getShell().addShellListener(new ShellListener() {
public void shellActivated(ShellEvent event) {
}//shellActivated()//
public void shellClosed(ShellEvent event) {
}//shellClosed()//
public void shellDeactivated(ShellEvent event) {
if(!getSwtToolItem().isDisposed()) {
getShell().getDisplay().asyncExec(new Runnable() {
public void run() {
if((isShowingDrop()) && (dropDown.dropShell != getShell().getDisplay().getActiveShell())) {
getShell().setActive();
hideDrop(true);
}//if//
}//run()//
});
}//if//
}//shellDeactivated()//
public void shellDeiconified(ShellEvent event) {
}//shellDeiconified()//
public void shellIconified(ShellEvent event) {
if(isShowingDrop()) {
hideDrop(false);
}//if//
}//shellIconified()//
});
getShell().addControlListener(new ControlListener() {
public void controlMoved(ControlEvent event) {
if(isShowingDrop()) {
hideDrop(false);
}//if//
}//controlMoved()//
public void controlResized(ControlEvent event) {
if(isShowingDrop()) {
hideDrop(false);
}//if//
}//controlResized()//
});
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
if(getSwtToolItem() != null && !getSwtToolItem().isDisposed()) {
getSwtToolItem().removeSelectionListener(this);
}//if//
super.internalViewRelease();
selection.release();
dropDown.dispose();
if((selectedColorImage != null) && (!selectedColorImage.isDisposed())) {
selectedColorImage.dispose();
selectedColorImage = null;
}//if//
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalViewRefreshSelection();
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
super.internalViewSynchronize();
if(!autoSynchronizeSelection) {
selection.setValue(selectedColor);
}//if//
}//internalViewSynchronize()//
/**
* Refreshes the color selection.
*/
protected void internalViewRefreshSelection() {
if(selection.refresh()) {
JefColor selectedColor = (JefColor) selection.getValue();
setSelectedColor(selectedColor, false);
}//if//
}//internalViewRefreshSelection()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent event) {
widgetSelected(event);
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent event) {
if(event.detail == SWT.ARROW) {
Rectangle rect = getSwtToolItem().getBounds();
Point point = new Point(rect.x, rect.y + rect.height);
//Show the drop down menu.//
point = getSwtToolItem().getParent().toDisplay(point);
dropDown.show(point, selectedColor);
}//if//
}//widgetSelected()//
/**
* Creates a color swatch image for the required color.
* @param color The color to generate an image for, or null for an image of no color (a red slash or other appropriate graphic).
* @return The color swatch image.
*/
protected Image createColorImage(JefColor swatchColor) {
return createColorImage(width, height, 0, swatchColor, null, null, null);
}//createColorImage()//
/**
* Creates a color swatch image for the required color.
* @param width The number of pixels across the whole image.
* @param height The number of pixels down the whole image.
* @param fillBorder The number of pixels of filler border around the swatch.
* @param swatchColor The color to generate an image for, or null for an image of no color (a red slash or other appropriate graphic).
* @param innerBorderColor The color of the border around the swatch. This is a one pixel border if this is non null.
* @param outerBorderColor The color of the border around the whole image. This is a one pixel border if this is non-null.
* @param fillColor The color of the fill between the swatch and the edges of the image. This should likely be a semi-transparent color.
* @return The color swatch image.
*/
protected Image createColorImage(int width, int height, int fillBorder, JefColor swatchColor, JefColor innerBorderColor, JefColor outerBorderColor, JefColor fillColor) {
Image image = new Image(getSwtToolItem().getDisplay(), width, height);
GC gc = new GC(image);
int swatchX = fillBorder;
int swatchY = fillBorder;
int swatchWidth = width - (fillBorder << 1) - 1;
int swatchHeight = height - (fillBorder << 1) - 1;
//Draw the fill.//
if(fillColor != null) {
Color swtColor = SwtUtilities.getColor(image.getDevice(), fillColor);
gc.setAlpha(fillColor.getAlpha() & 0xFF);
gc.setBackground(swtColor);
gc.fillRectangle(0, 0, width - 1, height - 1);
swtColor.dispose();
}//if//
else {
gc.setAlpha(0);
gc.fillRectangle(0, 0, width, height);
}//else//
//Draw the outer border.//
if(outerBorderColor != null) {
Color swtColor = SwtUtilities.getColor(image.getDevice(), outerBorderColor);
gc.setLineWidth(1);
gc.setForeground(swtColor);
gc.setAlpha(outerBorderColor.getAlpha() & 0xFF);
gc.drawRectangle(0, 0, width - 1, height - 1);
swtColor.dispose();
}//if//
//Draw the swatch.//
if(swatchColor == null) {
Color swtColor = SwtUtilities.getColor(image.getDevice(), new JefColor(JefColor.COLOR_RED));
gc.setAlpha(255);
gc.setForeground(swtColor);
gc.setLineWidth(2);
gc.setLineCap(SWT.CAP_ROUND);
gc.drawLine(width - (fillBorder << 1), fillBorder, fillBorder, height - (fillBorder << 1));
swtColor.dispose();
}//if//
else if((swatchColor.getAlpha() & 0xFF) != 0) {
Color swtColor = SwtUtilities.getColor(image.getDevice(), swatchColor);
gc.setAlpha(swatchColor.getAlpha() & 0xFF);
gc.setBackground(swtColor);
gc.fillRectangle(swatchX, swatchY, swatchWidth, swatchHeight);
swtColor.dispose();
}//else if//
//Draw the inner border.//
if(innerBorderColor != null) {
Color swtColor = SwtUtilities.getColor(image.getDevice(), innerBorderColor);
gc.setLineWidth(1);
gc.setForeground(swtColor);
gc.setAlpha(innerBorderColor.getAlpha() & 0xFF);
gc.drawRectangle(swatchX, swatchY, swatchWidth, swatchHeight);
swtColor.dispose();
}//if//
gc.dispose();
return image;
}//createColorImage()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == selection) {
internalViewRefreshSelection();
}//if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/**
* Sets the color image width.
* @param width The width of the image in the tool item.
*/
public void setWidth(int width) {
this.width = width;
}//setWidth()//
/**
* Sets the color image height.
* @param height The height of the image in the tool item.
*/
public void setHeight(int height) {
this.height = height;
}//setHeight()//
/**
* Sets the currently selected color, displays the color, and updates any linkages.
* @param selectedColor The color to be selected.
* @param updateModel Whether the model should be updated. This should only be false if being called due to a model change.
*/
protected void setSelectedColor(JefColor selectedColor, boolean updateModel) {
if(selectedColor == null) {
selectedColor = defaultColor;
}//if//
if(!Comparator.equals(this.selectedColor, selectedColor)) {
this.selectedColor = selectedColor;
if(isInitialized()) {
//Dispose of the old color image.//
if(selectedColorImage != null) {
getSwtToolItem().setImage(null);
selectedColorImage.dispose();
}//if//
selectedColorImage = createColorImage(selectedColor);
getSwtToolItem().setImage(selectedColorImage);
if(updateModel && autoSynchronizeSelection) {
selection.setValue(selectedColor);
}//if//
}//if//
colorLinkage.invoke(selectedColor);
}//if//
}//setSelectedColor()//
/**
* Sets the association container used to access the selection.
* @param container The selection association metadata.
*/
public void setSelectionAssociation(SingleAssociationContainer container) {
verifyThread();
this.selection.setAssociations(container);
}//setSelectionAssociation()//
/**
* Adds a link for the selected color.
* @param link The local linkage for the selected color.
*/
public void addColorLink(LinkData link) {
colorLinkage.add(link);
}//addColorLink()//
/**
* Sets the selected color.
* @param color The color selected.
*/
public void setColor(JefColor color) {
verifyThread();
this.selection.setDefaultValue(color);
}//setColor()//
/**
* Sets the selected color.
* @param color The color resource reference.
*/
public void setColor(ResourceReference color) {
this.selection.setDefaultValue(color);
}//setColor()//
/**
* Sets whether the control auto synchronizes the selected state of the button.
* @param autoSynchronizeSelection Whether the button state is automatically synchronized.
*/
public void setAutoSynchronizeSelection(boolean autoSynchronizeSelection) {
if(isStateful) {
this.autoSynchronizeSelection = autoSynchronizeSelection;
}//if//
}//setAutoSynchronizeSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnLinkInvoked(int, java.lang.Object)
*/
protected void internalOnLinkInvoked(int linkTarget, Object data) {
switch(linkTarget) {
case LINK_TARGET_SELECTION: {
JefColor color = data instanceof JefColor ? (JefColor) data : null;
setSelectedColor(color, true);
break;
}//case//
default: {
super.internalOnLinkInvoked(linkTarget, data);
break;
}//default//
}//switch//
}//internalOnLinkInvoked()//
/**
* Determines whether the drop down shell is currently being shown.
* @return Whether we are currently showing the drop control.
*/
protected boolean isShowingDrop() {
return dropDown != null && dropDown.dropShell.isVisible();
}//isShowingDrop()//
/**
* Shows the drop down shell.
*/
protected final void showDrop(Point location) {
if(!isShowingDrop()) {
dropDown.show(location, selectedColor);
}//if//
}//showDrop()//
/**
* Hides the drop down shell.
* @param synchronize Whether the drop control should synchronize its data with the tool item.
*/
protected final void hideDrop(boolean synchronize) {
if(isShowingDrop()) {
dropDown.hide(synchronize);
}//if//
}//hideDrop()//
}//ToolItemDropColor//

View File

@@ -0,0 +1,580 @@
/*
* Copyright (c) 2007,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MenuDetectEvent;
import org.eclipse.swt.events.MenuDetectListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import com.common.debug.Debug;
import com.common.thread.IRunnable;
import com.common.util.IIterator;
import com.common.util.IList;
import com.common.util.LiteList;
import com.foundation.controller.AbstractViewController;
import com.foundation.event.IRequestHandler;
import com.foundation.view.IAbstractComponent;
import com.foundation.view.IMethodAssociation;
import com.foundation.view.IView;
import com.foundation.view.IViewContext;
import com.foundation.view.JefImage;
import com.foundation.view.LinkData;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
import com.foundation.view.resource.AbstractResourceService;
import com.foundation.view.resource.ResourceReference;
import com.foundation.view.swt.AbstractComponent.Linkage;
import com.foundation.view.swt.AbstractComponent.Task;
public class TrayItem extends AbstractComponent implements IAbstractSwtContainer {
public static final int LINK_TARGET_IS_VISIBLE = AbstractComponent.LAST_LINK_TARGET + 1;
public static final int LINK_TARGET_TOOL_TIP_TEXT = AbstractComponent.LAST_LINK_TARGET + 2;
public static final int LAST_LINK_TARGET = AbstractComponent.LAST_LINK_TARGET + 2;
/** The component's name. This allows lookup of components in the view by the name. */
private String name = null;
/** The resource defining the visible state for the component. */
private SingleResourceAssociation isVisible = null;
/** The resource defining the tool tip text for the component. */
private SingleResourceAssociation toolTipText = null;
/** The container's image resource which may be used in different ways depending on the context (such as a frame icon, or a tab image). */
private SingleResourceAssociation image = null;
/** A holder for the value of the visibility flag. */
private ResourceHolder isVisibleHolder = new ResourceHolder(this);
/** A holder for the value of the tool tip text. */
private ResourceHolder toolTipTextHolder = new ResourceHolder(this);
/** A holder for the value of the image. */
private ResourceHolder imageHolder = new ResourceHolder(this);
/** The swt image currently used by the tray item. */
private Image swtImage = null;
/** The optional menu displayed when the SWT.MenuDetect event is fired by the TrayItem. */
private Menu menu = null;
/** The component's controller. */
private AbstractViewController controller = null;
/** A collection of components contained by this container. */
private IList components = new LiteList(10, 30);
/** A shell used only to support the menu used by the tray item. */
private Shell shell;
/** Called when the item is pressed. */
private IMethodAssociation selectionMethod = null;
/** The linkage for the selection. */
private Linkage selectionLinkage = new Linkage();
/**
* TrayItem default constructor.
* <p>Warning: This is only for use by the framework. This should never be called to create a useable instance.</p>
*/
public TrayItem() {
}//TrayItem()//
/**
* TrayItem constructor.
* @param viewContext The context under which this view component operates. For all but the outer most control this can be null.
* @param name The unique component name.
* @param style The style of control to construct.
*/
public TrayItem(IViewContext viewContext, String name, int style) {
super(null, viewContext, style, null);
initialize();
}//TrayItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.TrayItem(SwtViewContext.getSingleton().getDisplay().getSystemTray(), style));
getSwtWidget().setData(this);
shell = new Shell(SwtViewContext.getSingleton().getDisplay());
}//initializeControl()//
/**
* Initializes the component.
* <p>Note: This is separated so that a view can be instantiated via the default constructor for the purpose of determining the reflection metadata associated with the view. Any other call to the default constructor will create an invalid view.</p>
*/
private void initialize() {
isVisible = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_BOOLEAN, false, Boolean.TRUE);
toolTipText = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_TEXT, false, null);
image = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_IMAGE, false, null);
}//initialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#getResourceService()
*/
public AbstractResourceService getResourceService() {
return getController().getApplication().getResourceService();
}//getResourceService()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractContainer#addComponent(com.foundation.view.IAbstractComponent)
*/
public void addComponent(IAbstractComponent component) {
components.add((AbstractComponent) component);
}//addComponent()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractContainer#removeComponent(com.foundation.view.IAbstractComponent)
*/
public void removeComponent(IAbstractComponent component) {
components.remove((AbstractComponent) component);
}//removeComponent()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractContainer#getComponents()
*/
public IList getComponents() {
return components;
}//getComponents()//
/* (non-Javadoc)
* @see com.foundation.view.IView#layout()
*/
public void layout() {
//Does nothing.//
}//layout()//
/* (non-Javadoc)
* @see com.foundation.view.IView#getController()
*/
public AbstractViewController getController() {
return controller;
}//getController()//
/**
* Sets the container's associated controller.
* @param controller The controller for this container.
*/
public void setController(AbstractViewController controller) {
this.controller = controller;
}//setController()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#getShell()
*/
public Shell getShell() {
return shell;
}//getShell()//
/**
* Gets the system tray item encapsulated by this tray item component.
* @return The encapsulated tray item, or null if this tray item component does not have a viewable element.
*/
public org.eclipse.swt.widgets.TrayItem getSwtTrayItem() {
return (org.eclipse.swt.widgets.TrayItem) getSwtWidget();
}//getSwtTrayItem()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractComponent#getName()
*/
public String getName() {
return name;
}//getName()//
/**
* Adds a link for the selection.
* @param link The local linkage for the selection.
*/
public void addSelectionLink(LinkData link) {
selectionLinkage.add(link);
}//addSelectionLink()//
/**
* Sets the selection method called when the item is pressed.
* @param selectionMethod The method called when the tray item is pressed (left clicked).
*/
public void setSelectionMethod(IMethodAssociation selectionMethod) {
verifyThread();
this.selectionMethod = selectionMethod;
}//setSelectionMethod()//
/**
* Gets the menu used by the tray item, or null if one is not assigned.
* @return The optional menu for the tray item.
*/
public Menu getMenu() {
verifyThread();
return menu;
}//getMenuBar()//
/**
* Sets the component's popup or floating menu.
* @param menu The normally hidden menu that appears based on user interaction (usually a right click on a windows system).
*/
public void setMenu(Menu menu) {
verifyThread();
if(isInitialized() && this.menu != null) {
this.menu.internalViewReleaseAll();
this.menu = null;
}//if//
this.menu = menu;
if((isInitialized()) && (menu != null)) {
menu.internalViewInitializeAll();
}//if//
}//setMenu()//
/**
* Sets the association container used to access whether the control is visible.
* @param container The visible state association metadata.
*/
public void setIsVisibleAssociation(SingleAssociationContainer container) {
verifyThread();
this.isVisible.setAssociations(container);
}//setIsVisibleAssociation()//
/**
* Sets the association container used to access the tool tip text.
* @param container The tool tip association metadata.
*/
public void setToolTipTextAssociation(SingleAssociationContainer container) {
verifyThread();
this.toolTipText.setAssociations(container);
}//setToolTipTextAssociation()//
/**
* Sets the association container used to access the image.
* @param container The image association metadata.
*/
public void setImageAssociation(SingleAssociationContainer container) {
verifyThread();
this.image.setAssociations(container);
}//setImageAssociation()//
/**
* Sets whether the component is visible.
* @param isVisible Whether the user can see the component.
*/
public void setIsVisible(boolean isVisible) {
verifyThread();
this.isVisible.externalSetValue(isVisible ? Boolean.TRUE : Boolean.FALSE);
}//setIsVisible()//
/**
* Sets the default visibility.
* @param isVisible Whether the user can see the component if no other value is provided.
*/
public void setDefaultIsVisible(boolean isVisible) {
verifyThread();
this.isVisible.setDefaultValue(isVisible ? Boolean.TRUE : Boolean.FALSE);
}//setDefaultIsVisible()//
/**
* Sets the default visibility resource.
* @param isVisible Whether the user can see the component if no other value is provided.
*/
public void setDefaultIsVisible(ResourceReference isVisible) {
verifyThread();
this.isVisible.setDefaultValue(isVisible);
}//setDefaultIsVisible()//
/**
* Sets the component's default tool tip text.
* @param toolTipText The tool tip text to be displayed by this component.
*/
public void setDefaultToolTipText(String toolTipText) {
verifyThread();
this.toolTipText.setDefaultValue(toolTipText);
}//setDefaultToolTipText()//
/**
* Sets the component's default tool tip text resource.
* @param tooltipText The tool tip text to be displayed by this component.
*/
public void setDefaultToolTipText(ResourceReference toolTipText) {
verifyThread();
this.toolTipText.setDefaultValue(toolTipText);
}//setDefaultToolTipText()//
/**
* Sets the default image resource.
* @param image The image data that will be displayed by the tray.
*/
public void setDefaultImage(ResourceReference image) {
verifyThread();
this.image.setDefaultValue(image);
}//setDefaultImage()//
/**
* Sets the default image.
* @param image The image data that will be displayed by the tray.
*/
public void setDefaultImage(JefImage image) {
verifyThread();
this.image.setDefaultValue(image);
}//setDefaultImage()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
internalViewRefreshIsVisible();
internalViewRefreshToolTipText();
internalViewRefreshImage();
}//internalViewRefresh()//
/**
* Refreshes whether the component is visible based on the attribute value or if null the default flag value.
*/
protected void internalViewRefreshIsVisible() {
if(isVisible.refresh()) {
isVisibleHolder.setValue(isVisible.getValue());
}//if//
}//internalViewRefreshIsVisible()//
/**
* Refreshes the tool tip text from the tool tip text attribute and the default tool tip text.
*/
protected void internalViewRefreshToolTipText() {
if(toolTipText.refresh()) {
toolTipTextHolder.setValue(toolTipText.getValue());
}//if//
}//internalViewRefreshToolTipText()//
/**
* Refreshes the image.
*/
protected void internalViewRefreshImage() {
if(image.refresh()) {
imageHolder.setValue(image.getValue());
}//if//
}//internalViewRefreshImage()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefreshAll()
*/
public void internalViewRefreshAll() {
IIterator iterator = components.iterator();
//Refresh value holders.//
while(iterator.hasNext()) {
AbstractComponent component = (AbstractComponent) iterator.next();
if(component instanceof ValueHolder) {
component.internalViewRefreshAll();
}//if//
}//for//
if(getMenu() != null) {
getMenu().internalViewRefreshAll();
}//if//
super.internalViewRefreshAll();
}//internalViewRefreshAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronizeAll()
*/
public void internalViewSynchronizeAll() {
if(getMenu() != null) {
getMenu().internalViewSynchronizeAll();
}//if//
super.internalViewSynchronizeAll();
}//internalViewSynchronizeAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitializeAll()
*/
public void internalViewInitializeAll() {
IIterator iterator = components.iterator();
super.internalViewInitializeAll();
//Initialize contained value holders first.//
while(iterator.hasNext()) {
AbstractComponent component = (AbstractComponent) iterator.next();
if(component instanceof ValueHolder) {
component.internalViewInitializeAll();
}//if//
}//for//
if(menu != null) {
menu.internalViewInitializeAll();
}//if//
}//internalViewInitializeAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewReleaseAll()
*/
public void internalViewReleaseAll() {
IIterator iterator = new LiteList(getComponents()).iterator();
if(getMenu() != null) {
getMenu().internalViewReleaseAll();
}//if//
//Release sub-components.//
while(iterator.hasNext()) {
AbstractComponent component = (AbstractComponent) iterator.next();
component.internalViewReleaseAll();
}//for//
super.internalViewReleaseAll();
}//internalViewReleaseAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
getSwtTrayItem().addListener(SWT.MenuDetect, new Listener() {
public void handleEvent(Event event) {
if(menu != null) {
menu.getSwtMenu().setVisible(true);
}//if//
}//handleEvent()//
});
getSwtTrayItem().addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
if(selectionMethod != null) {
selectionMethod.invoke(new Object[] {new Integer(e.x), new Integer(e.y)}, true);
}//if//
else if(menu != null) {
menu.getSwtMenu().setVisible(true);
}//else if//
selectionLinkage.invoke(null);
}//widgetSelected()//
public void widgetDefaultSelected(SelectionEvent e) {
}//widgetDefaultSelected()//
});
isVisible.initialize();
toolTipText.initialize();
image.initialize();
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
destroyImage(swtImage);
isVisible.release();
toolTipText.release();
image.release();
toolTipTextHolder.release();
isVisibleHolder.release();
imageHolder.release();
if(getSwtTrayItem() != null && !getSwtTrayItem().isDisposed()) {
getSwtTrayItem().dispose();
}//if//
super.internalViewRelease();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnLinkInvoked(int, java.lang.Object)
*/
protected void internalOnLinkInvoked(int linkTarget, Object data) {
switch(linkTarget) {
case LINK_TARGET_IS_VISIBLE: {
getSwtTrayItem().setVisible(data != null && data instanceof Boolean ? ((Boolean) data).booleanValue() : false);
break;
}//case//
case LINK_TARGET_TOOL_TIP_TEXT: {
getSwtTrayItem().setToolTipText(data instanceof String ? (String) data : "");
break;
}//case//
default: {
super.internalOnLinkInvoked(linkTarget, data);
break;
}//default//
}//switch//
}//internalOnLinkInvoked()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == isVisible) {
internalViewRefreshIsVisible();
}//if//
else if(resourceAssociation == toolTipText) {
internalViewRefreshToolTipText();
}//else if//
else if(resourceAssociation == image) {
internalViewRefreshImage();
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalResourceHolderChanged(com.foundation.view.swt.ResourceHolder, java.lang.Object, java.lang.Object)
*/
protected void internalResourceHolderChanged(ResourceHolder resource, Object oldValue, Object newValue, int flags) {
if(resource == toolTipTextHolder) {
String value = (String) toolTipText.getValue();
//Set the control's tool tip text. This is normally enough, but some controls may need extra processing (hence the listeners).//
getSwtTrayItem().setToolTipText(value);
}//if//
else if(resource == imageHolder) {
destroyImage(swtImage);
swtImage = createImage((JefImage) imageHolder.getValue());
getSwtTrayItem().setImage(swtImage);
}//else if//
else if(resource == isVisibleHolder) {
if(!getSwtTrayItem().isDisposed()) {
getSwtTrayItem().setVisible(((Boolean) newValue).booleanValue());
}//if//
}//else if//
else {
super.internalResourceHolderChanged(resource, oldValue, newValue, flags);
}//else//
}//internalOnAssociationChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IAbstractSwtContainer#getSwtComposite()
*/
public Composite getSwtComposite() {
return null;
}//getSwtComposite()//
/* (non-Javadoc)
* @see com.foundation.view.swt.IAbstractSwtContainer#getSwtParent()
*/
public Composite getSwtParent() {
return null;
}//getSwtParent()//
/* (non-Javadoc)
* @see com.foundation.view.IView#center()
*/
public void center() {
}//center()//
/* (non-Javadoc)
* @see com.foundation.view.IView#center(com.foundation.view.IView)
*/
public void center(IView centerOnView) {
}//center()//
/* (non-Javadoc)
* @see com.foundation.view.IView#execute(com.common.thread.IRunnable)
*/
public Object execute(IRunnable runnable) {
return getViewContext().getRequestHandler().execute(runnable);
}//execute()//
/* (non-Javadoc)
* @see com.foundation.view.IView#executeAsynch(com.common.thread.IRunnable)
*/
public void executeAsync(IRunnable runnable) {
getViewContext().getRequestHandler().executeAsync(runnable);
}//executeAsynch()//
/* (non-Javadoc)
* @see com.foundation.view.IView#getRequestHandler()
*/
public IRequestHandler getRequestHandler() {
return getViewContext().getRequestHandler();
}//getRequestHandler()//
/* (non-Javadoc)
* @see com.foundation.view.IView#maximize()
*/
public void maximize() {
}//maximize()//
/* (non-Javadoc)
* @see com.foundation.view.IView#minimize()
*/
public void minimize() {
}//minimize()//
/* (non-Javadoc)
* @see com.foundation.view.IView#pack()
*/
public void pack() {
}//pack()//
/* (non-Javadoc)
* @see com.foundation.view.IView#setFocus()
*/
public void setFocus() {
}//setFocus()//
/* (non-Javadoc)
* @see com.foundation.view.IView#setIsEnabled(boolean)
*/
public void setIsEnabled(boolean isEnabled) {
}//setIsEnabled()//
/* (non-Javadoc)
* @see com.foundation.view.IView#show()
*/
public void show() {
}//show()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
return super.toString() + (getName() != null ? " (named: " + getName() + ")" : "");
}//toString()//
}//TrayItem//

View File

@@ -0,0 +1,901 @@
/*
* Copyright (c) 2004,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.events.SelectionListener;
import com.common.comparison.Comparator;
import com.common.debug.Debug;
import com.common.thread.IRunnable;
import com.common.util.*;
import com.foundation.view.IAbstractComponent;
public abstract class TreeComponent extends CollectionComponent implements SelectionListener {
/** The collection of visible columns ordered by their model side zero based index. */
private IList tableColumns = new LiteList(16);
/** Tracks whether or not to try updating the selection if the collection changed. */
protected boolean isSelectionInvalid = false;
/** The currently selected node which may be non-null if auto-synchronizing and allowing only a single selection. */
private NodeData currentlySelectedNode = null;
/** All nodes. */
private LiteHashSet nodes = new LiteHashSet(100);
protected class NodeData extends RowObject {
/** The collection of child NodeData instances, or null if currently unknown. */
private IList children = null;
/** The collection of nodes in the display tree (ie TreeItem's) which are displaying this node and its data. */
private IList displayNodes = new LiteList(1, 25); //TODO: Make this a map so that replacing is fast.
/** The count of parents referencing this node as a child. The node data should not be discarded until this count reaches zero (unless it is a root). */
private int parentCount = 0;
/**
* NodeData constructor.
* @param value The value represented by this node data instance.
*/
public NodeData(Object value) {
super(value);
}//NodeData()//
/**
* Gets the number of references to the value in the tree.
* @return The count of times the value is referenced by the tree's model.
*/
public int getReferenceCount() {
return referenceCount;
}//getReferenceCount()//
/**
* Increments the reference count by one.
*/
public void incrementReferenceCount() {
referenceCount++;
}//incrementReferenceCount()//
/**
* Decrements the reference count by one.
*/
public void decrementReferenceCount() {
referenceCount--;
}//decrementReferenceCount()//
/**
* Gets the child node data instances if known.
* @return The collection of child NodeData instances, or null if currently unknown.
*/
public IList getChildren() {
return children;
}//getChildren()//
/**
* Gets the child node data instances if known.
* @param children The collection of child NodeData instances, or null if currently unknown.
*/
public void setChildren(IList children) {
this.children = children;
}//setChildren()//
/**
* Gets the display components (ie TreeItem's) that are rendering this node.
* @return The collection of nodes in the display tree which are displaying this node and its data.
*/
public IList getDisplayNodes() {
return displayNodes;
}//getDisplayNodes()//
/**
* Gets the count of parents referencing this node.
* @return The count of parents referencing this node as a child. The node data should not be discarded until this count reaches zero (unless it is a root).
*/
public int getParentCount() {
return parentCount;
}//getParentCount()//
/**
* Increments the parent count.
*/
public void incrementParentCount() {
parentCount++;
}//incrementParentCount()//
/**
* Decrements the parent count.
*/
public void decrementParentCount() {
parentCount--;
}//decrementParentCount()//
/**
* Initializes the node and sets up the indexes.
*/
public void initialize() {
//Notify the collection component that an item has been added to the displayed collection. This will register the item with the hidden data 'columns'.//
internalItemAdded(value);
//Add the item to each of the columns so we receive updates.//
for(int index = 0; index < tableColumns.getSize(); index++) {
((AbstractColumn) tableColumns.get(index)).registerItem(getValue(), null);
}//for//
nodes.add(this);
}//initialize()//
/**
* Releases the node and cleans up the indexes.
*/
public void release() {
//Notify the collection component that an item has been removed from the displayed collection. This will unregister the item with the hidden data 'columns'.//
internalItemRemoved(value);
//Unregister the value with the columns so we stop receiving updates.//
for(int index = 0; index < tableColumns.getSize(); index++) {
((AbstractColumn) tableColumns.get(index)).unregisterItem(getValue());
}//for//
nodes.remove(this);
}//release()//
}//NodeData//
/**
* Encapsulates all the data pertaining to a single column in the table component.
*/
public static abstract class AbstractColumn implements IAbstractComponent {
/**
* Registers an item in the collection with this column.
* <p>An item can be registered more than once, but must be unregistered just as many times.</p>
* @param item The item to be registered.
* @param data The data to be associated with the registration.
*/
protected abstract void registerItem(Object item, Object data);
/**
* Unregisters an item that had been previously registered.
* @param item The item to be unregistered.
*/
protected abstract void unregisterItem(Object item);
/**
* Unregisters all items that had been previously registered.
*/
protected abstract void unregisterAllItems();
/**
* Refreshes the value for the header cell.
* @return Whether the header data was altered by the refresh.
*/
protected abstract boolean refreshHeaderData();
/**
* Refreshes the value for the cell(s) denoted by the item representing the row(s) and this column.
* @param item The item that represents the row(s).
* @return Whether the cell data was altered by the refresh.
*/
protected abstract boolean refreshCellData(Object item);
/**
* Gets the value for the cell(s) denoted by the item representing the row(s) and this column.
* @param item The item that represents the row(s).
* @return The cell value.
*/
protected abstract Object getCellData(Object item);
/**
* Gets the column's creation index.
* @return The index assigned to this column and used to facilitate communication with the actual column resource in the display.
*/
protected abstract int getIndex();
/**
* Sets the column's creation index.
* @param index The index assigned to this column and used to facilitate communication with the actual column resource in the display.
*/
protected abstract void setIndex(int index);
/**
* Initializes the column before the table component is initialized.
*/
protected abstract void initialize();
/**
* Initializes the column before the table component is released.
*/
protected abstract void release();
/**
* Refreshes the column.
*/
protected abstract void refresh();
}//AbstractColumn//
/**
* TreeComponent constructor.
* @param parent The parent container for this component.
* @param name The name of the component.
* @param style The style for the control.
*/
public TreeComponent(Container parent, String name, int style) {
super(parent, name, style);
}//TreeComponent()//
/**
* Adds a column to the component.
* @param column The column to be added.
*/
protected void addColumn(AbstractColumn column) {
tableColumns.add(column.getIndex(), column);
//Update the other column indices.//
for(int index = column.getIndex() + 1; index < tableColumns.getSize(); index++) {
((AbstractColumn) tableColumns.get(index)).setIndex(index);
}//for//
//Add the column.//
controlAddColumn(column, column.getIndex());
//Support columns added after the display is showing.//
if(isInitialized()) {
//Note: While it would be nice to send the header and cell data, we can't because the column hasn't been setup yet.//
}//if//
}//addColumn()//
/**
* Gets the number of columns in the table.
* @return The count of columns.
*/
protected int getColumnCount() {
return tableColumns.getSize();
}//getColumnCount()//
/**
* Gets the column at the given index.
* @param index The zero based column index.
* @return The column at the given index.
*/
protected AbstractColumn getColumn(int index) {
return (AbstractColumn) tableColumns.get(index);
}//getColumn()//
/**
* Gets the node for the given item.
* @param item The item object.
* @return The existing tree node representing the item, or null if one doesn't exist yet.
*/
protected abstract NodeData getNodeDataByItem(Object item);
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#internalViewRefreshCollection(com.common.util.ICollection, com.common.util.ICollection)
*/
protected void internalViewRefreshCollection(ICollection newCollection, ICollection oldCollection) {
controlSaveViewState();
//Clear the old data.//
itemAllRemoved();
//Rebuild the tree.//
if(newCollection != null) {
IIterator itemIterator = newCollection.iterator();
//Get the array of strings representing the list contents.//
while(itemIterator.hasNext()) {
Object item = itemIterator.next();
itemAdded(item, -1);
}//while//
}//if//
//If the selection was invalid previously then refresh the selection since it may no longer be invalid.//
if(isSelectionInvalid) {
internalViewRefreshSelection(null);
}//if//
controlRestoreViewState();
}//internalViewRefreshCollection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#internalViewRefreshSelection(java.lang.Object)
*/
protected void internalViewRefreshSelection(Object selectedItem) {
if(selectedItem != null) {
NodeData node = (NodeData) getNodeDataByItem(selectedItem);
if(node == null) {
//TODO: Check the currently selected node's children if they haven't been loaded yet.
//TODO: Search the entire tree of closed nodes for the node - ensure we don't encounter recursion in the tree.
isSelectionInvalid = true;
internalViewRefreshSelections((NodeData[]) null);
}//if//
else {
isSelectionInvalid = false;
internalViewRefreshSelections(new NodeData[] {node});
}//else//
}//if//
else {
//No selection.//
internalViewRefreshSelections((NodeData[]) null);
}//else//
}//internalViewRefreshSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#internalViewRefreshSelections(com.common.util.ICollection, com.common.util.ICollection)
*/
protected void internalViewRefreshSelections(ICollection newSelections, ICollection oldSelections) {
if(newSelections != null) {
LiteList selectedNodes = new LiteList(newSelections.getSize());
IIterator selectionIterator = newSelections.iterator();
NodeData[] nodeArray = null;
//Apply differences between the selection collection and the control selection. Also remove all impossible selections.//
while(selectionIterator.hasNext()) {
Object selection = selectionIterator.next();
NodeData node = (NodeData) getNodeDataByItem(selection);
if(node == null) {
//TODO: Check the currently selected node's children if they haven't been loaded yet.
//TODO: Search the entire tree of closed nodes for the node - ensure we don't encounter recursion in the tree.
//An invalid selection because the selection is not in the collection of displayed values.//
selectionIterator.remove();
}//if//
else {
selectedNodes.add(node);
}//else//
}//while//
selectedNodes.toArray(nodeArray = new NodeData[selectedNodes.getSize()]);
internalViewRefreshSelections(nodeArray);
}//if//
else {
//Remove all selections.//
internalViewRefreshSelections((NodeData[]) null);
}//else//
}//internalViewRefreshSelections()//
/**
* Refreshes the view selections based on the given selected nodes.
* @param selectedNodes The nodes to be selected in the view.
*/
protected void internalViewRefreshSelections(NodeData[] selectedNodes) {
//Determine whether this is a single selection or multi-selection component.//
if(getAllowMultiSelection()) {
if((selectedNodes == null) || (selectedNodes.length == 0)) {
//Clear all selections.//
controlRemoveAllSelections();
}//if//
else {
LiteHashSet selectedNodeDataSet = new LiteHashSet(selectedNodes.length, LiteHashSet.DEFAULT_LOAD_FACTOR, Comparator.getIdentityComparator(), LiteHashSet.STYLE_COUNT_DUPLICATES);
IList selectedControlItems = new LiteList(selectedNodes.length);
//Sort through the selections to see which requiring adding control selection, removing control selections, or are already selected in the control.//
for(int index = 0; index < selectedNodes.length; index++) {
NodeData nodeData = selectedNodes[index];
int alreadySelectedCount = selectedNodeDataSet.getCount(nodeData); //Gets the number of times the node data has already been added to the selection.//
if(nodeData.getDisplayNodes().getSize() > 1) {
IList items = (IList) nodeData.getDisplayNodes();
Object firstNonSelectedDisplayNode = null;
boolean addSelection = true;
//Look for the first non-selected display node and check to see if there is a node already selected (also track the count since a node could exist more than once and could be selected more than once).//
for(int displayNodeIndex = 0; (addSelection) && (displayNodeIndex < items.getSize()); displayNodeIndex++) {
Object displayNode = items.get(displayNodeIndex);
if(!controlIsSelected(displayNode)) {
//Make sure we haven't already identified the first non-selected display node and that the node is not already added to become selected.//
if((firstNonSelectedDisplayNode == null) && (!selectedControlItems.containsValue(displayNode))) {
firstNonSelectedDisplayNode = displayNode;
}//if//
}//if//
else {
if(alreadySelectedCount == 0) {
addSelection = false;
selectedControlItems.add(displayNode);
}//if//
else {
//Decrement the already selected count. This tracks the number of already selected nodes that we have re-selected.//
alreadySelectedCount--;
}//else//
}//else//
}//for//
//If an additional selection is required then add it.//
if(addSelection && (firstNonSelectedDisplayNode != null)) {
selectedControlItems.add(firstNonSelectedDisplayNode);
}//if//
}//if//
else if(nodeData.getDisplayNodes().getSize() == 1) {
selectedControlItems.add(nodeData.getDisplayNodes().getFirst());
}//else if//
selectedNodeDataSet.add(nodeData);
}//for//
//TODO: We should get the current selections and verify they are not identical to the selections we are about to make.
//Set the selections.//
controlSetSelections(selectedControlItems);
}//else//
}//if//
else {
//Identify the single selected node.//
if((selectedNodes != null) && (selectedNodes.length > 1)) {
currentlySelectedNode = null;
Debug.log("Error: Can't set multiple selections to a single selection control.");
}//if//
else {
currentlySelectedNode = ((currentlySelectedNode == null) || (selectedNodes.length == 0)) ? null : selectedNodes[0];
}//else//
//If there is a selection then figure out if it is already selected in the display, otherwise set the selection.//
if(currentlySelectedNode != null) {
if(currentlySelectedNode.getDisplayNodes().getSize() > 0) {
NodeData currentSelection = controlGetSelection();
boolean alreadySelected = currentSelection == currentlySelectedNode;
if(!alreadySelected) {
controlSetSelection(currentlySelectedNode.getDisplayNodes().getFirst());
}//if//
}//if//
}//if//
else {
controlRemoveAllSelections();
}//else//
}//else//
}//internalViewRefreshSelections()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
//Initialize all the columns.//
for(int columnIndex = 0; columnIndex < tableColumns.getSize(); columnIndex++) {
((AbstractColumn) tableColumns.get(columnIndex)).initialize();
}//for//
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#internalViewRelease()
*/
protected void internalViewRelease() {
//Release all the columns.//
for(int columnIndex = 0; columnIndex < tableColumns.getSize(); columnIndex++) {
((AbstractColumn) tableColumns.get(columnIndex)).release();
}//for//
super.internalViewRelease();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
//Refresh all the columns.//
for(int columnIndex = 0; columnIndex < tableColumns.getSize(); columnIndex++) {
((AbstractColumn) tableColumns.get(columnIndex)).refresh();
}//for//
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#itemSorted(int[])
*/
protected void itemSorted(int[] mapping) {
}//itemSorted()//
/**
* Adds the selection to the currently selected set.
* @param node The node to be selected.
*/
private void internalAddSelection(NodeData node) {
//TODO: Check unopened nodes?
if(node.getDisplayNodes().getSize() > 1) {
//Search for the first node that isn't selected.//
for(int index = 0; index < node.getDisplayNodes().getSize(); index++) {
Object item = node.getDisplayNodes().get(index);
if(!controlIsSelected(item)) {
controlAddSelection(item);
break;
}//if//
}//while//
}//if//
else if(node.getDisplayNodes().getSize() == 1) {
controlAddSelection(node.getDisplayNodes().getFirst());
}//else//
}//internalAddSelections()//
/**
* Removes the selection from the currently selected set.
* @param node The node to no longer be selected.
*/
private void internalRemoveSelection(NodeData node) {
//TODO: Check unopened nodes?
if(node.getDisplayNodes().getSize() > 1) {
//Search for the last node that is selected.//
for(int index = node.getDisplayNodes().getSize() - 1; index >= 0; index--) {
Object item = node.getDisplayNodes().get(index);
if(controlIsSelected(item)) {
controlRemoveSelection(item);
break;
}//if//
}//for//
}//if//
else if(node.getDisplayNodes().getSize() == 1) {
controlRemoveSelection(node.getDisplayNodes().getFirst());
}//else//
}//internalRemoveSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#selectionAdded(java.lang.Object)
*/
protected void selectionAdded(Object value) {
NodeData node = (NodeData) getNodeDataByItem(value);
if(node != null) {
internalAddSelection(node);
}//if//
}//selectionAdded()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#selectionRemoved(java.lang.Object)
*/
protected void selectionRemoved(Object value) {
NodeData node = (NodeData) getNodeDataByItem(value);
if(node != null) {
internalRemoveSelection(node);
}//if//
}//selectionRemoved()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#selectionAllRemoved()
*/
protected void selectionAllRemoved() {
controlRemoveAllSelections();
}//selectionAllRemoved()//
/**
* Gets the item data array containing the cell data for each column.
* @param item The collection item whose cell data is to be retreived.
* @return The cell data for each table column.
*/
protected Object[] getItemData(Object item) {
Object[] result = new Object[tableColumns.getSize() + 1];
refreshRowHeaderCellData(item);
result[0] = getRowHeaderCellData(item);
for(int index = 0; index < result.length; index++) {
AbstractColumn column = (AbstractColumn) tableColumns.get(index);
if(column != null) {
column.refreshCellData(item);
result[index + 1] = column.getCellData(item);
}//if//
}//for//
return result;
}//getItemData()//
/**
* Updates the cell data with the latest values.
* @param item The collection item representing the row(s) to be updated.
* @param columnIndex The index of the updated column.
* @param data The data for the specified cell(s).
*/
protected void updateCellData(Object item, AbstractColumn column, Object data) {
NodeData node = (NodeData) getNodeDataByItem(item);
//Notify the table component that the cell data needs refreshing.//
controlSetCellData(node, column != null ? column.getIndex() : -1, data);
}//updateCellData()//
/**
* Updates the cell data with the latest values for all cells in the given column.
* @param columnIndex The index of the updated column.
*/
protected void updateCellData(AbstractColumn column) {
IIterator iterator = nodes.iterator();
while(iterator.hasNext()) {
NodeData node = (NodeData) iterator.next();
if(column == null) {
if(refreshRowHeaderCellData(node.getValue())) {
Object data = getRowHeaderCellData(node.getValue());
//Notify the table component that the row header cell data needs refreshing.//
controlSetCellData(node, -1, data);
}//if//
}//if//
else {
if(column.refreshCellData(node.getValue())) {
Object data = column.getCellData(node.getValue());
//Notify the table component that the cell data needs refreshing.//
controlSetCellData(node, column.getIndex(), data);
}//if//
}//else//
}//while//
}//updateCellData()//
/**
* Refreshes the row header cell data and determines whether there were substantial alterations.
* @param item The row item.
* @return Whether the cell data was changed.
*/
protected abstract boolean refreshRowHeaderCellData(Object item);
/**
* Gets the row header cell data.
* @param item The row item.
* @return The cell data for the row's row header.
*/
protected abstract Object getRowHeaderCellData(Object item);
/**
* Synchronizes the selections with the model.
* @param selectedNodes The selected nodes that should be reflected in the model.
*/
protected void synchronizeSelection(NodeData[] selectedNodes) {
if(getAllowMultiSelection()) {
boolean[] selectionMarks = new boolean[selectedNodes.length];
ICollection modelSelections = getModelSelections();
//Prevent the selection additions from causing a feedback loop.//
suspendSelectionHooks = true;
try {
if(modelSelections != null) {
IIterator iterator = modelSelections.iterator();
LiteList removed = new LiteList(modelSelections.getSize());
LiteList added = new LiteList(selectedNodes.length);
//Initialize the bit field.//
for(int index = 0; index < selectionMarks.length; index++) {
selectionMarks[index] = false;
}//for//
//For each previous selection, try to find a matching current selection, otherwise remove it. Mark all used current selections.//
while(iterator.hasNext()) {
Object nextValue = iterator.next();
boolean found = false;
for(int index = 0; (!found) && (index < selectedNodes.length); index++) {
if((selectedNodes[index].getValue() == nextValue) && (!selectionMarks[index])) {
selectionMarks[index] = true;
found = true;
}//if//
}//for//
//If the selection wasn't found in the view then remove it from the model.//
if(!found) {
removed.add(nextValue);
}//if//
//Add the selections that were in the view but not in the model.//
for(int index = 0; index < selectionMarks.length; index++) {
if(!selectionMarks[index]) {
added.add(selectedNodes[index].getValue());
}//if//
}//for//
}//while//
modelSelections.replaceAll(removed, added);
}//if//
}//try//
finally {
suspendSelectionHooks = false;
}//finally//
}//if//
else {
synchronizeSelection(selectedNodes != null && selectedNodes.length > 0 ? selectedNodes[0] : null);
}//else//
}//synchronizeSelection()//
/**
* Synchronizes the selection with the model.
* @param selectedNode The selected node that should be reflected in the model.
*/
protected void synchronizeSelection(NodeData selectedNode) {
if(!getAllowMultiSelection()) {
setModelSelection(selectedNode == null ? null : selectedNode.getValue());
}//if//
}//synchronizeSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#internalViewSynchronizeSelection()
*/
protected void synchronizeSelection() {
NodeData selectedNode = getAllowMultiSelection() ? null : controlGetSelection();
NodeData[] selectedNodes = getAllowMultiSelection() ? controlGetSelections() : null;
//TODO: Is there any point in trying to optimize things by only sending changes in a multi-select scenario? The problem is the message ordering on the server is unknown.//
if(selectedNodes != null) {
if(selectedNodes.length == 0) {
selectedNodes = null;
}//if//
}//if//
//Called when the user picks a selection.//
if(getAutoSynchronizeSelection()) {
if((getAllowMultiSelection()) || (currentlySelectedNode != selectedNode)) {
currentlySelectedNode = selectedNode;
if(getAutoSynchronizeSelectionDelay() > 0) {
//Start a task to send the selections to the server after a short delay.//
synchronized(this) {
final NodeData taskSelectedNode = selectedNode;
final NodeData[] taskSelectedNodes = selectedNodes;
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
}//if//
autoSynchronizeSelectionTask = new Task() {
public void execute() {
//Make sure that this task is still valid and is not being superceeded.//
synchronized(TreeComponent.this) {
if(autoSynchronizeSelectionTask == this) {
//Cleanup after the task.//
autoSynchronizeSelectionTask = null;
getEventLoop().executeAsync(new IRunnable() {
public Object run() {
if(getAllowMultiSelection()) {
synchronizeSelection(taskSelectedNodes);
}//if//
else {
synchronizeSelection(taskSelectedNode);
}//else//
if(getAutoValidate()) {
postSynchronizeValidate();
}//if//
return null;
}//run()//
});
}//if//
}//synchronized//
}//run()//
};
addTask(autoSynchronizeSelectionTask, getAutoSynchronizeSelectionDelay());
}//synchronized//
}//if//
}//if//
else {
if(getAllowMultiSelection()) {
synchronizeSelection(selectedNodes);
}//if//
else {
synchronizeSelection(selectedNode);
}//else//
if(getAutoValidate()) {
postSynchronizeValidate();
}//if//
}//else//
}//if//
}//synchronizeSelection()//
/* (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;
NodeData[] selectedNodes = controlGetSelections();
if((selectedNodes != null) && (selectedNodes.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 < selectedNodes.length); selectionIndex++) {
updateSelectionLinks = (selectedNodes[selectionIndex] != null) && (selectedNodes[selectionIndex].getValue() == item);
}//for//
}//if//
if(updateSelectionLinks) {
updateSelectionLinks(selectedNodes, getHiddenData(hiddenDataIndex));
}//if//
}//if//
else {
NodeData selectedNode = controlGetSelection();
if((selectedNode != null) && (selectedNode.getValue() == item)) {
getHiddenData(hiddenDataIndex).invokeLinkage(selectedNode != null ? selectedNode.getValue() : null);
}//if//
}//else//
}//updateHiddenData()//
/* (non-Javadoc)
* @see com.foundation.view.swt.CollectionComponent#updateSelectionLinks()
*/
protected void updateSelectionLinks() {
super.updateSelectionLinks();
if(getHiddenDataCount() > 0) {
if(getAllowMultiSelection()) {
NodeData[] selectedNodes = controlGetSelections();
for(int hiddenDataIndex = 0; hiddenDataIndex < getHiddenDataCount(); hiddenDataIndex++) {
updateSelectionLinks(selectedNodes, getHiddenData(hiddenDataIndex));
}//for//
}//if//
else {
NodeData selectedNode = controlGetSelection();
for(int hiddenDataIndex = 0; hiddenDataIndex < getHiddenDataCount(); hiddenDataIndex++) {
getHiddenData(hiddenDataIndex).invokeLinkage(selectedNode != null ? selectedNode.getValue() : null);
}//for//
}//else//
}//if//
}//updateSelectionLinks()//
/**
* Updates selection linkages associated with the hidden data 'column'.
* @param selectedNodes The set of nodes selected.
* @param hiddenData The hidden data whose linkages will be updated.
*/
protected void updateSelectionLinks(NodeData[] selectedNodes, HiddenData hiddenData) {
Object[] values = null;
if((selectedNodes != null) && (selectedNodes.length > 0)) {
values = new Object[selectedNodes.length];
for(int index = 0; index < values.length; index++) {
values[index] = selectedNodes[index].getValue();
}//for//
}//if//
hiddenData.invokeLinkage(values);
}//updateSelectionLinks()//
/**
* Removes all displayed items from the control.
*/
protected abstract void controlRemoveAll();
/**
* Adds a link between the parent and child node data's. This must update the display to show the relationship.
* <p>Warning: It is possible to have a child displayed more than once under a single parent.</p>
* @param parent The parent node.
* @param child The new child node.
*/
protected abstract void controlAddLinkage(NodeData parent, NodeData child);
/**
* Removes a link between the parent and child node data's. This must update the display to show the relationship.
* <p>Warning: It is possible to have a child displayed more than once under a single parent.</p>
* @param parent The parent node.
* @param child The old child node.
*/
protected abstract void controlRemoveLinkage(NodeData parent, NodeData child);
/**
* Sets the data displayed by the node cell.
* @param nodeData The object encapsulating the data for the node. The node data may reference multiple display components which must be updated to reflect the new state.
* @param columnIndex The index of the affected column.
* @param data The data to be displayed by the cell(s).
*/
protected abstract void controlSetCellData(NodeData nodeData, int columnIndex, Object data);
/**
* Saves some state information about the view to allow restoration of the view state when a rebuild of the view is completed.
*/
protected abstract void controlSaveViewState();
/**
* Restores the view state after rebuilding the view.
*/
protected abstract void controlRestoreViewState();
/**
* Adds a column to the right of existing columns.
* @param columnData The metadata for the column. This should be associated with the table column.
*/
protected abstract void controlAddColumn(AbstractColumn column);
/**
* Adds a column at the index in the set of existing columns.
* @param columnData The metadata for the column. This should be associated with the table column.
* @param columnIndex The index of the affected column.
*/
protected abstract void controlAddColumn(AbstractColumn column, int columnIndex);
/**
* Removes the specified column.
* @param columnIndex The index of the affected column.
*/
protected abstract void controlRemoveColumn(int columnIndex);
/**
* Gets the indices selected within the control.
* @return The collection of nodes for the currently selected rows, or null if empty.
*/
protected abstract NodeData[] controlGetSelections();
/**
* Gets the node selected.
* @return The selected node in the view.
*/
protected abstract NodeData controlGetSelection();
/**
* Sets the selected values in the control.
* @param itemData The table item objects representing the selected rows. The list contents are control dependant.
*/
protected abstract void controlSetSelections(IList itemData);
/**
* Sets the selected value in the control.
* @param itemData The table item object representing the selected row. The type is control dependant.
*/
protected abstract void controlSetSelection(Object itemData);
/**
* Adds a selected value in the control.
* @param itemData The table item object representing the selected row. The type is control dependant.
*/
protected abstract void controlAddSelection(Object itemData);
/**
* Deselects a value in the control.
* @param itemData The table item object representing the selected row. The type is control dependant.
*/
protected abstract void controlRemoveSelection(Object itemData);
/**
* Deselects all rows in the control.
*/
protected abstract void controlRemoveAllSelections();
/**
* Checks to see if a value is selected.
* @param itemData The table item object representing the possibly selected row. The type is control dependant.
* @return Whether the row is currently selected.
*/
protected abstract boolean controlIsSelected(Object itemData);
/**
* Forces the selection event handler to be called.
*/
protected abstract void forceSelectionEvent(); //Should call widgetSelected implemented by the subclass. This name may need to change.//
}//TreeComponent//

View File

@@ -0,0 +1,253 @@
/*
* 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.debug.*;
import com.foundation.view.*;
import com.foundation.controller.IController;
import com.foundation.event.*;
/*
* Encapsulates an object reference used by the view system at runtime, and the class of the runtime reference to allow design type automation.
*/
public class ValueHolder extends Component implements IValueHolder {
/** The class of value held by this value holder. */
private Class heldType = null;
/** The current value held by this value holder. */
private IEventEmitter value = null;
/** The collection of event listeners listening for held value events. */
private LiteHashSet eventListeners = new LiteHashSet(5);
/** The collection of value holder listeners listening for held value events. */
private LiteHashSet valueHolderListeners = new LiteHashSet(5, LiteHashSet.DEFAULT_LOAD_FACTOR, LiteHashSet.DEFAULT_COMPARATOR, LiteHashSet.STYLE_COUNT_DUPLICATES);
/** The event support used by value holder related associations to listen for held value events. */
private EventSupport eventSupport = null;
/** The parent resource from which this holder's value is derived. */
private SingleResourceAssociation parent = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_OBJECT, false, null);
/** Whether the value holder gets its value from a parent. */
private boolean hasParent = false;
/** Whether to not warn when an attempt is made to place a value that is not of the correct type. */
private boolean ignoreWarnings = false;
/**
* ValueHolder constructor.
* @param parent The parent container.
* @param name The view unqiue name of the component.
* @param heldType The type of object to be held by the value holder.
*/
public ValueHolder(IAbstractContainer parent, String name, Class heldType) {
super(parent, name, 0);
this.heldType = heldType;
}//ValueHolder()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
//Does nothing since this is a non-visual component.//
}//initializeControl()//
/**
* Sets whether the holder supresses warnings relating to attempts at setting the value to an invalid object type.
* @param ignoreWarnings Whether to not warn when an attempt is made to place a value that is not of the correct type.
*/
public void ignoreWarnings(boolean ignoreWarnings) {
this.ignoreWarnings = ignoreWarnings;
}//ignoreWarnings()//
/**
* Sets the association container used to access the parent value holder.
* @param container The parent association metadata.
*/
public void setParentAssociation(SingleAssociationContainer container) {
verifyThread();
this.parent.setAssociations(container);
this.hasParent = true;
}//setParentAssociation()//
/**
* Gets the support object that provides listener functionality.
* @return The support object used to listen for events from IEventEmitter objects.
*/
protected EventSupport getEventSupport() {
if(eventSupport == null) {
eventSupport = new EventSupport(null);
}//if//
return eventSupport;
}//getEventListenerSupport()//
/**
* The value being held by this holder.
* @return The currently held value.
*/
public IEventEmitter getValue() {
return value;
}//getValue()//
/**
* Gets the class for the values held by this value holder.
* @return The held value type.
*/
public Class getHeldType() {
return heldType;
}//getHeldType()//
/* (non-Javadoc)
* @see com.foundation.view.IValueHolder#registerListener(com.foundation.view.IEventCapableAssociation)
*/
public void registerListener(IEventCapableAssociation eventAssociation) {
IEventEmitter value = getValue();
if((value != null) && (eventAssociation.getEventNumber() != -1) && ((eventAssociation.getValueHolderHeldType() == null) || (eventAssociation.getValueHolderHeldType().isAssignableFrom(value.getClass())))) {
getEventSupport().register(value, eventAssociation.getEventNumber(), eventAssociation, true);
}//if//
eventListeners.add(eventAssociation);
}//registerListener()//
/* (non-Javadoc)
* @see com.foundation.view.IValueHolder#unregisterListener(com.foundation.view.IEventCapableAssociation)
*/
public void unregisterListener(IEventCapableAssociation eventAssociation) {
IEventEmitter value = getValue();
if((value != null) && (eventAssociation.getEventNumber() != -1) && ((eventAssociation.getValueHolderHeldType() == null) || (eventAssociation.getValueHolderHeldType().isAssignableFrom(value.getClass())))) {
getEventSupport().unregister(value, eventAssociation.getEventNumber(), eventAssociation);
}//if//
eventListeners.remove(eventAssociation);
}//unregisterListener()//
/* (non-Javadoc)
* @see com.foundation.view.IValueHolder#registerListener(com.foundation.view.IValueHolderListener)
*/
public void registerListener(IValueHolderListener listener) {
valueHolderListeners.add(listener);
}//registerListener()//
/* (non-Javadoc)
* @see com.foundation.view.IValueHolder#unregisterListener(com.foundation.view.IValueHolderListener)
*/
public void unregisterListener(IValueHolderListener listener) {
valueHolderListeners.remove(listener);
}//unregisterListener()//
/**
* Updates the registered listeners so that they are registered with the new held value and are notified that their attributes may have changed.
* @param oldHeldValue The old value held by this value holder.
* @param newHeldValue The new value held by this value holder.
*/
public synchronized void updateRegisteredListeners(IEventEmitter oldHeldValue, IEventEmitter newHeldValue) {
IIterator iterator = new LiteHashSet(eventListeners).iterator();
//Unregister and reregister handlers.//
while(iterator.hasNext()) {
IEventCapableAssociation eventAssociation = (IEventCapableAssociation) iterator.next();
if((oldHeldValue != null) && ((eventAssociation.getValueHolderHeldType() == null) || (eventAssociation.getValueHolderHeldType().isAssignableFrom(value.getClass())))) {
getEventSupport().unregister(oldHeldValue, eventAssociation.getEventNumber(), eventAssociation);
}//if//
if((newHeldValue != null) && ((eventAssociation.getValueHolderHeldType() == null) || (eventAssociation.getValueHolderHeldType().isAssignableFrom(value.getClass())))) {
getEventSupport().register(newHeldValue, eventAssociation.getEventNumber(), eventAssociation, true);
}//if//
}//while//
iterator.resetToFront();
//Fire the events so that the listener view components know to update themselves.//
while(iterator.hasNext()) {
IEventCapableAssociation eventAssociation = (IEventCapableAssociation) iterator.next();
eventAssociation.evaluate(eventAssociation.getEventNumber(), null, 0);
}//while//
//Notify the listeners so they can update.//
if(valueHolderListeners.getSize() > 0) {
iterator = new LiteHashSet(valueHolderListeners).iterator();
while(iterator.hasNext()) {
IValueHolderListener listener = (IValueHolderListener) iterator.next();
listener.heldValueChanged();
}//while//
}//if//
}//updateRegisteredListeners()//
/**
* Sets the value being held.
* @param value The held value.
*/
protected void setValue(IEventEmitter value) {
if(value != this.value) {
IEventEmitter oldValue = this.value;
this.value = value;
updateRegisteredListeners(oldValue, value);
}//if//
}//setValue()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
parent.initialize();
isInitialized(true);
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
parent.release();
getEventSupport().unregisterAll();
if(getContainer() != null) {
getContainer().getComponents().remove(this);
}//if//
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
if(isInitialized()) {
if(hasParent) {
if(parent.refresh()) {
Object value = parent.getValue();
if((value == null) || (value instanceof IEventEmitter) && (heldType.isAssignableFrom(value.getClass()))) {
setValue((IEventEmitter) value);
}//if//
else if(!ignoreWarnings) {
if(value instanceof IEventEmitter) {
Debug.log("Invalid held object. Received a " + value.getClass().getName() + " and was expecting a " + heldType.getName() + " in the ValueHolder named " + getName() + ".");
}//if//
else {
Debug.log("Invalid held object. The class " + value.getClass().getName() + " does not implement " + IEventEmitter.class.getName() + " in the ValueHolder named " + getName() + ".");
}//else//
}//else if//
}//if//
}//if//
else {
IAbstractContainer parent = getContainer();
IController controller = null;
while((parent != null) && (controller == null)) {
if(parent instanceof IView) {
controller = ((IView) parent).getController();
}//if//
else {
parent = parent.getContainer();
}//else//
}//while//
if((controller != null) && (controller.getClass().isAssignableFrom(heldType))) {
setValue((IEventEmitter) controller);
}//if//
else if(!controller.getClass().isAssignableFrom(heldType)) {
Debug.log("Invalid controller object. Received a " + controller.getClass().getName() + " and was expecting a " + heldType.getName() + " in the ValueHolder named " + getName() + ".");
}//else if//
}//else//
}//if//
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(isInitialized()) {
internalViewRefresh();
}//if//
}//internalOnValueChanged()//
}//ValueHolder//

View File

@@ -0,0 +1,207 @@
/*
* 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.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import com.common.debug.Debug;
import com.foundation.view.*;
import com.foundation.controller.*;
public class Window extends Frame {
public static final int STYLE_MODELESS = SWT.MODELESS;
public static final int STYLE_PRIMARY_MODAL = SWT.PRIMARY_MODAL;
public static final int STYLE_APPLICATION_MODAL = SWT.APPLICATION_MODAL;
public static final int STYLE_SYSTEM_MODAL = SWT.SYSTEM_MODAL;
/** The parent in this case is not the container, but used for dialog like functionality. This may be null if the parent shell is not a JEF view component. */
private Window parent;
/** The parent shell in this case is not the container, but used for dialog like functionality. */
private Shell parentShell;
/**
* Window default constructor.
* <p>Warning: This is only for use by the framework. This should never be called to create a useable instance.</p>
*/
public Window() {
}//Window()//
/**
* Window constructor.
* @param parent
* @param name
* @param style
* @param viewContext
* @see #STYLE_BORDER
* @see #STYLE_H_SCROLL
* @see #STYLE_V_SCROLL
* @see #STYLE_BORDER
* @see #STYLE_LEFT_TO_RIGHT
* @see #STYLE_RIGHT_TO_LEFT
* @see #STYLE_NO_BACKGROUND
* @see #STYLE_NO_FOCUS
* @see #STYLE_NO_MERGE_PAINTS
* @see #STYLE_NO_REDRAW_RESIZE
* @see #STYLE_NO_RADIO_GROUP
* @see #STYLE_CLOSE
* @see #STYLE_MIN
* @see #STYLE_MAX
* @see #STYLE_RESIZE
* @see #STYLE_TITLE
* @see #STYLE_NO_TRIM
* @see #STYLE_SHELL_TRIM
* @see #STYLE_DIALOG_TRIM
* @see #STYLE_ON_TOP
* @see #STYLE_TOOL
* @see #STYLE_MODELESS
* @see #STYLE_PRIMARY_MODAL
* @see #STYLE_APPLICATION_MODAL
* @see #STYLE_SYSTEM_MODAL
*/
public Window(AbstractViewController parent, String name, int style, IViewContext viewContext, ViewController viewController) {
super(name, viewContext, style, viewController);
}//Window()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
ViewController viewController = (ViewController) data;
AbstractViewController parentViewController = viewController.getParent();
setController(viewController);
if(parentViewController != null) {
IView view = parentViewController.getView();
if(view instanceof Window) {
this.parent = (Window) view;
this.parentShell = this.parent.getSwtShell();
}//if//
else {
this.parentShell = ((Container) view).getSwtComposite().getShell();
if(this.parentShell.getData() instanceof Window) {
this.parent = (Window) this.parentShell.getData();
}//if//
}//else//
}//if//
//Set the modal flag.//
switch(viewController.getOptions()) {
case AbstractViewController.OPTION_MODELESS: {
style |= SWT.MODELESS;
break;
}//case//
case AbstractViewController.OPTION_MODAL: {
style |= SWT.PRIMARY_MODAL;
break;
}//case//
case AbstractViewController.OPTION_APPLICATION_MODAL: {
style |= SWT.APPLICATION_MODAL;
break;
}//case//
case AbstractViewController.OPTION_SYSTEM_MODAL: {
style |= SWT.SYSTEM_MODAL;
break;
}//case//
default: {
//Does nothing.//
}//default//
}//switch//
if(parentShell != null) {
setSwtWidget(new org.eclipse.swt.widgets.Shell(parentShell, style));
// if(parent != null) {
// parent.setIsEnabled(false);
// }//if//
}//if//
else {
setSwtWidget(new org.eclipse.swt.widgets.Shell(EventLoop.getSingleton().getDisplay(), style));
}//else//
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT shell that represents this frame.
* @return The shell providing visualization for this frame.
*/
public org.eclipse.swt.widgets.Shell getSwtShell() {
return (org.eclipse.swt.widgets.Shell) getSwtControl();
}//getSwtShell()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Frame#registerShellListeners()
*/
protected void registerShellListeners() {
//Add this component as a shell listener so we get shell events.//
getSwtShell().addShellListener(this);
}//registerShellListeners()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
//Initialize the super class components.//
super.internalViewInitialize();
if(parentShell != null) { //Center the window on the parent if there is one. TODO: Allow a way to turn this centering off?//
Rectangle parentBounds = parentShell.getBounds();
Point size = getSwtShell().getSize();
Rectangle displayArea = getSwtShell().getDisplay().getClientArea();
int x = ((parentBounds.width - size.x) >> 1) + parentBounds.x;
int y = ((parentBounds.height - size.y) >> 1) + parentBounds.y;
if((x + size.x) - parentBounds.x > displayArea.width) {
x = (displayArea.width - size.x) + parentBounds.x;
}//if//
if((y + size.y) - parentBounds.y > displayArea.height) {
y = (displayArea.height - size.y) + parentBounds.y;
}//if//
if(x - parentBounds.x < 0) {
x = parentBounds.x;
}//if//
if(y - parentBounds.y < 0) {
y = parentBounds.y;
}//if//
getSwtShell().setLocation(x, y);
}//block//
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
try {
super.internalViewRelease();
}//try//
finally {
if(parentShell != null) {
if(parent != null) {
//TODO: Figure out how to make the parent be the top most visible window?//
// parent.setIsEnabled(true);
parent.setFocus();
}//if//
else {
parentShell.setFocus();
}//else//
//parent.setIsVisible(true);
//parent.getSwtShell().setActive();
//parent.getSwtShell().forceActive();
//parent.getSwtShell().forceFocus();
//parent.getSwtShell().redraw();
parent = null;
parentShell = null;
}//if//
}//finally//
}//internalViewRelease()//
}//ExternalFrame//

View File

@@ -0,0 +1,159 @@
/*
* 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.view.swt;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.custom.StackLayout;
import com.common.util.*;
import com.foundation.view.*;
/*
* TODO: Is this used any more??
*/
public class Wizard extends Container {
/** The attribute that tracks which page number is being displayed. */
private IAttributeAssociation pageAttribute = null;
/** The index of the currently visible 'page' component. */
private int currentPageNumber = -1;
/**
* Wizard constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_NO_BACKGROUND
* @see #STYLE_NO_FOCUS
* @see #STYLE_NO_MERGE_PAINTS
* @see #STYLE_NO_REDRAW_RESIZE
* @see #STYLE_NO_RADIO_GROUP
* @see #STYLE_H_SCROLL
* @see #STYLE_V_SCROLL
* @see #STYLE_BORDER
* @see #STYLE_LEFT_TO_RIGHT
* @see #STYLE_RIGHT_TO_LEFT
*/
public Wizard(Container parent, String name, int style) {
super(parent, name, style);
}//Wizard()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.widgets.Composite(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
//getSwtComposite().setLayout(new com.foundation.view.swt.layout.WizardLayout());
getSwtComposite().setLayout(new StackLayout());
}//initializeControl()//
/**
* Gets the stack layout used with the wizard.
* @return The wizard's stack layout.
*/
protected StackLayout getLayout() {
return (StackLayout) getSwtComposite().getLayout();
}//getLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Container#setLayout(org.eclipse.swt.widgets.Layout)
*/
public void setLayout(Layout layout) {
//Does nothing. Layouts are not allowed here.//
}//setLayout()//
/**
* Gets the SWT composite that represents this panel.
* @return The SWT composite providing visualization for this panel.
*/
public org.eclipse.swt.widgets.Composite getSwtComposite() {
return (org.eclipse.swt.widgets.Composite) getSwtControl();
}//getSwtComposite()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnEventFired(com.foundation.view.swt.IEventAssociation, java.lang.Object[])
*/
protected void internalOnEventFired(IEventAssociation eventAssociation, Object[] eventArguments) {
}//internalOnEventFired()//
/**
* Sets the currently displayed page number attribute.
* @param pageAttribute The attribute referencing the currently displayed page's number.
*/
public void setPageAttribute(IAttributeAssociation pageAttribute) {
if((isInitialized()) && (this.pageAttribute != null)) {
this.pageAttribute.unregister();
}//if//
this.pageAttribute = pageAttribute;
if(isInitialized()) {
pageAttribute.register();
internalRefreshPage();
}//if//
}//setPageAttribute()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
if(pageAttribute != null) {
pageAttribute.register();
}//if//
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
super.internalViewRelease();
if(pageAttribute != null) {
pageAttribute.unregister();
}//if//
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalRefreshPage();
}//internalViewRefresh()//
/**
* Refreshes the currently visible wizard page.
*/
protected void internalRefreshPage() {
if(pageAttribute != null) {
Number pageNumber = (Number) pageAttribute.getAttributeValue();
if(pageNumber == null) {
pageNumber = new Integer(0);
pageAttribute.setAttributeValue(pageNumber);
}//if//
if(currentPageNumber != pageNumber.intValue()) {
currentPageNumber = pageNumber.intValue();
getLayout().topControl = ((Component) ((IList) getComponents()).get(currentPageNumber)).getSwtControl();
getSwtComposite().layout();
((Component) ((IList) getComponents()).get(currentPageNumber)).getSwtControl().setFocus();
}//if//
}//if//
}//internalRefreshPage()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
//Since the page can only be set manually, this method should do nothing.//
super.internalViewSynchronize();
}//internalViewSynchronize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#onValueChanged(com.foundation.view.swt.IAttributeAssociation)
*/
protected void internalOnValueChanged(IAttributeAssociation attributeAssociation) {
if(attributeAssociation == pageAttribute) {
internalRefreshPage();
}//if//
else {
super.internalOnValueChanged(attributeAssociation);
}//else//
}//internalOnValueChanged()//
}//Wizard//

View File

@@ -0,0 +1,611 @@
/*
* Copyright (c) 2006,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.cell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Button;
import com.common.thread.IRunnable;
import com.common.util.IIterator;
import com.foundation.view.*;
import com.foundation.view.resource.ResourceReference;
import com.foundation.view.swt.*;
import com.foundation.view.swt.util.SwtUtilities;
public class CellButton extends CellComponent {
public static final int STYLE_ARROW = SWT.ARROW;
public static final int STYLE_CHECK = SWT.CHECK;
public static final int STYLE_PUSH = SWT.PUSH;
public static final int STYLE_RADIO = SWT.RADIO;
public static final int STYLE_TOGGLE = SWT.TOGGLE;
public static final int STYLE_FLAT = SWT.FLAT;
public static final int STYLE_LEFT = SWT.LEFT;
public static final int STYLE_RIGHT = SWT.RIGHT;
public static final int STYLE_CENTER = SWT.CENTER;
public static final int STYLE_UP = SWT.UP;
public static final int STYLE_DOWN = SWT.DOWN;
/** Called when the button is pressed (only used for push buttons). */
private IMethodAssociation selectionMethod = null;
/** The button's selection state resource. */
private MultiResourceAssociation selection = new MultiResourceAssociation(this, this, getViewContext(), MultiResourceAssociation.TYPE_BOOLEAN, true, Boolean.FALSE);
/** The button's text resource. */
private VariableResourceAssociation text = new VariableResourceAssociation(this, this, getViewContext(), MultiResourceAssociation.TYPE_TEXT, false, "");
/** The button's image resource. */
private VariableResourceAssociation image = new VariableResourceAssociation(this, this, getViewContext(), MultiResourceAssociation.TYPE_IMAGE, false, null);
/** The delay to be used when auto synchronizing changes to the text. */
private long autoSynchronizeSelectionDelay = 500;
/** Whether this is a stateful button. */
private final boolean isStateful;
/** The control style. */
private int style = 0;
/** A holder for the value of the text. */
private ResourceHolder textHolder = new ResourceHolder(this);
/** A holder for the value of the image. */
private ResourceHolder imageHolder = new ResourceHolder(this);
/** The swt image last held by the image holder. */
private Image swtImage = null;
public class ButtonCellControl extends CellControl implements SelectionListener {
/** The task that auto synchronizes the selection after a short delay. */
private Task autoSynchronizeSelectionTask = null;
/** A holder for the value of the text. */
private ResourceHolder textHolder = new ResourceHolder(this);
/** A holder for the value of the image. */
private ResourceHolder imageHolder = new ResourceHolder(this);
/** The swt image last held by the image holder. */
private Image swtImage = null;
/**
* ButtonCellControl constructor.
* @param control The control being encapsulated.
* @param rowObject The data model the control interacts with.
*/
public ButtonCellControl(Button control, Object rowObject) {
super(control, rowObject);
}//ButtonCellControl()//
/**
* Gets the button control.
* @return The button being encapsulated.
*/
public Button getSwtButton() {
return (Button) getSwtControl();
}//getSwtButton()//
/**
* Sets the control's image.
* @param image The image.
*/
protected void controlSetImage(JefImage image) {
if(swtImage != null) {
swtImage.dispose();
swtImage = null;
}//if//
if(image != null) {
swtImage = SwtUtilities.getImage(getSwtControl().getDisplay(), image);
}//if//
getSwtButton().setImage(swtImage);
}//controlSetImage()//
/**
* Sets the text.
* @param text The text to display.
*/
protected void controlSetText(String Text) {
getSwtButton().setText(Text);
}//controlSetText()//
/**
* Sets the component's selection state.
* @param isSelected Whether the button is to be selected.
*/
protected void controlSetSelection(boolean isSelected) {
getSwtButton().setSelection(isSelected);
}//controlSetSelection()//
/**
* Initializes the control.
*/
public void initialize() {
getSwtButton().addSelectionListener(this);
super.initialize();
}//initialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent.CellControl#refresh()
*/
public void refresh() {
super.refresh();
refreshImage();
refreshSelection();
refreshText();
}//refresh()//
/**
* Refreshes the image.
*/
public void refreshImage() {
//Check for a common value which will only be set if the value is a single association.//
if(CellButton.this.imageHolder != null) {
getSwtButton().setImage(CellButton.this.swtImage);
}//if//
else { //Use a value per row.//
if(imageHolder == null) {
imageHolder = new ResourceHolder(this);
}//if//
imageHolder.setValue(image.getValue(getRowValue()));
}//else//
}//refreshImage()//
/**
* Refreshes the text.
*/
public void refreshText() {
//Check for a common value which will only be set if the value is a single association.//
if(CellButton.this.textHolder != null) {
String value = (String) CellButton.this.textHolder.getValue();
getSwtButton().setText(value != null ? value : "");
}//if//
else { //Use a value per row.//
if(textHolder == null) {
textHolder = new ResourceHolder(this);
}//if//
textHolder.setValue(text.getValue(getRowValue()));
}//else//
}//refreshText()//
/**
* Refreshes the selection value.
*/
public void refreshSelection() {
if(isStateful) {
Boolean value = (Boolean) selection.getValue(getRowValue());
controlSetSelection(value != null ? value.booleanValue() : false);
}//if//
}//refreshSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent.CellControl#release()
*/
public void release() {
if(textHolder != null) {
textHolder.release();
}//if//
if(imageHolder != null) {
imageHolder.release();
}//if//
if((swtImage != null) && (!swtImage.isDisposed())) {
swtImage.dispose();
}//if//
if(!getSwtButton().isDisposed()) {
getSwtButton().removeSelectionListener(this);
}//if//
//Ignore any pending synchronizations.//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
autoSynchronizeSelectionTask = null;
}//if//
}//synchronized//
super.release();
}//release()//
/**
* Forces any pending synchronizations to complete.
*/
public void synchronize() {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
autoSynchronizeSelectionTask.execute();
autoSynchronizeSelectionTask = null;
}//if//
}//synchronize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent.CellControl#resourceHolderChanged(com.foundation.view.AbstractResourceHolder, java.lang.Object, java.lang.Object)
*/
public void resourceHolderChanged(AbstractResourceHolder resourceHolder, Object oldValue, Object newValue, int flags) {
if(resourceHolder == textHolder) {
controlSetText((String) resourceHolder.getValue());
}//if//
else if(resourceHolder == imageHolder) {
controlSetImage((JefImage) resourceHolder.getValue());
}//else if//
}//resourceHolderChanged()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent event) {
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent event) {
final boolean isSelected = getSwtButton().getSelection();
if((selectionMethod == null) && (autoSynchronizeSelectionDelay > 0)) {
//Start a task to send the text to the server after a short delay. This will reduce the overhead of auto synchronizing the selection.//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
}//if//
autoSynchronizeSelectionTask = new Task() {
public void execute() {
//Make sure that this task is still valid and is not being superceeded.//
synchronized(ButtonCellControl.this) {
if(autoSynchronizeSelectionTask == this) {
//Cleanup after the task.//
autoSynchronizeSelectionTask = null;
getEventLoop().executeAsync(new IRunnable() {
public Object run() {
selection.setValue(getRowValue(), isSelected ? Boolean.TRUE : Boolean.FALSE);
return null;
}//run()//
});
}//if//
}//synchronized//
}//run()//
};
addTask(autoSynchronizeSelectionTask, autoSynchronizeSelectionDelay);
}//synchronized//
}//if//
else {
if(selectionMethod != null) {
if(selectionMethod.getIsValueHolderAssociated()) {
selectionMethod.invoke(new Object[] {getRowValue()}, true);
}//if//
else {
selectionMethod.invoke(getRowValue(), null, true);
}//else//
}//if//
else {
selection.setValue(getRowValue(), isSelected ? Boolean.TRUE : Boolean.FALSE);
}//else//
}//else//
}//widgetSelected()//
}//ButtonCellControl//
/**
* CellButton constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_ARROW
* @see #STYLE_CHECK
* @see #STYLE_PUSH
* @see #STYLE_RADIO
* @see #STYLE_TOGGLE
* @see #STYLE_FLAT
* @see #STYLE_LEFT
* @see #STYLE_RIGHT
* @see #STYLE_CENTER
* @see #STYLE_UP
* @see #STYLE_DOWN
*/
public CellButton(ICellContainer parent, String name, int style) {
super(parent, name, style);
isStateful = ((style & STYLE_RADIO) > 0) || ((style & STYLE_TOGGLE) > 0) || ((style & STYLE_CHECK) > 0);
this.style = style;
}//CellButton()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractComponent#getName()
*/
public String getName() {
return "__CellButton__";
}//getName()//
/**
* Sets the association container used to access the text.
* @param container The text association metadata.
*/
public void setTextAssociation(AssociationContainer container) {
verifyThread();
this.text.setAssociations(container);
}//setTextAssociation()//
/**
* Sets the association container used to access the image.
* @param container The image association metadata.
*/
public void setImageAssociation(AssociationContainer container) {
verifyThread();
this.image.setAssociations(container);
}//setImageAssociation()//
/**
* Sets the association container used to access the selection.
* @param container The selection association metadata.
*/
public void setSelectionAssociation(MultiAssociationContainer container) {
verifyThread();
this.selection.setAssociations(container);
}//setSelectionAssociation()//
/**
* Sets the selection method called when the button is pressed (intended only for push buttons).
* @param selectionMethod The method called when the button is pressed.
*/
public void setSelectionMethod(IMethodAssociation selectionMethod) {
verifyThread();
if(!isStateful) {
this.selectionMethod = selectionMethod;
}//if//
}//setSelectionMethod()//
/**
* Sets the component text.
* @param text The text that will appear in the component.
*/
public void setText(String text) {
verifyThread();
this.text.setDefaultValue(text);
}//setText()//
/**
* Sets the component's default text resource.
* @param text The text to be displayed by this component.
*/
public void setText(ResourceReference text) {
verifyThread();
this.text.setDefaultValue(text);
}//setText()//
/**
* Sets the component image.
* @param image The image to be displayed by the component.
*/
public void setImage(JefImage image) {
verifyThread();
this.image.setDefaultValue(image);
}//setImage()//
/**
* Sets the component's default image resource.
* @param image The image to be displayed by this component.
*/
public void setImage(ResourceReference image) {
verifyThread();
this.image.setDefaultValue(image);
}//setImage()//
/**
* Sets the delay for the auto synchronize selection.
* @param autoSynchronizeSelectionDelay The delay in terms of milliseconds between the value of zero and ten thousand. A zero value has no delay.
*/
public void setAutoSynchronizeSelectionDelay(long autoSynchronizeSelectionDelay) {
verifyThread();
if(autoSynchronizeSelectionDelay < 0) {
autoSynchronizeSelectionDelay = 0;
}//if//
else if(autoSynchronizeSelectionDelay > 10000) {
autoSynchronizeSelectionDelay = 10000;
}//else if//
this.autoSynchronizeSelectionDelay = autoSynchronizeSelectionDelay;
}//setAutoSynchronizeSelectionDelay()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
super.internalViewInitialize();
text.initialize();
image.initialize();
selection.initialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewRelease()
*/
protected void internalViewRelease() {
if(textHolder != null) {
textHolder.release();
}//if//
if(imageHolder != null) {
imageHolder.release();
}//if//
if((swtImage != null) && (!swtImage.isDisposed())) {
swtImage.dispose();
}//if//
super.internalViewRelease();
text.release();
image.release();
selection.release();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
internalViewRefreshImage();
internalViewRefreshText();
super.internalViewRefresh();
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewRefresh(com.foundation.view.swt.cell.CellComponent.CellControl)
*/
protected void internalViewRefresh(CellControl cellControl) {
super.internalViewRefresh(cellControl);
internalViewRefreshSelection((ButtonCellControl) cellControl);
internalViewRefreshText((ButtonCellControl) cellControl);
internalViewRefreshImage((ButtonCellControl) cellControl);
}//internalViewRefresh()//
/**
* Refreshes the button selection.
* @param cellControl The control to update with the latest state.
*/
protected void internalViewRefreshSelection(ButtonCellControl cellControl) {
if((isStateful) && (selection.refresh(cellControl.getRowValue()))) {
cellControl.refreshSelection();
}//if//
}//internalViewRefreshSelection()//
/**
* Refreshes the button image.
* @param cellControl The control to update with the latest state.
*/
protected void internalViewRefreshImage(ButtonCellControl cellControl) {
if(image.isMulti() && image.refresh(cellControl.getRowValue())) {
cellControl.refreshImage();
}//if//
}//internalViewRefreshImage()//
/**
* Refreshes the button image.
*/
protected void internalViewRefreshImage() {
if(image.isSingle() && image.refresh(null)) {
if(imageHolder == null) {
imageHolder = new ResourceHolder(this);
}//if//
imageHolder.setValue(image.getValue(null));
}//if//
}//internalViewRefreshImage()//
/**
* Refreshes the button text.
* @param cellControl The control to update with the latest state.
*/
protected void internalViewRefreshText(ButtonCellControl cellControl) {
if(text.isMulti() && text.refresh(cellControl.getRowValue())) {
cellControl.refreshText();
}//if//
}//internalViewRefreshText()//
/**
* Refreshes the button text.
*/
protected void internalViewRefreshText() {
if(text.isSingle() && text.refresh(null)) {
if(textHolder == null) {
textHolder = new ResourceHolder(this);
}//if//
textHolder.setValue(text.getValue(null));
}//if//
}//internalViewRefreshText()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.MultiResourceAssociation, java.lang.Object)
*/
protected void internalOnValueChanged(MultiResourceAssociation resourceAssociation, Object alteredItem, Object data, boolean isUpdate) {
if(text.hasAssociation(resourceAssociation)) {
ButtonCellControl control = (ButtonCellControl) getCellControl(alteredItem);
if(control != null) {
internalViewRefreshText(control);
}//if//
}//if//
else if(image.hasAssociation(resourceAssociation)) {
ButtonCellControl control = (ButtonCellControl) getCellControl(alteredItem);
if(control != null) {
internalViewRefreshImage(control);
}//if//
}//else if//
else if(resourceAssociation == selection) {
ButtonCellControl control = (ButtonCellControl) getCellControl(alteredItem);
if(control != null) {
internalViewRefreshSelection(control);
}//if//
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, alteredItem, data, isUpdate);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(text.hasAssociation(resourceAssociation)) {
internalViewRefreshText();
}//if//
else if(image.hasAssociation(resourceAssociation)) {
internalViewRefreshImage();
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else/
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalResourceHolderChanged(com.foundation.view.swt.ResourceHolder, java.lang.Object, java.lang.Object)
*/
protected void internalResourceHolderChanged(ResourceHolder resourceHolder, Object oldValue, Object newValue, int flags) {
if(resourceHolder == textHolder) {
IIterator iterator = getCellControlIterator();
//Update the existing controls.//
while(iterator.hasNext()) {
ButtonCellControl cellControl = (ButtonCellControl) iterator.next();
cellControl.refreshText();
}//while//
}//if//
else if(resourceHolder == imageHolder) {
IIterator iterator = getCellControlIterator();
if(swtImage != null) {
swtImage.dispose();
}//if//
if(newValue != null) {
swtImage = SwtUtilities.getImage(getDisplay(), (JefImage) newValue);
}//if//
//Update the existing controls.//
while(iterator.hasNext()) {
ButtonCellControl cellControl = (ButtonCellControl) iterator.next();
cellControl.refreshImage();
}//while//
}//else if//
else {
super.internalResourceHolderChanged(resourceHolder, oldValue, newValue, flags);
}//else//
}//internalResourceHolderChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#paintCell(java.lang.Object, org.eclipse.swt.graphics.GC)
*/
public void paintCell(Object rowObject, GC graphics) {
}//paintCell()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#supportsControl()
*/
public boolean supportsControl() {
return true;
}//supportsControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#initializeControl(java.lang.Object)
*/
protected CellControl initializeControl(Object rowObject) {
return new ButtonCellControl(new Button(getCellContainer().getSwtComposite(rowObject), style), rowObject);
}//createControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#registerRowItem(java.lang.Object, java.lang.Object)
*/
public void registerRowItem(Object rowItem, Object data) {
super.registerRowItem(rowItem, data);
text.registerItem(rowItem, data);
image.registerItem(rowItem, data);
selection.registerItem(rowItem, data);
}//registerRowItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#unregisterRowItem(java.lang.Object)
*/
public void unregisterRowItem(Object rowItem) {
super.unregisterRowItem(rowItem);
text.unregisterItem(rowItem);
image.unregisterItem(rowItem);
selection.unregisterItem(rowItem);
}//unregisterRowItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#unregisterRowItems()
*/
public void unregisterRowItems() {
super.unregisterRowItems();
text.unregisterAllItems();
image.unregisterAllItems();
selection.unregisterAllItems();
}//unregisterRowItems()//
}//CellButton//

View File

@@ -0,0 +1,964 @@
/*
* Copyright (c) 2007,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.cell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.widgets.Combo;
import com.common.comparison.Comparator;
import com.common.thread.IRunnable;
import com.common.util.ICollection;
import com.common.util.IIndexedCollection;
import com.common.util.IIterator;
import com.common.util.LiteHashSet;
import com.common.util.LiteList;
import com.foundation.util.IInlineCollectionObservable;
import com.foundation.util.IInlineCollectionObserver;
import com.foundation.util.IInlineIndexedCollectionObservable;
import com.foundation.util.IInlineIndexedCollectionObserver;
import com.foundation.view.MultiAssociationContainer;
import com.foundation.view.MultiResourceAssociation;
import com.foundation.view.ResourceAssociation;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
import com.foundation.view.swt.ICellContainer;
public class CellComboBox extends CellComponent {
public static final int STYLE_DROP_DOWN = SWT.DROP_DOWN;
public static final int STYLE_READ_ONLY = SWT.READ_ONLY;
public static final int STYLE_SIMPLE = SWT.SIMPLE;
/** Used by the hidden data to identify when the previous value has not yet been assigned a value. */
protected static final Object UNSET_VALUE = new Object();
/** The association containing the collection of items displayed to the user. */
private SingleResourceAssociation collection = new SingleResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_OBJECT, false, null);
/** The association containing the selected collection item(s). */
private MultiResourceAssociation selection = new MultiResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_OBJECT, true, null);
/** Converts the collection item to a string used to show the item to the user. */
protected MultiResourceAssociation itemText = new MultiResourceAssociation(this, this, getViewContext(), ResourceAssociation.TYPE_TEXT, false, null);
/** Whether the user can type a custom selection. If this is true and the selection attribute is not a String type then the user input must match a list item's text. */
private boolean allowUserItems = false;
/** Whether the selection should be automatically synchronized from the view to the model when altered in the view. */
private boolean autoSynchronizeSelection = false;
/** The number of milliseconds of delay before auto synchronizing the selection. */
private long autoSynchronizeSelectionDelay = 0;
/** A reference to the last item collection known to this component. */
private ICollection currentCollection = null;
/** A handler that will redirect collection events to this collection component. */
private final CollectionHandler collectionHandler = new CollectionHandler();
/** A flag indicating whether the collection event hooks should ignore input temporarily. */
protected boolean suspendCollectionHooks = false;
/** A mapping of collection values by the control assigned indexes. */
private IIndexedCollection valueByIndexMap = new LiteList(100);
/** The set of all values. This is used only to track duplicates. */
private LiteHashSet valueSet = new LiteHashSet(100, LiteHashSet.DEFAULT_LOAD_FACTOR, Comparator.getIdentityComparator(), LiteHashSet.STYLE_COUNT_DUPLICATES);
/** The set of texts displayed by the combo box in the list. */
private String[] texts = null;
/** The text limit to use with the combo box controls. */
private int textLimit = -1;
/** The style used to create controls. */
private int style = 0;
/**
* Captures and directs item collection changes.
*/
private final class CollectionHandler implements IInlineCollectionObserver, IInlineIndexedCollectionObserver {
/**
* CollectionHandler constructor.
*/
private CollectionHandler() {
}//CollectionHandler()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#valueAdded(java.lang.Object, int)
*/
public void valueAdded(Object value, int index) {
if(!suspendCollectionHooks) {
itemAdded(value, index);
}//if//
}//valueAdded()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineCollectionObserver#valueAdded(java.lang.Object)
*/
public void valueAdded(Object value) {
if(!suspendCollectionHooks) {
itemAdded(value, -1);
}//if//
}//valueAdded()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#valueRemoved(java.lang.Object, int)
*/
public void valueRemoved(Object value, int index) {
if(!suspendCollectionHooks) {
itemRemoved(value, index);
}//if//
}//valueRemoved()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineCollectionObserver#valueRemoved(java.lang.Object)
*/
public void valueRemoved(Object value) {
if(!suspendCollectionHooks) {
itemRemoved(value, -1);
}//if//
}//valueRemoved()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#allRemoved()
*/
public void removingAll() {
if(!suspendCollectionHooks) {
itemAllRemoved();
}//if//
}//removingAll()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineIndexedCollectionObserver#valuesSorted(int[])
*/
public void valuesSorted(int[] mapping) {
if(!suspendCollectionHooks) {
itemSorted(mapping);
}//if//
}//valuesSorted()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineCollectionObserver#startChanges(int)
*/
public void startChanges(int changeCount) {
}//startChanges()//
/* (non-Javadoc)
* @see com.foundation.util.IInlineCollectionObserver#stopChanges()
*/
public void stopChanges() {
postCollectionChanged();
}//stopChanges()//
}//CollectionHandler//
public class ComboBoxCellControl extends CellControl implements SelectionListener, ModifyListener {
/** Used to stop selection events from being handled while the items are being changed. */
private boolean suspendSelectionEvents = false;
/** The task that auto synchronizes the selection after a short delay. */
protected Task autoSynchronizeSelectionTask = null;
/**
* ComboBoxCellControl constructor.
* @param control The control being encapsulated.
* @param rowObject The data model the control interacts with.
*/
public ComboBoxCellControl(Combo control, Object rowObject) {
super(control, rowObject);
getSwtCombo().addSelectionListener(this);
getSwtCombo().addModifyListener(this);
}//ComboBoxCellControl()//
protected void controlRemoveAll() {
suspendSelectionEvents = true;
getSwtCombo().removeAll();
suspendSelectionEvents = false;
}//controlRemoveAll()//
protected void controlSetItems(Object[] items) {
String[] itemTexts = new String[items.length];
System.arraycopy(items, 0, itemTexts, 0, itemTexts.length);
suspendSelectionEvents = true;
try {
getSwtCombo().setItems(itemTexts);
}//try//
finally {
suspendSelectionEvents = false;
}//finally//
}//controlSetItems()//
protected void controlSetItem(int index, Object itemData) {
suspendSelectionEvents = true;
getSwtCombo().setItem(index, (String) itemData);
suspendSelectionEvents = false;
}//controlSetItem()//
protected void controlAddItem(Object itemData, int index) {
suspendSelectionEvents = true;
getSwtCombo().add((String) itemData, index);
suspendSelectionEvents = false;
}//controlAddItem()//
protected void controlAddItem(Object itemData) {
suspendSelectionEvents = true;
getSwtCombo().add((String) itemData);
suspendSelectionEvents = false;
}//controlAddItem()//
protected void controlRemoveItem(int index) {
suspendSelectionEvents = true;
getSwtCombo().remove(index);
suspendSelectionEvents = false;
}//controlRemoveItem()//
protected int controlGetSelection() {
return getSwtCombo().getSelectionIndex();
}//controlGetSelection()//
protected void controlSetSelection(int index) {
suspendSelectionEvents = true;
if(index == -1) {
getSwtCombo().deselectAll();
}//if//
else {
getSwtCombo().select(index);
}//else//
suspendSelectionEvents = false;
}//controlSetSelection()//
protected void controlSetSelection(String text) {
suspendSelectionEvents = true;
if(text == null) {
getSwtCombo().deselectAll();
}//if//
else {
getSwtCombo().setText(text);
}//else//
suspendSelectionEvents = false;
}//controlSetSelection()//
protected int controlGetSelectionCount() {
return getSwtCombo().getText().length() > 0 ? 1 : 0;
}//controlGetSelectionCount()//
/**
* Gets the combo control.
* @return The combo being encapsulated.
*/
public Combo getSwtCombo() {
return (Combo) getSwtControl();
}//getSwtCombo()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent.CellControl#release()
*/
public void release() {
if(!getAutoSynchronizeSelection()) {
synchronizeSelection();
}//if//
if((getSwtCombo() != null) && (!getSwtCombo().isDisposed())) {
getSwtCombo().removeSelectionListener(this);
getSwtCombo().removeModifyListener(this);
}//if//
//Ignore any pending synchronizations.//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
autoSynchronizeSelectionTask = null;
}//if//
}//synchronized//
super.release();
}//release()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent.CellControl#refresh()
*/
public void refresh() {
refreshCollection();
refreshSelection();
super.refresh();
}//refresh()//
/**
* Refreshes the selection.
*/
public void refreshSelection() {
Object selectedModelItem = selection.getValue(getRowValue());
int index = getItemIndex(selectedModelItem);
controlSetSelection(index);
}//refreshSelection()//
/**
* Refreshes the collection.
*/
public void refreshCollection() {
suspendSelectionEvents = true;
if(texts != null) {
getSwtCombo().setItems(texts);
}//if//
else {
getSwtCombo().removeAll();
}//else//
suspendSelectionEvents = false;
}//refreshCollection()//
/**
* Forces any pending synchronizations to complete.
*/
public void synchronize() {
if(!getAutoSynchronizeSelection()) {
synchronizeSelection();
}//if//
else {
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
autoSynchronizeSelectionTask.execute();
autoSynchronizeSelectionTask = null;
}//if//
}//synchronized//
}//else//
}//synchronize()//
/**
* 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() && (getSwtCombo().getSelectionIndex() == -1) && (getSwtCombo().getText() != null) && (getSwtCombo().getText().length() > 0);
}//hasCustomSelection()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent event) {
widgetSelected(event);
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent event) {
final Object rowItem = getRowValue();
if(getAutoSynchronizeSelection()) {
if(getAutoSynchronizeSelectionDelay() > 0) {
int selectionIndex = getSwtCombo().getSelectionIndex();
final Object modelSelection = selectionIndex != -1 ? getItemAtIndex(selectionIndex) : null;
final String customSelection = hasCustomSelection() ? getSwtCombo().getText() : null;
//Start a task to send the selection to the server after a short delay. This will reduce the overhead of auto synchronizing the selection.//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
}//if//
autoSynchronizeSelectionTask = new Task() {
public void execute() {
//Make sure that this task is still valid and is not being superceeded.//
synchronized(CellComboBox.this) {
if(autoSynchronizeSelectionTask == this) {
//Cleanup after the task.//
autoSynchronizeSelectionTask = null;
getEventLoop().executeAsync(new IRunnable() {
public Object run() {
if((customSelection != null) || (modelSelection != selection.getValue(rowItem))) {
//Send the model the newest selection.//
selection.setValue(rowItem, modelSelection);
}//if//
return null;
}//run()//
});
}//if//
}//synchronized//
}//run()//
};
addTask(autoSynchronizeSelectionTask, getAutoSynchronizeSelectionDelay());
}//synchronized//
}//if//
else {
synchronizeSelection();
}//else//
}//if//
}//widgetSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent)
*/
public void modifyText(ModifyEvent event) {
if(!suspendSelectionEvents) {
//TODO: Shouldn't this always call widgetSelected(null)?
if(getSwtCombo().getSelectionIndex() == -1) {
widgetSelected(null);
}//if//
}//if//
}//modifyText()//
/**
* 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() {
Object rowItem = getRowValue();
if(hasCustomSelection()) {
String text = getSwtCombo().getText();
selection.setValue(rowItem, text);
}//if//
else {
int selectionIndex = getSwtCombo().getSelectionIndex();
Object modelSelection = selectionIndex != -1 ? getItemAtIndex(selectionIndex) : null;
if(modelSelection != selection.getValue(rowItem)) {
selection.setValue(rowItem, modelSelection);
}//if//
}//else//
}//synchronizeSelection()//
}//ComboBoxCellControl//
/**
* ComboBox constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_DROP_DOWN
* @see #STYLE_READ_ONLY
* @see #STYLE_SIMPLE
*/
public CellComboBox(ICellContainer parent, String name, int style) {
super(parent, name, style);
this.style = style;
setAllowUserItems(!((style & STYLE_READ_ONLY) > 0));
}//ComboBox()//
/**
* Sets the association container used to access the displayed collection.
* @param container The collection association metadata.
*/
public void setCollectionAssociation(SingleAssociationContainer container) {
verifyThread();
this.collection.setAssociations(container);
}//setCollectionAssociation()//
/**
* Sets the association container used to access the selection.
* @param container The selection association metadata.
*/
public void setSelectionAssociation(MultiAssociationContainer container) {
verifyThread();
this.selection.setAssociations(container);
}//setSelectionAssociation()//
/**
* Sets the association container used to access the item text.
* @param container The item text association metadata.
*/
public void setItemTextAssociation(MultiAssociationContainer container) {
verifyThread();
this.itemText.setAssociations(container);
}//setItemTextAssociation()//
/**
* Gets the component text size limit.
* @return The maximum number of characters allowed in the text.
*/
public Integer getTextLimit() {
verifyThread();
return new Integer(textLimit);
}//getTextLimit()//
/**
* Sets the component text size limit.
* @param textLimit The maximum number of characters allowed in the text.
*/
public void setTextLimit(Integer textLimit) {
IIterator iterator = getCellControlIterator();
verifyThread();
this.textLimit = textLimit.intValue();
//Update existing controls.//
while(iterator.hasNext()) {
((ComboBoxCellControl) iterator.next()).getSwtCombo().setTextLimit(this.textLimit);
}//while//
}//setTextLimit()//
/**
* Gets whether the selection will automatically synchronize.
* @return Whether the selection is automatically synchronized from the view to the model when changed, or whether it must be manually synchronized.
*/
protected boolean getAutoSynchronizeSelection() {
return autoSynchronizeSelection;
}//getAutoSynchronizeSelection()//
/**
* Sets whether the selection will automatically synchronize.
* @param autoSynchronizeSelection Whether the selection is automatically synchronized from the view to the model when changed, or whether it must be manually synchronized.
*/
public void setAutoSynchronizeSelection(boolean autoSynchronizeSelection) {
verifyThread();
this.autoSynchronizeSelection = autoSynchronizeSelection;
}//setAutoSynchronizeSelection()//
/**
* Gets the number of milliseconds to wait before automatically synchronizing selection changes. This must be a number between zero and ten thousand where zero synchronizes without delay.
* @return The number of milliseconds of delay when auto synchronizing the selection.
*/
protected long getAutoSynchronizeSelectionDelay() {
return autoSynchronizeSelectionDelay;
}//getAutoSynchronizeSelectionDelay()//
/**
* Sets the number of milliseconds to wait before automatically synchronizing selection changes. This must be a number between zero and ten thousand where zero synchronizes without delay.
* @param autoSynchronizeSelectionDelay The number of milliseconds of delay when auto synchronizing the selection.
*/
public void setAutoSynchronizeSelectionDelay(long autoSynchronizeSelectionDelay) {
verifyThread();
if(autoSynchronizeSelectionDelay < 0) {
autoSynchronizeSelectionDelay = 0;
}//if//
else if(autoSynchronizeSelectionDelay > 10000) {
autoSynchronizeSelectionDelay = 10000;
}//else if//
this.autoSynchronizeSelectionDelay = autoSynchronizeSelectionDelay;
}//setAutoSynchronizeSelectionDelay()//
/**
* Gets the index for the given item.
* @param item The item whose index is required.
* @return The index for the given item.
*/
protected int getItemIndex(Object item) {
return valueByIndexMap.getIndexOf(item);
}//getItemIndex()//
/**
* Gets the model item for the given collection index.
* @param index The zero based index in the collection.
* @return The model value at the given index.
*/
protected Object getItemAtIndex(int index) {
return valueByIndexMap.get(index);
}//getItemAtIndex()//
/**
* Registers the collection item with any and all listeners and associations.
* @param item The item in the collection being displayed.
* @param data The data to associated with the registration.
*/
protected void registerItem(Object item, Object data) {
itemText.registerItem(item, data);
}//registerItem()//
/**
* Unregisters the collection item with any and all listeners and associations.
* @param item The item no longer in the collection being displayed.
*/
protected void unregisterItem(Object item) {
itemText.unregisterItem(item);
}//unregisterItem()//
/**
* Unregisters all the collection items with any and all listeners and associations.
*/
protected void unregisterItems() {
itemText.unregisterAllItems();
}//unregisterItems()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#registerRowItem(java.lang.Object, java.lang.Object)
*/
public void registerRowItem(Object rowItem, Object data) {
selection.registerItem(rowItem, data);
super.registerRowItem(rowItem, data);
}//registerRowItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#unregisterRowItem(java.lang.Object)
*/
public void unregisterRowItem(Object rowItem) {
selection.unregisterItem(rowItem);
super.unregisterRowItem(rowItem);
}//unregisterRowItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#unregisterRowItems()
*/
public void unregisterRowItems() {
selection.unregisterAllItems();
super.unregisterRowItems();
}//unregisterRowItems()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalOnValueChanged(com.foundation.view.MultiResourceAssociation, java.lang.Object)
*/
protected void internalOnValueChanged(MultiResourceAssociation resourceAssociation, Object alteredItem, Object data, boolean isUpdate) {
if(resourceAssociation == itemText) {
internalViewRefreshItemText(alteredItem);
}//if//
else if(resourceAssociation == selection) {
internalViewRefreshSelection(alteredItem);
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, alteredItem, data, isUpdate);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == collection) {
internalViewRefreshCollection();
}//if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
super.internalViewInitialize();
collection.initialize();
selection.initialize();
itemText.initialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewRelease()
*/
protected void internalViewRelease() {
super.internalViewRelease();
collection.release();
selection.release();
itemText.release();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalViewRefreshCollection();
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewRefresh(com.foundation.view.swt.cell.CellComponent.CellControl)
*/
protected void internalViewRefresh(CellControl cellControl) {
super.internalViewRefresh(cellControl);
internalViewRefreshSelection(cellControl.getRowValue());
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
*/
protected void internalViewSynchronize() {
super.internalViewSynchronize();
//TODO: Iterate over the controls and synchronize them.
internalViewSynchronizeSelection();
}//internalViewSynchronize()//
/**
* Synchronizes the selections for all combo boxs.
*/
protected void internalViewSynchronizeSelection() {
if(!getAutoSynchronizeSelection()) {
IIterator iterator = getCellControlIterator();
while(iterator.hasNext()) {
ComboBoxCellControl control = (ComboBoxCellControl) iterator.next();
control.synchronizeSelection();
}//while//
}//if//
}//internalViewSynchronizeSelection()//
/**
* Refreshes the collection.
*/
protected final void internalViewRefreshCollection() {
if(collection.refresh()) {
ICollection oldCollection = currentCollection;
IIterator controlIterator = getCellControlIterator();
if((collection.getValue() == null) || (collection.getValue() instanceof ICollection)) {
currentCollection = (ICollection) collection.getValue();
}//if//
else if(collection.getValue() instanceof Object[]) {
currentCollection = new LiteList((Object[]) collection.getValue());
}//else if//
else {
currentCollection = new LiteList(collection.getValue());
}//else//
if(oldCollection != null) {
unregisterItems();
unregisterCollectionHooks(oldCollection, collectionHandler);
}//if//
if(currentCollection != null) {
IIterator iterator = currentCollection.iterator();
suspendCollectionHooks = true;
registerCollectionHooks(currentCollection, collectionHandler);
suspendCollectionHooks = false;
while(iterator.hasNext()) {
Object next = iterator.next();
registerItem(next, null);
}//while//
}//if//
internalViewRefreshCollection(currentCollection, oldCollection);
postCollectionChanged();
while(controlIterator.hasNext()) {
ComboBoxCellControl control = (ComboBoxCellControl) controlIterator.next();
control.refresh();
}//while//
}//if//
}//internalViewRefreshCollection()//
/**
* Refreshes the collection.
* @param newCollection The new collection of items in the component.
* @param oldCollection The old collection of items in the component.
*/
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)) {
IIterator iterator = newCollection.iterator();
//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();
valueSet.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(valueSet.containsValue(value)) {
valueSet.add(value);
}//if//
else {
valueSet.add(value);
valueByIndexMap.add(value);
}//else//
}//while//
texts = new String[valueByIndexMap.getSize()];
for(int index = 0; index < valueByIndexMap.getSize(); index++) {
texts[index] = getItemText(valueByIndexMap.get(index));
}//for//
}//if//
else {
//Remove all existing items.//
texts = null;
}//else//
}//internalViewRefreshCollection()//
/**
* Gets the text associated with the given collection item for use in the display.
* @param item The item whose data is to be collected.
* @return The text that represents the item in the display.
*/
protected String getItemText(Object item) {
String result = null;
itemText.refresh(item);
result = (String) itemText.getValue(item);
if(result == null) {
result = item != null ? item.toString() : "";
}//if//
return result;
}//getItemText()//
/**
* Refreshes the selection.
* @param externalRowObject The the model object for the row in which the combo box resides whose selection we are refreshing.
*/
protected final void internalViewRefreshSelection(Object externalRowObject) {
if(selection.refresh(externalRowObject)) {
Object selectedItem = selection.getValue(externalRowObject);
internalViewRefreshSelection(externalRowObject, selectedItem);
}//if//
}//internalViewRefreshSelection()//
/**
* Refreshes the selection.
* @param externalRowObject The model object for the row in which the combo box resides whose selection we are refreshing.
* @param selectedItem The new selected item.
*/
protected void internalViewRefreshSelection(Object externalRowObject, Object selectedItem) {
ComboBoxCellControl control = (ComboBoxCellControl) getCellControl(externalRowObject);
if(control != null) {
if(selectedItem != null) {
int index = getItemIndex(selectedItem);
if(index == -1) {
if(getAllowUserItems()) {
control.controlSetSelection(selectedItem.toString());
}//if//
else {
control.controlSetSelection(-1);
}//else//
}//if//
else {
control.controlSetSelection(index);
}//else//
}//if//
else {
//No selection.//
control.controlSetSelection(-1);
}//else//
}//if//
}//internalViewRefreshSelection()//
/**
* Refreshes the item text.
* @param item The collection item whose text needs refreshing.
*/
protected void internalViewRefreshItemText(Object item) {
String itemText = getItemText(item);
int itemIndex = valueByIndexMap.getIndexOf(item);
IIterator controlIterator = getCellControlIterator();
texts[itemIndex] = itemText;
while(controlIterator.hasNext()) {
ComboBoxCellControl control = (ComboBoxCellControl) controlIterator.next();
control.refresh();
}//while//
}//internalViewRefreshItemText()//
/**
* Called after the collection of combo values has been altered.
*/
protected void postCollectionChanged() {
/*
if((currentCollection != null) && (currentCollection.getSize() > 0)) {
IIterator iterator = currentCollection.iterator();
texts = new String[currentCollection.getSize()];
for(int index = 0; index < texts.length; index++) {
Object nextText = itemText.getValue(iterator.next());
texts[index] = nextText != null ? nextText.toString() : "";
}//for//
}//if//
else {
texts = null;
}//else//
*/
}//postCollectionChanged()//
/**
* Registers the collection hooks that allow the component to receive collection changes.
* @param collection The collection whose associated hooks are to be added.
*/
protected void registerCollectionHooks(ICollection collection, Object listener) {
if(collection instanceof IInlineIndexedCollectionObservable) {
((IInlineIndexedCollectionObservable) collection).addCollectionObserver((IInlineIndexedCollectionObserver) listener);
}//if//
else if(collection instanceof IInlineCollectionObservable) {
((IInlineCollectionObservable) collection).addCollectionObserver((IInlineCollectionObserver) listener);
}//else if//
}//registerCollectionHooks()//
/**
* Unregisters the collection hooks that allow the component to receive collection changes.
* @param collection The collection whose associated hooks are to be removed.
*/
protected void unregisterCollectionHooks(ICollection collection, Object listener) {
if(collection instanceof IInlineIndexedCollectionObservable) {
((IInlineIndexedCollectionObservable) collection).removeCollectionObserver((IInlineIndexedCollectionObserver) listener);
}//if//
else if(collection instanceof IInlineCollectionObservable) {
((IInlineCollectionObservable) collection).removeCollectionObserver((IInlineCollectionObserver) listener);
}//else if//
}//unregisterCollectionHooks()//
/**
* Called when an item is added to the primary collection.
* @param item The item added.
* @param index The index of the item if available, otherwise -1.
*/
protected void itemAdded(Object item, int index) {
if(valueSet.containsValue(item)) {
valueSet.add(item);
}//if//
else {
String[] texts = new String[(this.texts != null ? this.texts.length : 0) + 1];
if((index < 0) || (index >= valueByIndexMap.getSize())) {
index = valueByIndexMap.getSize();
}//if//
else {
//Rebuild the value by index map.//
}//else//
valueSet.add(item);
valueByIndexMap.add(index, item);
registerItem(item, null);
if(this.texts != null) {
if(index != 0) {
System.arraycopy(this.texts, 0, texts, 0, index);
}//if//
if(index != texts.length - 1) {
System.arraycopy(this.texts, index, texts, index + 1, this.texts.length - index);
}//if//
}//if//
texts[index] = getItemText(item);
this.texts = texts;
}//else//
}//itemAdded()//
/**
* Called when an item is removed from the primary collection.
* @param item The item removed.
* @param index The index of the item if available, otherwise -1.
*/
protected void itemRemoved(Object item, int index) {
valueSet.remove(item);
if(!valueSet.containsValue(item)) {
String[] texts = this.texts.length == 1 ? null : new String[this.texts.length - 1];
if(index < 0) {
index = valueByIndexMap.getIndexOf(item);
}//if//
valueByIndexMap.remove(index);
unregisterItem(item);
if(texts != null) {
if(index != 0) {
System.arraycopy(this.texts, 0, texts, 0, index);
}//if//
if(index != texts.length) {
System.arraycopy(this.texts, index + 1, texts, index, texts.length - index);
}//if//
}//if//
this.texts = texts;
}//if//
}//itemRemoved()//
/**
* Called when all the items are removed from the primary collection.
*/
protected void itemAllRemoved() {
unregisterItems();
valueByIndexMap.removeAll();
valueSet.removeAll();
texts = null;
}//itemAllRemoved()//
/**
* Called when the items in the primary collection have been externally sorted.
* @param mapping A mapping of new positions to old positions. The index is the new position and the value is the old position.
*/
protected void itemSorted(int[] mapping) {
//TODO: Implement.
}//itemSorted()//
/**
* Determines whether the control allows the user to type in custom items (combobox).
* @return Whether users will be allowed to type in a custom value.
*/
protected boolean getAllowUserItems() {
return allowUserItems;
}//getAllowUserItems()//
/**
* Determines whether the control allows the user to type in custom items (combobox).
* @param allowUserItems Whether users will be allowed to type in a custom value.
*/
protected void setAllowUserItems(boolean allowUserItems) {
this.allowUserItems = allowUserItems;
}//setAllowUserItems()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#initializeControl(java.lang.Object)
*/
protected CellControl initializeControl(Object rowValue) {
return new ComboBoxCellControl(new Combo(getCellContainer().getSwtComposite(rowValue), style), rowValue);
}//initializeControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#supportsControl()
*/
public boolean supportsControl() {
return true;
}//supportsControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#paintCell(java.lang.Object, org.eclipse.swt.graphics.GC)
*/
public void paintCell(Object rowObject, GC graphics) {
}//paintCell()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractComponent#getName()
*/
public String getName() {
return "__CellComboBox__";
}//getName()//
}//ComboBox//

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,342 @@
/*
* Copyright (c) 2007,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.cell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import com.common.util.IIterator;
import com.common.util.IList;
import com.common.util.LiteList;
import com.foundation.view.swt.ICellContainer;
import com.foundation.view.swt.Layout;
public abstract class CellContainer extends CellComponent implements ICellContainer {
public static final int STYLE_H_SCROLL = SWT.H_SCROLL;
public static final int STYLE_V_SCROLL = SWT.V_SCROLL;
public static final int STYLE_NO_BACKGROUND = SWT.NO_BACKGROUND;
public static final int STYLE_NO_FOCUS = SWT.NO_FOCUS;
public static final int STYLE_NO_MERGE_PAINTS = SWT.NO_MERGE_PAINTS;
public static final int STYLE_NO_REDRAW_RESIZE = SWT.NO_REDRAW_RESIZE;
public static final int STYLE_NO_RADIO_GROUP = SWT.NO_RADIO_GROUP;
public static final int STYLE_EMBEDDED = SWT.EMBEDDED;
public static final int STYLE_DOUBLE_BUFFERED = SWT.DOUBLE_BUFFERED;
public static final int INHERIT_NONE = 0;
public static final int INHERIT_DEFAULT = 1;
public static final int INHERIT_FORCE = 2;
/** A collection of components contained by this container. */
private IList cellComponents = null;
/** The layout used for the cells. */
private Layout layout = null;
/** The inheritance of the background for this container. */
private int inheritType = 0;
/** The ordering of the contained cell components for tabbing. */
private CellComponent[] tabOrder = null;
public abstract class ContainerControl extends CellControl {
/**
* ContainerControl constructor.
* @param control The control being encapsulated.
* @param rowValue The data model the control interacts with.
*/
public ContainerControl(Composite control, Object rowValue) {
super(control, rowValue);
}//ContainerControl()//
/**
* Sets the background inheritance for all children.
* @param inherit Whether the background of this composite should be inherited by all child controls. The default value will cause children that don't specify otherwise to inherit the background.
* @see #INHERIT_NONE
* @see #INHERIT_DEFAULT
* @see #INHERIT_FORCE
*/
public void setInheritBackground(int inheritType) {
int mode = inheritType == INHERIT_FORCE ? SWT.INHERIT_FORCE : inheritType == INHERIT_DEFAULT ? SWT.INHERIT_DEFAULT : SWT.INHERIT_NONE;
getSwtComposite().setBackgroundMode(mode);
}//setInheritBackground()//
/**
* Gets the SWT composite for this cell.
* @return The composite being encapsulated.
*/
public Composite getSwtComposite() {
return (Composite) getSwtControl();
}//getSwtComposite()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent.CellControl#initialize()
*/
public void initialize() {
if(CellContainer.this.getLayout() != null) {
getSwtComposite().setLayout(CellContainer.this.getLayout().createLayout(getRowValue()));
}//if//
super.initialize();
setInheritBackground(CellContainer.this.inheritType);
//Initialize the child cell components.//
for(int index = 0; index < getCellComponents().getSize(); index++) {
((CellComponent) getCellComponents().get(index)).getCellControl(getRowValue()).initialize();
}//for//
if((getTabOrder() != null) && (getTabOrder().length > 0)) {
Control[] tabList = new Control[getTabOrder().length];
for(int index = 0; index < getTabOrder().length; index++) {
tabList[index] = getTabOrder()[index].getCellControl(getRowValue()).getSwtControl();
}//for//
getSwtComposite().setTabList(tabList);
}//if//
}//initialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent.CellControl#refresh()
*/
public void refresh() {
super.refresh();
//Refresh the child cell components.//
for(int index = 0; index < getCellComponents().getSize(); index++) {
((CellComponent) getCellComponents().get(index)).getCellControl(getRowValue()).refresh();
}//for//
}//refresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent.CellControl#release()
*/
public void release() {
super.release();
//Release the child cell components.//
for(int index = 0; index < getCellComponents().getSize(); index++) {
CellControl cellControl = ((CellComponent) getCellComponents().get(index)).getCellControl(getRowValue());
if(cellControl != null) {
cellControl.release();
}//if//
}//for//
}//release()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent.CellControl#synchronize()
*/
public void synchronize() {
//Synchronize the child cell components.//
for(int index = 0; index < getCellComponents().getSize(); index++) {
((CellComponent) getCellComponents().get(index)).getCellControl(getRowValue()).synchronize();
}//for//
}//synchronize()//
}//ContainerControl//
/**
* CellContainer constructor.
*/
public CellContainer() {
}//CellContainer()//
/**
* CellContainer constructor.
* @param parent The parent container for this container.
* @param name The component's name. This allows lookup of components in the view by the name.
* @param style The component style.
*/
public CellContainer(ICellContainer parent, String name, int style) {
super(parent, name, style);
}//CellContainer()//
/**
* Sets the background inheritance for all children.
* @param inherit Whether the background of this composite should be inherited by all child controls. The default value will cause children that don't specify otherwise to inherit the background.
* @see #INHERIT_NONE
* @see #INHERIT_DEFAULT
* @see #INHERIT_FORCE
*/
public void setInheritBackground(int inheritType) {
IIterator iterator = getCellControlIterator();
//Update the existing controls.//
while(iterator.hasNext()) {
ContainerControl containerControl = (ContainerControl) iterator.next();
containerControl.setInheritBackground(inheritType);
}//while//
this.inheritType = inheritType;
}//setInheritBackground()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#paintCell(java.lang.Object, org.eclipse.swt.graphics.GC)
*/
public void paintCell(Object rowObject, GC graphics) {
//Does nothing. TODO: Should some components of a cell container be paintable and others are not?
}//paintCell()//
/* (non-Javadoc)
* @see com.foundation.view.swt.ICellContainer#getSwtComposite(java.lang.Object)
*/
public Composite getSwtComposite(Object rowObject) {
return ((ContainerControl) getCellControl(rowObject)).getSwtComposite();
}//getSwtComposite()//
/* (non-Javadoc)
* @see com.foundation.view.swt.ICellContainer#getSwtComposites()
*/
public IIterator getSwtComposites() {
final IIterator cellControlIterator = getCellControlIterator();
return new IIterator() {
public void resetToFront() {
cellControlIterator.resetToFront();
}//resetToFont()//
public boolean remove() {
return false;
}//remove()//
public Object next() {
return ((ContainerControl) cellControlIterator.next()).getSwtComposite();
}//next()//
public boolean hasNext() {
return cellControlIterator.hasNext();
}//hasNext()//
};
}//getSwtComposites()//
/* (non-Javadoc)
* @see com.foundation.view.swt.ICompositeCellContainer#addCellComponent(com.foundation.view.swt.cell.CellComponent)
*/
public void addCellComponent(CellComponent component) {
if(cellComponents == null) {
cellComponents = new LiteList(10, 20);
}//if//
cellComponents.add(component);
}//addCellComponent()//
/**
* Gets the collection of cell components for this container.
* @return The cell components contained within this container.
*/
public IList getCellComponents() {
return cellComponents == null ? LiteList.EMPTY_LIST : cellComponents;
}//getCellComponents()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitializeAll()
*/
public void internalViewInitializeAll() {
super.internalViewInitializeAll();
if(cellComponents != null) {
for(int index = 0; index < cellComponents.getSize(); index++) {
((CellComponent) cellComponents.get(index)).internalViewInitializeAll();
}//for//
}//if//
}//internalViewInitializeAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefreshAll()
*/
public void internalViewRefreshAll() {
super.internalViewRefreshAll();
if(cellComponents != null) {
for(int index = 0; index < cellComponents.getSize(); index++) {
((CellComponent) cellComponents.get(index)).internalViewRefreshAll();
}//for//
}//if//
}//internalViewRefreshAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewReleaseAll()
*/
public void internalViewReleaseAll() {
super.internalViewReleaseAll();
if(cellComponents != null) {
for(int index = 0; index < cellComponents.getSize(); index++) {
((CellComponent) cellComponents.get(index)).internalViewReleaseAll();
}//for//
}//if//
}//internalViewReleaseAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronizeAll()
*/
public void internalViewSynchronizeAll() {
super.internalViewSynchronizeAll();
if(cellComponents != null) {
for(int index = 0; index < cellComponents.getSize(); index++) {
((CellComponent) cellComponents.get(index)).internalViewSynchronizeAll();
}//for//
}//if//
}//internalViewSynchronizeAll()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
super.internalViewInitialize();
if(getLayout() != null) {
getLayout().initialize();
}//if//
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
if(getLayout() != null) {
getLayout().refresh();
}//if//
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewRelease()
*/
protected void internalViewRelease() {
if(getLayout() != null) {
getLayout().release();
}//if//
super.internalViewRelease();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewRefresh(com.foundation.view.swt.cell.CellComponent.CellControl)
*/
protected void internalViewRefresh(CellControl cellControl) {
super.internalViewRefresh(cellControl);
((ContainerControl) cellControl).setInheritBackground(inheritType);
}//internalRefresh()//
/**
* Gets the layout used by the cell panels.
* @return The layout used, or null if the default layout is to be used.
*/
protected Layout getLayout() {
return layout;
}//getLayout()//
/**
* Sets the layout used by the cell panels.
* @param layout The layout used, or null if the default layout is to be used.
*/
public void setLayout(Layout layout) {
verifyThread();
if(this.layout != null) {
throw new RuntimeException("Cannot change the layout once set.");
}//if//
else if(isInitialized()) {
throw new RuntimeException("Cannot set the layout once the view is initialized.");
}//else if//
this.layout = layout;
}//setLayout()//
/**
* Gets the tab ordering for the cell components contained within the panel.
* @return The panel's component tab ordering.
*/
protected CellComponent[] getTabOrder() {
return tabOrder;
}//getTabOrder()//
/**
* Sets the tab ordering for the cell components contained within the panel.
* @param tabOrder The panel's component tab ordering.
*/
public void setTabOrder(CellComponent[] tabOrder) {
this.tabOrder = tabOrder;
}//setTabOrder()//
}//CellContainer//

View File

@@ -0,0 +1,369 @@
/*
* Copyright (c) 2007,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.cell;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.GC;
import com.common.thread.IRunnable;
import com.foundation.view.MultiAssociationContainer;
import com.foundation.view.MultiResourceAssociation;
import com.foundation.view.swt.ICellContainer;
public class CellDateTime extends CellComponent {
public static final int STYLE_DATE = SWT.DATE;
public static final int STYLE_TIME = SWT.TIME;
public static final int STYLE_CALENDAR = SWT.CALENDAR;
public static final int STYLE_SHORT = SWT.SHORT;
public static final int STYLE_MEDIUM = SWT.MEDIUM;
public static final int STYLE_LONG = SWT.LONG;
/** The date/time selection. */
private MultiResourceAssociation selection = new MultiResourceAssociation(this, this, getViewContext(), MultiResourceAssociation.TYPE_DATE, true, null);
/** The delay to be used when auto synchronizing changes to the text. */
private long autoSynchronizeSelectionDelay = 500;
/** The control style. */
private int style = 0;
/** Whether the year should be transfered to/from the view/model. */
private boolean includeYear = false;
/** Whether the month should be transfered to/from the view/model. */
private boolean includeMonth = false;
/** Whether the day should be transfered to/from the view/model. */
private boolean includeDay = false;
/** Whether the hour should be transfered to/from the view/model. */
private boolean includeHour = false;
/** Whether the minutes should be transfered to/from the view/model. */
private boolean includeMinute = false;
/** Whether the seconds should be transfered to/from the view/model. */
private boolean includeSecond = false;
public class DateTimeCellControl extends CellControl implements SelectionListener {
/** The task that auto synchronizes the selection after a short delay. */
private Task autoSynchronizeSelectionTask = null;
/** The calendar used to transfer the date/time data to/from the model. */
private Calendar calendar = GregorianCalendar.getInstance();
/**
* ButtonCellControl constructor.
* @param control The control being encapsulated.
* @param rowObject The data model the control interacts with.
*/
public DateTimeCellControl(org.eclipse.swt.widgets.DateTime control, Object rowObject) {
super(control, rowObject);
}//DateTimeCellControl()//
/**
* Gets the button control.
* @return The button being encapsulated.
*/
public org.eclipse.swt.widgets.DateTime getSwtDateTime() {
return (org.eclipse.swt.widgets.DateTime) getSwtControl();
}//getSwtDateTime()//
/**
* Sets the component's selection state.
* @param date The selected date.
*/
protected void controlSetSelection(Date date) {
date = date == null ? new Date() : date;
calendar.setTime(date);
if(includeYear) {
getSwtDateTime().setYear(calendar.get(Calendar.YEAR));
}//if//
if(includeMonth) {
getSwtDateTime().setMonth(calendar.get(Calendar.MONTH));
}//if//
if(includeDay) {
getSwtDateTime().setDay(calendar.get(Calendar.DAY_OF_MONTH));
}//if//
if(includeHour) {
getSwtDateTime().setHours(calendar.get(Calendar.HOUR_OF_DAY));
}//if//
if(includeMinute) {
getSwtDateTime().setMinutes(calendar.get(Calendar.MINUTE));
}//if//
if(includeSecond) {
getSwtDateTime().setSeconds(calendar.get(Calendar.SECOND));
}//if//
}//controlSetSelection()//
/**
* Initializes the control.
*/
public void initialize() {
getSwtDateTime().addSelectionListener(this);
super.initialize();
}//initialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent.CellControl#refresh()
*/
public void refresh() {
super.refresh();
refreshSelection();
}//refresh()//
/**
* Refreshes the selection value.
*/
public void refreshSelection() {
Date value = (Date) selection.getValue(getRowValue());
controlSetSelection(value == null ? new Date() : value);
}//refreshSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent.CellControl#release()
*/
public void release() {
if(!getSwtDateTime().isDisposed()) {
getSwtDateTime().removeSelectionListener(this);
}//if//
//Ignore any pending synchronizations.//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
autoSynchronizeSelectionTask = null;
}//if//
}//synchronized//
super.release();
}//release()//
/**
* Forces any pending synchronizations to complete.
*/
public void synchronize() {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
autoSynchronizeSelectionTask.execute();
autoSynchronizeSelectionTask = null;
}//if//
}//synchronize()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent event) {
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent event) {
if(includeYear) {
calendar.set(Calendar.YEAR, getSwtDateTime().getYear());
}//if//
if(includeMonth) {
calendar.set(Calendar.MONTH, getSwtDateTime().getMonth());
}//if//
if(includeDay) {
calendar.set(Calendar.DAY_OF_MONTH, getSwtDateTime().getDay());
}//if//
if(includeHour) {
calendar.set(Calendar.HOUR_OF_DAY, getSwtDateTime().getHours());
}//if//
if(includeMinute) {
calendar.set(Calendar.MINUTE, getSwtDateTime().getMinutes());
}//if//
if(includeSecond) {
calendar.set(Calendar.SECOND, getSwtDateTime().getSeconds());
}//if//
if(autoSynchronizeSelectionDelay > 0) {
final Date date = calendar.getTime();
//Start a task to send the text to the server after a short delay. This will reduce the overhead of auto synchronizing the selection.//
synchronized(this) {
if(autoSynchronizeSelectionTask != null) {
removeTask(autoSynchronizeSelectionTask);
}//if//
autoSynchronizeSelectionTask = new Task() {
public void execute() {
//Make sure that this task is still valid and is not being superceeded.//
synchronized(DateTimeCellControl.this) {
if(autoSynchronizeSelectionTask == this) {
//Cleanup after the task.//
autoSynchronizeSelectionTask = null;
getEventLoop().executeAsync(new IRunnable() {
public Object run() {
selection.setValue(getRowValue(), date);
return null;
}//run()//
});
}//if//
}//synchronized//
}//run()//
};
addTask(autoSynchronizeSelectionTask, autoSynchronizeSelectionDelay);
}//synchronized//
}//if//
else {
selection.setValue(getRowValue(), calendar.getTime());
}//else//
}//widgetSelected()//
}//DateTimeCellControl//
/**
* CellDateTime constructor.
*/
public CellDateTime() {
}//CellDateTime()//
/**
* CellDateTime constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_DATE
* @see #STYLE_TIME
* @see #STYLE_CALENDAR
* @see #STYLE_SHORT
* @see #STYLE_MEDIUM
* @see #STYLE_LONG
*/
public CellDateTime(ICellContainer parent, String name, int style) {
super(parent, name, style);
this.style = style;
includeYear = (((style & STYLE_DATE) > 0) || ((style & STYLE_CALENDAR) > 0));
includeMonth = (((style & STYLE_DATE) > 0) || ((style & STYLE_CALENDAR) > 0));
includeDay = ((((style & STYLE_DATE) > 0) && ((style & STYLE_SHORT) == 0)) || ((style & STYLE_CALENDAR) > 0));
includeHour = ((style & STYLE_TIME) > 0);
includeMinute = ((style & STYLE_TIME) > 0);
includeSecond = (((style & STYLE_TIME) > 0) && ((style & STYLE_SHORT) == 0));
}//CellDateTime()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#initializeControl(java.lang.Object)
*/
protected CellControl initializeControl(Object rowObject) {
return new DateTimeCellControl(new org.eclipse.swt.widgets.DateTime(getCellContainer().getSwtComposite(rowObject), style), rowObject);
}//initializeControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#paintCell(java.lang.Object, org.eclipse.swt.graphics.GC)
*/
public void paintCell(Object rowObject, GC graphics) {
}//paintCell()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractComponent#getName()
*/
public String getName() {
return "__CellDateTime__";
}//getName()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#supportsControl()
*/
public boolean supportsControl() {
return true;
}//supportsControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#registerRowItem(java.lang.Object, java.lang.Object)
*/
public void registerRowItem(Object rowItem, Object data) {
super.registerRowItem(rowItem, data);
selection.registerItem(rowItem, data);
}//registerRowItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#unregisterRowItem(java.lang.Object)
*/
public void unregisterRowItem(Object rowItem) {
super.unregisterRowItem(rowItem);
selection.unregisterItem(rowItem);
}//unregisterRowItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#unregisterRowItems()
*/
public void unregisterRowItems() {
super.unregisterRowItems();
selection.unregisterAllItems();
}//unregisterRowItems()//
/**
* Sets the association container used to access the selection.
* @param container The selection association metadata.
*/
public void setSelectionAssociation(MultiAssociationContainer container) {
verifyThread();
this.selection.setAssociations(container);
}//setSelectionAssociation()//
/**
* Sets the delay for the auto synchronize selection.
* @param autoSynchronizeSelectionDelay The delay in terms of milliseconds between the value of zero and ten thousand. A zero value has no delay.
*/
public void setAutoSynchronizeSelectionDelay(long autoSynchronizeSelectionDelay) {
verifyThread();
if(autoSynchronizeSelectionDelay < 0) {
autoSynchronizeSelectionDelay = 0;
}//if//
else if(autoSynchronizeSelectionDelay > 10000) {
autoSynchronizeSelectionDelay = 10000;
}//else if//
this.autoSynchronizeSelectionDelay = autoSynchronizeSelectionDelay;
}//setAutoSynchronizeSelectionDelay()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
super.internalViewInitialize();
selection.initialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewRelease()
*/
protected void internalViewRelease() {
super.internalViewRelease();
selection.release();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewRefresh(com.foundation.view.swt.cell.CellComponent.CellControl)
*/
protected void internalViewRefresh(CellControl cellControl) {
super.internalViewRefresh(cellControl);
internalViewRefreshSelection((DateTimeCellControl) cellControl);
}//internalViewRefresh()//
/**
* Refreshes the button selection.
* @param cellControl The control to update with the latest state.
*/
protected void internalViewRefreshSelection(DateTimeCellControl cellControl) {
if(selection.refresh(cellControl.getRowValue())) {
cellControl.refreshSelection();
}//if//
}//internalViewRefreshSelection()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.MultiResourceAssociation, java.lang.Object)
*/
protected void internalOnValueChanged(MultiResourceAssociation resourceAssociation, Object alteredItem, Object data, boolean isUpdate) {
if(resourceAssociation == selection) {
DateTimeCellControl control = (DateTimeCellControl) getCellControl(alteredItem);
if(control != null) {
internalViewRefreshSelection(control);
}//if//
}//if//
else {
super.internalOnValueChanged(resourceAssociation, alteredItem, data, isUpdate);
}//else//
}//internalOnValueChanged()//
}//CellDateTime//

View File

@@ -0,0 +1,105 @@
/*
* Copyright (c) 2007,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.cell;
import org.eclipse.swt.widgets.Composite;
import com.foundation.view.swt.ICellContainer;
public class CellPanel extends CellContainer {
/** The control style. */
private int style = 0;
public class PanelCellControl extends ContainerControl {
/**
* PanelCellControl constructor.
* @param control The control being encapsulated.
* @param rowObject The data model the control interacts with.
*/
public PanelCellControl(Composite control, Object rowObject) {
super(control, rowObject);
}//PanelCellControl()//
/**
* Initializes the control.
*/
public void initialize() {
super.initialize();
}//initialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent.CellControl#refresh()
*/
public void refresh() {
super.refresh();
}//refresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent.CellControl#release()
*/
public void release() {
super.release();
}//release()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellContainer.ContainerControl#synchronize()
*/
public void synchronize() {
super.synchronize();
}//synchronize()//
}//PanelCellControl//
/**
* CellPanel constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #STYLE_NO_BACKGROUND
* @see #STYLE_NO_FOCUS
* @see #STYLE_NO_MERGE_PAINTS
* @see #STYLE_NO_REDRAW_RESIZE
* @see #STYLE_NO_RADIO_GROUP
* @see #STYLE_EMBEDDED
* @see #STYLE_DOUBLE_BUFFERED
* @see #STYLE_H_SCROLL
* @see #STYLE_V_SCROLL
* @see #STYLE_BORDER
* @see #STYLE_LEFT_TO_RIGHT
* @see #STYLE_RIGHT_TO_LEFT
*/
public CellPanel(ICellContainer parent, String name, int style) {
super(parent, name, style);
this.style = style;
}//CellPanel()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#initializeControl(java.lang.Object)
*/
protected CellControl initializeControl(Object rowValue) {
return new PanelCellControl(new Composite(getCellContainer().getSwtComposite(rowValue), style), rowValue);
}//initializeControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalCreateCellControl(java.lang.Object)
*/
protected CellControl internalCreateCellControl(Object rowValue) {
CellControl result = super.internalCreateCellControl(rowValue);
//Initialize the child cell components.//
for(int index = 0; index < getCellComponents().getSize(); index++) {
((CellComponent) getCellComponents().get(index)).internalCreateCellControl(rowValue);
}//for//
return result;
}//internalCreateCellControl()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractComponent#getName()
*/
public String getName() {
return "__CellPanel__";
}//getName()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#supportsControl()
*/
public boolean supportsControl() {
return true;
}//supportsControl()//
}//CellPanel//

View File

@@ -0,0 +1,272 @@
/*
* Copyright (c) 2007,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.cell;
import java.math.BigDecimal;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import com.foundation.view.JefColor;
import com.foundation.view.MultiAssociationContainer;
import com.foundation.view.MultiResourceAssociation;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
import com.foundation.view.swt.ICellContainer;
import com.foundation.view.swt.util.SwtUtilities;
public class CellProgress extends CellComponent {
/** The progress' maximum resource which bounds the progress states. */
private SingleResourceAssociation maximum = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, false, new Integer(0));
/** The progress' minimum resource which bounds the progress states. */
private SingleResourceAssociation minimum = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_INTEGER, false, new Integer(0));
/** The progress' progress resource which defines the current progress state. */
private MultiResourceAssociation progress = new MultiResourceAssociation(this, this, getViewContext(), MultiResourceAssociation.TYPE_BIG_DECIMAL, false, new Integer(0));
/** The multiplier used to generate an integer from the current progress value. */
private BigDecimal multiplier = null;
/** The progress color. */
private JefColor foreground = new JefColor("blue");
/** The control style. */
private int style = 0;
/**
* CellButton constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
*/
public CellProgress(ICellContainer parent, String name, int style) {
super(parent, name, style);
this.style = style;
}//Progress()//
/**
* Gets the multiplier used to construct an integer from the progress value.
* @return The progress multiplier.
*/
public BigDecimal getMultiplier() {
return multiplier;
}//getMultiplier()//
/**
* Sets the multiplier used to construct an integer from the progress value.
* @param multiplier The progress multiplier.
*/
public void setMultiplier(BigDecimal multiplier) {
this.multiplier = multiplier;
}//setMultiplier()//
/**
* Sets the component maximum progress value.
* @param maximum The maximum value in the progress range.
*/
public void setMaximum(Integer maximum) {
verifyThread();
this.maximum.setDefaultValue(maximum);
}//setMaximum()//
/**
* Sets the component minimum progress value.
* @param minimum The minimum value in the progress range. This must be greater than or equal to zero.
*/
public void setMinimum(Integer minimum) {
verifyThread();
this.minimum.setDefaultValue(minimum);
}//setMinimum()//
/**
* Sets the component progress value.
* @param progress The current progress value. This must be greater than or equal to the minimum and less than or equal to the maximum.
*/
public void setProgress(BigDecimal progress) {
verifyThread();
this.progress.setDefaultValue(progress);
}//setProgress()//
/**
* Sets the association container used to access the maximum value.
* @param container The maximum value association metadata.
*/
public void setMaximumAssociation(SingleAssociationContainer container) {
verifyThread();
this.maximum.setAssociations(container);
}//setMaximumAssociation()//
/**
* Sets the association container used to access the minimum value.
* @param container The minimum value association metadata.
*/
public void setMinimumAssociation(SingleAssociationContainer container) {
verifyThread();
this.minimum.setAssociations(container);
}//setMinimumAssociation()//
/**
* Sets the association container used to access the progress value.
* @param container The progress value association metadata.
*/
public void setProgressAssociation(MultiAssociationContainer container) {
verifyThread();
this.progress.setAssociations(container);
}//setProgressAssociation()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#supportsPaint()
*/
public boolean supportsPaint() {
return true;
}//supportsPaint()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
super.internalViewInitialize();
progress.initialize();
minimum.initialize();
maximum.initialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewRelease()
*/
protected void internalViewRelease() {
super.internalViewRelease();
progress.release();
minimum.release();
maximum.release();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
internalViewRefreshMinimum();
internalViewRefreshMaximum();
super.internalViewRefresh();
}//internalViewRefresh()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#internalViewRefresh(com.foundation.view.swt.cell.CellComponent.CellControl)
*/
protected void internalViewRefresh(CellControl cellControl) {
super.internalViewRefresh(cellControl);
// internalViewRefreshProgress((ProgressCellControl) cellControl);
}//internalViewRefresh()//
/**
* Refreshes the minimum progress value.
*/
protected void internalViewRefreshMinimum() {
if(minimum.refresh()) {
//TODO: Force all visible progress bars to repaint.
getSwtContainer().getSwtComposite().redraw();
}//if//
}//internalViewRefreshText()//
/**
* Refreshes the maximum progress value.
*/
protected void internalViewRefreshMaximum() {
if(maximum.refresh()) {
//TODO: Force all visible progress bars to repaint.
getSwtContainer().getSwtComposite().redraw();
}//if//
}//internalViewRefreshText()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.MultiResourceAssociation, java.lang.Object)
*/
protected void internalOnValueChanged(MultiResourceAssociation resourceAssociation, Object alteredItem, Object data, boolean isUpdate) {
if(progress == resourceAssociation) {
//TODO: Force the progress bar to repaint if visible.
//TODO: Instead of getting the control, we need to see if the item is visible and force a refresh of its image if it is, and ignore it if it isn't.
//TODO: Narrow this to the affected cell.
getSwtContainer().getSwtComposite().redraw();
}//if//
else {
super.internalOnValueChanged(resourceAssociation, alteredItem, data, isUpdate);
}//else//
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(minimum == resourceAssociation) {
internalViewRefreshMinimum();
}//if//
else if(maximum == resourceAssociation) {
internalViewRefreshMaximum();
}//else if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else/
}//internalOnValueChanged()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#paintCell(java.lang.Object, org.eclipse.swt.graphics.GC)
*/
public void paintCell(Object rowObject, GC graphics) {
progress.refresh(rowObject); //TODO: Can we move this so we are not refreshing every time? With the new association code this is much less expensive, so may be it is ok to leave.
double minimum = ((Number) this.minimum.getValue()).doubleValue();
double maximum = ((Number) this.maximum.getValue()).doubleValue();
BigDecimal currentProgress = (BigDecimal) this.progress.getValue(rowObject);
double progress;
if(multiplier != null) {
currentProgress = currentProgress.multiply(multiplier);
}//if//
progress = currentProgress.doubleValue();
if(progress != minimum) {
Rectangle rectangle = graphics.getClipping();
double width = rectangle.width;
Color foreground = SwtUtilities.getColor(graphics.getDevice(), this.foreground);
Color oldForeground = graphics.getForeground();
Color oldBackground = graphics.getBackground();
//Set the graphics context's initial settings.//
graphics.setForeground(foreground);
graphics.setBackground(foreground);
//Draw the progress bar.//
rectangle.height -= 2;
rectangle.y--;
rectangle.width = (int) Math.ceil(width / ((maximum - minimum) / progress));
graphics.fillRectangle(rectangle);
//Reset the graphics context settings.//
graphics.setForeground(oldForeground);
graphics.setBackground(oldBackground);
if(!this.foreground.isColorConstant()) {
foreground.dispose();
}//if//
}//if//
}//paintCell()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#initializeControl(java.lang.Object)
*/
protected CellControl initializeControl(Object rowObject) {
return null;
}//initializeControl()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#registerRowItem(java.lang.Object, java.lang.Object)
*/
public void registerRowItem(Object rowItem, Object data) {
super.registerRowItem(rowItem, data);
progress.registerItem(rowItem, data);
}//registerRowItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#unregisterRowItem(java.lang.Object)
*/
public void unregisterRowItem(Object rowItem) {
super.unregisterRowItem(rowItem);
progress.unregisterItem(rowItem);
}//unregisterRowItem()//
/* (non-Javadoc)
* @see com.foundation.view.swt.cell.CellComponent#unregisterRowItems()
*/
public void unregisterRowItems() {
super.unregisterRowItems();
progress.unregisterAllItems();
}//unregisterRowItems()//
/* (non-Javadoc)
* @see com.foundation.view.IAbstractComponent#getName()
*/
public String getName() {
return "__CellProgress__";
}//getName()//
}//Progress//

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,575 @@
/*
* Copyright (c) 2005,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt.custom;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import com.foundation.view.swt.layout.FillLayout;
import org.eclipse.swt.widgets.*;
/*
* A custom combo box which allows the user to setup any primary display component, and any drop display component.
*/
public abstract class CustomCombo extends Composite {
protected static final int BUTTON_PADDING = 0;
protected Control selectionControl = null;
protected Control dropControl = null;
protected Control dropButton = null;
protected Shell dropShell = null;
/** Whether the user has manually resized the drop shell and the shell should not be automatically resized when next opened. */
private boolean sizeDropShell = true;
/** Temporarily tells the listeners to ignore resize events occuring on the drop shell. */
private boolean ignoreDropShellResize = false;
/**
* CustomCombo constructor.
* @param parent A non-null widget which will be the parent of the new instance.
* @param style The style of widget to construct.
* @see SWT#RESIZE
* @see SWT#BORDER
* @see Widget#getStyle
*/
public CustomCombo(Composite parent, int style) {
super(parent, (style | SWT.NO_BACKGROUND | SWT.INHERIT_DEFAULT) & (~SWT.RESIZE));
int buttonStyle = SWT.ARROW | SWT.DROP_DOWN | SWT.MAX;
int dropShellStyle = SWT.NO_BACKGROUND | SWT.TOOL | SWT.ON_TOP | SWT.NO_FOCUS;
TraverseListener traverseListener = new TraverseListener() {
public void keyTraversed(TraverseEvent event) {
switch(event.detail) {
case SWT.TRAVERSE_RETURN:
case SWT.TRAVERSE_TAB_PREVIOUS:
case SWT.TRAVERSE_TAB_NEXT:
case SWT.TRAVERSE_ARROW_PREVIOUS:
case SWT.TRAVERSE_PAGE_PREVIOUS:
case SWT.TRAVERSE_PAGE_NEXT:
if(isShowingDrop()) {
hideDrop(true);
event.doit = true;
}//if//
break;
case SWT.TRAVERSE_ESCAPE:
if(isShowingDrop()) {
hideDrop(false);
event.doit = false;
}//if//
break;
default:
break;
}//switch//
}//keyTraversed()//
};
//TODO: Do any native systems put the drop button on the left?
super.setLayout(new Layout() {
protected void layout(Composite composite, boolean flushCache) {
internalLayout(composite, flushCache);
}//layout()//
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
return internalComputeSize(composite, wHint, hHint, flushCache);
}//computeSize()//
});
if((style & SWT.RESIZE) > 0) {
dropShellStyle |= SWT.RESIZE | SWT.BORDER;
}//if//
dropButton = createDropButton();
//Add a listener to this composite to allow resizing of the children.//
addControlListener(new ControlListener() {
public void controlMoved(ControlEvent event) {
}//controlMoved()//
public void controlResized(ControlEvent event) {
/* TODO Remove
Rectangle area = getClientArea();
arrow.setBounds(area.width - arrowSize.x, 0, arrowSize.x, area.height);
valueAreaBounds = new Rectangle(0, 0, area.width - arrowSize.x, area.height);
*/
}//controlResized()//
});
//Add a listener to this composite to hide the drop down shell if a traveral event occurs.//
addTraverseListener(traverseListener);
//Add a listener to this composite to redraw after a focus change.//
addFocusListener(new FocusListener() {
public void focusLost(FocusEvent event) {
redraw();
}//focusLost()//
public void focusGained(FocusEvent event) {
redraw();
}//focusGained()//
});
//Add a listener to this composite to show the drop down if a mouse click occurs outside the children but inside the composite.//
addMouseListener(new MouseListener() {
public void mouseDoubleClick(MouseEvent event) {
}//mouseDoubleClick()//
public void mouseDown(MouseEvent event) {
if(!isShowingDrop()) {
showDrop();
forceFocus();
}//if//
}//mouseDown()//
public void mouseUp(MouseEvent event) {
}//mouseUp()//
});
dropShell = new Shell(getShell(), dropShellStyle);
dropShell.setLayout(new FillLayout());
dropShell.setBackgroundMode(SWT.INHERIT_FORCE);
dropShell.addControlListener(new ControlListener() {
public void controlResized(ControlEvent event) {
if(!ignoreDropShellResize) {
//Keep the combo from resizing the drop down shell when it next opens.//
sizeDropShell = false;
}//if//
}//controlResized()//
public void controlMoved(ControlEvent event) {
}//controlMoved()//
});
dropShell.addShellListener(new ShellListener() {
public void shellActivated(ShellEvent event) {
}//shellActivated()//
public void shellClosed(ShellEvent event) {
}//shellClosed()//
public void shellDeactivated(ShellEvent event) {
hideDrop(true);
}//shellDeactivated()//
public void shellDeiconified(ShellEvent event) {
}//shellDeiconified()//
public void shellIconified(ShellEvent event) {
}//shellIconified()//
});
dropShell.addTraverseListener(traverseListener);
getDisplay().addFilter(SWT.MouseDown, new Listener() {
public void handleEvent(Event event) {
if((isShowingDrop()) && (event.widget instanceof Control)) {
Control c = (Control) event.widget;
//If the mouse event occured outside the drop shell then close the drop shell.//
if(!dropShell.getBounds().contains(getDisplay().map(c, null, event.x, event.y))) {
hideDrop(true);
event.type = 0;
}//if//
}//if//
}//handleEvent//
});
//if the outer most shell is deactivated or iconified, then stop showing the drop down shell.//
getShell().addShellListener(new ShellListener() {
public void shellActivated(ShellEvent event) {
}//shellActivated()//
public void shellClosed(ShellEvent event) {
}//shellClosed()//
public void shellDeactivated(ShellEvent event) {
if(!isDisposed()) {
getShell().getDisplay().asyncExec(new Runnable() {
public void run() {
//TODO: Clean this up so it works properly.
if((isShowingDrop()) && (dropShell != getDisplay().getActiveShell())) {
getShell().setActive();
hideDrop(true);
}//if//
}//run()//
});
}//if//
}//shellDeactivated()//
public void shellDeiconified(ShellEvent event) {
}//shellDeiconified()//
public void shellIconified(ShellEvent event) {
if(isShowingDrop()) {
hideDrop(false);
}//if//
}//shellIconified()//
});
getShell().addControlListener(new ControlListener() {
public void controlMoved(ControlEvent event) {
if(isShowingDrop()) {
hideDrop(false);
}//if//
}//controlMoved()//
public void controlResized(ControlEvent event) {
if(isShowingDrop()) {
hideDrop(false);
}//if//
}//controlResized()//
});
initialize();
dropControl = createDropControl(dropShell);
selectionControl = createSelectionControl();
postInitialize();
}//CustomCombo()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Control#getBackground()
*/
public Color getBackground() {
return selectionControl.getBackground();
}//getBackground()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Control#setBackground(org.eclipse.swt.graphics.Color)
*/
public void setBackground(Color color) {
super.setBackground(color);
//selectionControl.setBackground(color);
//dropButton.setBackground(color);
dropControl.setBackground(color);
}//setBackground()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Control#getBackgroundImage()
*/
public Image getBackgroundImage() {
return selectionControl.getBackgroundImage();
}//getBackgroundImage()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Control#setBackgroundImage(org.eclipse.swt.graphics.Image)
*/
public void setBackgroundImage(Image image) {
super.setBackgroundImage(image);
//selectionControl.setBackgroundImage(image);
//dropButton.setBackgroundImage(image);
dropControl.setBackgroundImage(image);
}//setBackgroundImage()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Control#getFont()
*/
public Font getFont() {
return selectionControl.getFont();
}//getFont()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Control#setFont(org.eclipse.swt.graphics.Font)
*/
public void setFont(Font font) {
super.setFont(font);
selectionControl.setFont(font);
dropButton.setFont(font);
dropControl.setFont(font);
}//setFont()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Control#getForeground()
*/
public Color getForeground() {
return selectionControl.getForeground();
}//getForeground()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Control#setForeground(org.eclipse.swt.graphics.Color)
*/
public void setForeground(Color color) {
super.setForeground(color);
selectionControl.setForeground(color);
dropButton.setForeground(color);
dropControl.setForeground(color);
}//setForeground()//
/**
* Initializes the combo's state prior to any of the controls being setup.
*/
protected abstract void initialize();
/**
* Initializes the combo's state after all the controls have been setup.
*/
protected abstract void postInitialize();
/**
* Creates the control for displaying the selection.
* @return The control that displays the current drop down selection or contents.
*/
protected abstract Control createSelectionControl();
/**
* Creates the control displayed in the drop down.
* @return The drop down contents.
*/
protected abstract Control createDropControl(Shell parent);
/**
* Creates a new drop button control.
* @return The button used to open the drop shell.
*/
protected Control createDropButton() {
Button dropButton = new Button(this, SWT.ARROW | SWT.DOWN | SWT.FLAT | SWT.INHERIT_DEFAULT);
dropButton.addMouseListener(new MouseListener() {
public void mouseDoubleClick(MouseEvent event) {
}//mouseDoubleClick()//
public void mouseDown(MouseEvent event) {
if(!isShowingDrop()) {
showDrop();
}//if//
}//mouseDown()//
public void mouseUp(MouseEvent event) {
}//mouseUp()//
});
dropButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent event) {
forceFocus();
}//widgetSelected()//
public void widgetDefaultSelected(SelectionEvent event) {
}//widgetDefaultSelected()//
});
return dropButton;
}//createDropButton()//
/**
* Gets the control that displays the combo selection.
* @return The control to be used to display the selection.
*/
protected Control getSelectionControl() {
return selectionControl;
}//getSelectionControl()//
/**
* Gets the control that displays the drop down.
* @return The control to be used to display the drop down.
*/
protected Control getDropControl() {
return dropControl;
}//getDropControl()//
/**
* Gets the control used to open the drop panel.
* @return The button control whose action opens the drop panel.
*/
protected Control getDropButton() {
return dropButton;
}//getDropButton()//
/**
* Gets the shell that contains the drop panel.
* @return The shell that is used to display the drop panel.
*/
protected Shell getDropShell() {
return dropShell;
}//getDropShell()//
/**
* Determines whether the drop down shell is currently being shown.
* @return Whether we are currently showing the drop control.
*/
public boolean isShowingDrop() {
return dropShell != null && !dropShell.isDisposed() && dropShell.isVisible();
}//isShowingDrop()//
/**
* Shows the drop down shell.
*/
public final void showDrop() {
checkWidget();
if(!isShowingDrop()) {
if(!dropShell.isDisposed()) {
Point comboSize = getSize();
Point size;
Point location;
refreshDrop();
//Get the combo location within the screen.//
location = getDisplay().map(getParent(), null, getLocation());
if(sizeDropShell) {
int trimWidth = dropShell.computeTrim(0, 0, 1, 1).width - 1;
Rectangle bounds;
int quarterScreenHeight = getDisplay().getClientArea().height / 4;
size = dropShell.computeSize(comboSize.x - trimWidth, -1);
if(size.y > quarterScreenHeight) {
size.y = quarterScreenHeight;
}//if//
bounds = dropShell.computeTrim(0, 0, size.x, size.y);
dropShell.setSize(bounds.width, bounds.height);
}//if//
else {
size = dropShell.getSize();
}//else//
//Horizontal positioning.//
if(size.x < comboSize.x) {
location.x += comboSize.x - size.x;
}//if//
else {
location.x -= (size.x - comboSize.x) >> 1;
}//else//
//Horizontal bounds checking.//
if(location.x + size.x > getDisplay().getClientArea().width) {
location.x = getDisplay().getClientArea().width - size.x;
}//if//
if(location.x < getDisplay().getClientArea().x) {
location.x = getDisplay().getClientArea().x;
}//if//
//Vertical positioning.//
location.y += comboSize.y;
//Make the pull down go up instead of down.//
if(location.y + size.y > getDisplay().getClientArea().height) {
location.y -= comboSize.y + size.y;
}//if//
if(location.y < getDisplay().getClientArea().y) {
//Use the larger of the two positionings and then resize the pulldown.//
if(location.y < (location.y + comboSize.y + size.y + size.y) - getDisplay().getClientArea().height) {
//Make the combo drop down again since it will have the most space this way.//
location.y += comboSize.y + size.y;
size.y -= getDisplay().getClientArea().height - (location.y + size.y);
}//if//
else {
size.y += location.y;
location.y = getDisplay().getClientArea().y;
}//else//
//Adjust the shell size.//
dropShell.setSize(size);
}//if//
ignoreDropShellResize = true;
dropShell.setLocation(location);
dropShell.setVisible(true);
ignoreDropShellResize = false;
redraw();
}//if//
}//if//
}//showDrop()//
/**
* Hides the drop down shell.
* @param synchronize Whether the drop control should synchronize its data with the combo.
*/
public final void hideDrop(boolean synchronize) {
checkWidget();
if(isShowingDrop()) {
dropShell.setVisible(false);
getShell().setActive();
forceFocus();
forceFocus();
redraw();
if(synchronize) {
synchronizeDrop();
}//if//
}//if//
}//hideDrop()//
/**
* Rebuilds the drop control.
*/
protected void rebuildDropControl() {
dropControl.dispose();
dropControl = createDropControl(dropShell);
if(isShowingDrop()) {
dropShell.layout(true, true);
dropShell.redraw();
}//if//
}//rebuildDropControl()//
/**
* Rebuilds the selection control.
*/
protected void rebuildSelectionControl() {
selectionControl.dispose();
selectionControl = createSelectionControl();
layout(true, true);
redraw();
}//rebuildSelectionControl()//
/**
* Called to refresh the drop control's data.
*/
protected abstract void refreshDrop();
/**
* Called to synchronize the drop control's data.
*/
protected abstract void synchronizeDrop();
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Composite#setLayout(org.eclipse.swt.widgets.Layout)
*/
public void setLayout(Layout layout) {
}//setLayout()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Control#computeSize(int, int, boolean)
*/
public Point computeSize(int wHint, int hHint, boolean changed) {
Point buttonSize = getDropButton().computeSize(-1, hHint, changed);
Point size = getSelectionControl().computeSize(-1, hHint, changed);
Point dropSize = getDropShell().computeSize(-1, -1, changed);
size.y = Math.max(buttonSize.y, size.y);
size.x += buttonSize.x;
size.x = Math.max(size.x, dropSize.x);
return size;
}//computeSize()//
/**
* Called by the container's layout code.
* @param composite The composite to be layed out.
* @param flushCache Whether the cache of layout data must be flushed.
*/
protected void internalLayout(Composite composite, boolean flushCache) {
Point size = composite.getSize();
Point buttonSize = getDropButton().computeSize(-1, size.y, flushCache);
Point selectionSize = new Point(0, size.y);
buttonSize.y = size.y;
getDropButton().setLocation(size.x - buttonSize.x + getButtonOffset(), getButtonOffset());
buttonSize.y += getButtonOffset();
buttonSize.x += getButtonOffset();
getDropButton().setSize(buttonSize);
selectionSize.x = size.x - buttonSize.x;
getSelectionControl().setSize(selectionSize);
getSelectionControl().setLocation(0, 0);
}//internalLayout()//
/**
* Gets the offset to use when laying out the drop button.
* <p>This is required by windows which will not display the button correctly without the offset. This may need to be platform specific.</p>
* @return The offset to shift the button down and right (or if negative up and left).
*/
protected int getButtonOffset() {
return SWT.getPlatform().equals("win32") ? -1 : 0;
}//getButtonOffset()//
/**
* Called by the container's layout code.
* @param composite The composite whose size is being computed.
* @param wHint The width hint.
* @param hHint The height hint.
* @param flushCache Whether the cache of layout data must be flushed.
* @return The component's size.
*/
protected Point internalComputeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
Point selectionSize = getSelectionControl().computeSize(wHint, hHint, flushCache);
Point dropButtonSize = getDropButton().computeSize(-1, hHint, flushCache);
selectionSize.x += dropButtonSize.x;
selectionSize.y = Math.max(selectionSize.y, dropButtonSize.y);
return selectionSize;
}//internalComputeSize()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Widget#dispose()
*/
public void dispose() {
if(dropControl != null && !dropControl.isDisposed()) {
dropControl.dispose();
dropControl = null;
}//if//
if(dropShell != null && !dropShell.isDisposed()) {
dropShell.dispose();
dropShell = null;
}//if//
if(dropButton != null && !dropButton.isDisposed()) {
dropButton.dispose();
dropButton = null;
}//if//
if(selectionControl != null && !selectionControl.isDisposed()) {
selectionControl.dispose();
selectionControl = null;
}//if//
super.dispose();
}//dispose()//
}//CustomCombo//

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 2007 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.layout;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
public class CardLayout extends Layout {
/** The cached width. */
private int x = 0;
/** The cached height. */
private int y = 0;
/** The index of the control that will be displayed on top. */
public int topIndex = 0;
/** The top and bottom margins. */
public int marginHeight = 0;
/** The left and right margins. */
public int marginWidth = 0;
/**
* CardLayout constructor.
*/
public CardLayout() {
}//CardLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#computeCurrentSize(org.eclipse.swt.widgets.Composite)
*/
public Point computeCurrentSize(Composite composite) {
Point result = super.computeCurrentSize(composite);
result.x += marginWidth;
result.y += marginHeight;
return result;
}//computeCurrentSize()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int, boolean)
*/
protected Point computeSize(Composite composite, int hintX, int hintY, boolean flushCache) {
Control[] children = composite.getChildren();
if(flushCache || x == 0 || y == 0) {
x = 0;
y = 0;
for(int index = 0; index < children.length; index++) {
Point childSize = children[index].computeSize(hintX, hintY);
x = Math.max(x, childSize.x);
y = Math.max(y, childSize.y);
}//for//
}//if//
return new Point(Math.max(x + (marginWidth << 1), hintX), Math.max(y + (marginHeight << 1), hintY));
}//computeSize()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#flushCache(org.eclipse.swt.widgets.Control)
*/
protected boolean flushCache(Control control) {
x = 0;
y = 0;
return true;
}//flushCache()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
*/
protected void layout(Composite composite, boolean flushCache) {
Control[] children = composite.getChildren();
if(children != null && children.length > 0) {
Rectangle bounds = composite.getClientArea();
int top = topIndex < 0 ? 0 : topIndex >= children.length ? children.length - 1 : topIndex;
bounds.x += marginWidth;
bounds.width -= marginWidth << 1;
bounds.y += marginHeight;
bounds.height -= marginHeight << 1;
for(int index = 0; index < children.length; index++) {
children[index].setBounds(bounds);
children[index].setVisible(index == top);
}//for//
}//if//
}//layout()//
}//CardLayout//

View File

@@ -0,0 +1,83 @@
package com.foundation.view.swt.layout;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
/**
* A very simple layout that centers the first child within the parent.
* All other children are not visible.
* There is no data attached to the children that is used by this layout.
*/
public class CenterLayout extends Layout {
private Point size = new Point(0, 0);
private Point firstChildSize = new Point(0, 0);
/**
* CenterLayout constructor.
*/
public CenterLayout() {
}//CenterLayout()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int, boolean)
*/
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
if(flushCache) {
Control[] children = composite.getChildren();
size.x = 0;
size.y = 0;
firstChildSize.x = 0;
firstChildSize.y = 0;
if(children != null) {
for(int index = 0; index < children.length; index++) {
Point childSize = children[index].computeSize(wHint, hHint, flushCache);
size.x = Math.max(childSize.x, size.x);
size.y = Math.max(childSize.y, size.y);
if(index == 0) {
firstChildSize.x = childSize.x;
firstChildSize.y = childSize.y;
}//if//
}//for//
}//if//
}//if//
return new Point(size.x, size.y);
}//computeSize()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
*/
protected void layout(Composite composite, boolean flushCache) {
Rectangle space = composite.getClientArea();
Control[] children = composite.getChildren();
if(flushCache || firstChildSize.x == 0 || firstChildSize.y == 0) {
if(children != null && children.length > 0) {
Point childSize = children[0].computeSize(-1, -1, true);
firstChildSize.x = childSize.x;
firstChildSize.y = childSize.y;
}//if//
else {
firstChildSize.x = 0;
firstChildSize.y = 0;
}//else//
}//if//
if(children != null) {
for(int index = 0; index < children.length; index++) {
if(index == 0) {
children[index].setSize(firstChildSize);
children[index].setLocation(space.x + ((space.width - firstChildSize.x) >> 1), space.y + ((space.height - firstChildSize.y) >> 1));
}//if//
else {
children[index].setSize(0, 0);
children[index].setLocation(0, 0);
}//else//
}//for//
}//if//
}//layout()//
}//CenterLayout//

View File

@@ -0,0 +1,86 @@
/*
* Copyright (c) 2007,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.layout;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
/**
* The data assigned to a component whose parent uses a FillLayout.
*/
public class FillData extends LayoutData {
/** The last generated default result (where the hints are the default: SWT.DEFAULT). */
private Point defaultResult = null;
/** The hints last used to create the lastHintResult. */
private int lastWidthHint = -1;
/** The hints last used to create the lastHintResult. */
private int lastHeightHint = -1;
/** The last generated result (where non-default hints are given). */
private Point lastHintResult = null;
/** The default width supplied by the view for the control this data describes. This overrides the control's desired width if it is not assigned SWT.DEFAULT. */
public int defaultWidth = SWT.DEFAULT;
/** The default height supplied by the view for the control this data describes. This overrides the control's desired height if it is not assigned SWT.DEFAULT. */
public int defaultHeight = SWT.DEFAULT;
/** The minimum width for the control. */
public int minWidth = -1;
/** The minimum height for the control. */
public int minHeight = -1;
/** The minimum width for the control. */
public int cachedMinWidth = -1;
/** The minimum height for the control. */
public int cachedMinHeight = -1;
/**
* FillData constructor.
*/
public FillData() {
super();
}//FillData()//
/**
* Computes the size of the control that this data describes.
* @param result The point that will contain the resulting size.
* @param control The control the data is describing.
* @param wHint The hint for the width, or SWT.DEFAULT if no hint is given.
* @param hHint The hint for the height, or SWT.DEFAULT if no hint is given.
* @param flushCache Whether to first flush the cache, forcing the control's size preferences to be re-assertained.
* @return The point describing the control's desired size.
*/
void computeSize(Point result, Control control, int wHint, int hHint, boolean flushCache) {
if(flushCache) {
flushCache();
}//if//
if(wHint == SWT.DEFAULT && hHint == SWT.DEFAULT) {
if(defaultResult == null) {
defaultResult = control.computeSize(defaultWidth, defaultHeight, flushCache);
}//if//
result.x = defaultResult.x;
result.y = defaultResult.y;
}//if//
else {
if(lastHintResult == null || wHint != lastWidthHint || hHint != lastHeightHint) {
lastHintResult = control.computeSize(wHint, hHint, flushCache);
lastWidthHint = wHint;
lastHeightHint = hHint;
}//if//
result.x = lastHintResult.x;
result.y = lastHintResult.y;
}//else//
}//computeSize()//
/**
* Releases all cached data.
*/
public void flushCache() {
defaultResult = null;
lastHintResult = null;
cachedMinWidth = -1;
cachedMinHeight = -1;
}//flushCache()//
}//FillData//

View File

@@ -0,0 +1,359 @@
/*
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Declarative Engineering - Major additions (overlays & minimum sizing) + maintenance, formatting, & commenting.
*/
package com.foundation.view.swt.layout;
import java.util.Arrays;
import java.util.Comparator;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Scrollable;
import com.foundation.view.swt.IOverlay;
/**
* <code>FillLayout</code> is the simplest layout class. It lays out
* controls in a single row or column, forcing them to be the same size.
* <p>
* Initially, the controls will all be as tall as the tallest control,
* and as wide as the widest. <code>FillLayout</code> does not wrap,
* but you can specify margins and spacing. You might use it to
* lay out buttons in a task bar or tool bar, or to stack checkboxes
* in a <code>Group</code>. <code>FillLayout</code> can also be used
* when a <code>Composite</code> only has one child. For example,
* if a <code>Shell</code> has a single <code>Group</code> child,
* <code>FillLayout</code> will cause the <code>Group</code> to
* completely fill the <code>Shell</code> (if margins are 0).
* </p>
* <p>
* Example code: first a <code>FillLayout</code> is created and
* its type field is set, and then the layout is set into the
* <code>Composite</code>. Note that in a <code>FillLayout</code>,
* children are always the same size, and they fill all available space.
* <pre>
* FillLayout fillLayout = new FillLayout();
* fillLayout.type = SWT.VERTICAL;
* shell.setLayout(fillLayout);
* </pre>
* </p>
*/
public final class FillLayout extends Layout {
/** Specifies how controls will be positioned within the layout. */
public int type = SWT.HORIZONTAL;
/** Specifies the number of pixels of horizontal margin that will be placed along the left and right edges of the layout. */
public int marginWidth = 0;
/** Specifies the number of pixels of vertical margin that will be placed along the top and bottom edges of the layout. */
public int marginHeight = 0;
/** Specifies the number of pixels between the edge of one cell and the edge of its neighbouring cell. */
public int spacing = 0;
/**
* FillLayout constructor.
*/
public FillLayout() {
}//FillLayout()//
/**
* FillLayout constructor.
* @param type The fill direction (HORIZONTAL | VERTICAL).
*/
public FillLayout(int type) {
this.type = type;
}//FillLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#computeCurrentSize(org.eclipse.swt.widgets.Composite)
*/
public Point computeCurrentSize(Composite composite) {
Point result = super.computeCurrentSize(composite);
result.x += marginWidth;
result.y += marginHeight;
return result;
}//computeCurrentSize()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int, boolean)
*/
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
Control[] children = composite.getChildren();
int count = children.length;
int maxWidth = 0;
int maxHeight = 0;
int width = 0;
int height = 0;
Point size = new Point(0, 0);
for(int i = 0; i < children.length; i++) {
Control child = children[i];
int w = wHint;
int h = hHint;
if((child instanceof IOverlay) || (!child.getVisible())) {
count--;
}//if//
else {
if(count > 0) {
if(type == SWT.HORIZONTAL && wHint != SWT.DEFAULT) {
w = Math.max(0, (wHint - (count - 1) * spacing) / count);
}//if//
if(type == SWT.VERTICAL && hHint != SWT.DEFAULT) {
h = Math.max(0, (hHint - (count - 1) * spacing) / count);
}//if//
}//if//
computeChildSize(size, child, w, h, flushCache);
maxWidth = Math.max(maxWidth, size.x);
maxHeight = Math.max(maxHeight, size.y);
}//else//
}//for//
if(type == SWT.HORIZONTAL) {
width = count * maxWidth;
if(count != 0) {
width += (count - 1) * spacing;
}//if//
height = maxHeight;
}//if//
else {
width = maxWidth;
height = count * maxHeight;
if(count != 0) {
height += (count - 1) * spacing;
}//if//
}//else//
width += marginWidth * 2;
height += marginHeight * 2;
if(wHint != SWT.DEFAULT) {
width = wHint;
}//if//
if(hHint != SWT.DEFAULT) {
height = hHint;
}//if//
size.x = width;
size.y = height;
return size;
}//computeSize()//
/**
* Computes the size of the child control.
* @param control The child control.
* @param wHint The width hint, or -1.
* @param hHint The height hint, or -1.
* @param flushCache Whether to flush the child's cache.
* @return The child's size.
*/
private void computeChildSize(Point result, Control control, int wHint, int hHint, boolean flushCache) {
FillData data = (FillData) control.getLayoutData();
if(data == null) {
data = new FillData();
control.setLayoutData(data);
}//if//
if(wHint == SWT.DEFAULT && hHint == SWT.DEFAULT) {
data.computeSize(result, control, wHint, hHint, flushCache);
}//if//
else {
int trimX, trimY;
int w;
int h;
if(control instanceof Scrollable) {
Rectangle rect = ((Scrollable) control).computeTrim(0, 0, 0, 0);
trimX = rect.width;
trimY = rect.height;
}//if//
else {
trimX = trimY = control.getBorderWidth() * 2;
}//else//
w = wHint == SWT.DEFAULT ? wHint : Math.max(0, wHint - trimX);
h = hHint == SWT.DEFAULT ? hHint : Math.max(0, hHint - trimY);
data.computeSize(result, control, w, h, flushCache);
}//else//
}//computeChildSize()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#flushCache(org.eclipse.swt.widgets.Control)
*/
public boolean flushCache(Control control) {
Object data = control.getLayoutData();
if(data != null) {
((FillData) data).flushCache();
}//if//
return true;
}//flushCache()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
*/
protected void layout(Composite composite, boolean flushCache) {
Rectangle rect = composite.getClientArea();
Control[] children = composite.getChildren();
int count = children.length;
IOverlay[] overlayChildren = new IOverlay[children.length];
int overlayCount = 0;
//Declarative Engineering//
//Ignore invisible and overlay children.//
for(int index = children.length - 1; index >= 0; index--) {
if((children[index] instanceof IOverlay) || (!children[index].getVisible())) {
if(children[index] instanceof IOverlay) {
overlayChildren[overlayCount++] = (IOverlay) children[index];
}//if//
if(index + 1 != count) {
System.arraycopy(children, index + 1, children, index, children.length - index - 1);
}//if//
count--;
}//if//
}//for//
if(count != 0) {
int width = rect.width - marginWidth * 2;
int height = rect.height - marginHeight * 2;
int x;
int y;
int extra;
if(type == SWT.HORIZONTAL) {
int cellWidth;
width -= (count - 1) * spacing;
x = rect.x + marginWidth;
y = rect.y + marginHeight;
extra = width % count;
cellWidth = width / count;
for(int i = 0; i < count; i++) {
Control child = children[i];
int childWidth = cellWidth;
if(i == 0) {
childWidth += extra / 2;
}//if//
else if(i == count - 1) {
childWidth += (extra + 1) / 2;
}//else if//
child.setBounds(x, y, childWidth, height);
x += childWidth + spacing;
}//for//
}//if//
else {
int cellHeight;
height -= (count - 1) * spacing;
x = rect.x + marginWidth;
y = rect.y + marginHeight;
cellHeight = height / count;
extra = height % count;
for(int i = 0; i < count; i++) {
Control child = children[i];
int childHeight = cellHeight;
if(i == 0) {
childHeight += extra / 2;
}//if//
else if(i == count - 1) {
childHeight += (extra + 1) / 2;
}//else if//
child.setBounds(x, y, width, childHeight);
y += childHeight + spacing;
}//for//
}//else//
if(overlayCount > 0) { //Layout the overlays.//
int upperLeftOffset = 0;
int upperRightOffset = 0;
int lowerLeftOffset = 0;
int lowerRightOffset = 0;
Control lastPeer = null;
Arrays.sort(overlayChildren, 0, overlayCount, new Comparator() {
public int compare(Object arg0, Object arg1) {
return ((IOverlay) arg0).getPeerControl().hashCode() - ((IOverlay) arg1).getPeerControl().hashCode();
}//compare()//
});
for(int index = 0; index < overlayCount; index++) {
IOverlay overlay = overlayChildren[index];
Control peer = overlay.getPeerControl();
Rectangle bounds = peer.getBounds();
Point size = overlay.getSize();
if(peer != lastPeer) {
upperLeftOffset = 0;
upperRightOffset = 0;
lowerLeftOffset = 0;
lowerRightOffset = 0;
lastPeer = peer;
}//if//
switch(overlay.getPosition()) {
case IOverlay.POSITION_UPPER_LEFT: {
bounds.x += overlay.getHorizontalOffset() + upperLeftOffset;
bounds.y += overlay.getVerticalOffset();
bounds.width = size.x;
bounds.height = size.y;
upperLeftOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_UPPER_RIGHT: {
bounds.x += bounds.width + (overlay.getHorizontalOffset() * -1) - size.x - upperRightOffset;
bounds.y += overlay.getVerticalOffset();
bounds.width = size.x;
bounds.height = size.y;
upperRightOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_LOWER_RIGHT: {
bounds.x += bounds.width + (overlay.getHorizontalOffset() * -1) - size.x - lowerRightOffset;
bounds.y += bounds.height + (overlay.getVerticalOffset() * -1) - size.y;
bounds.width = size.x;
bounds.height = size.y;
lowerRightOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_LOWER_LEFT: {
bounds.x += overlay.getHorizontalOffset() + lowerLeftOffset;
bounds.y += bounds.height + (overlay.getVerticalOffset() * -1) - size.y;
bounds.width = size.x;
bounds.height = size.y;
lowerLeftOffset += bounds.width + 1;
break;
}//case//
}//switch//
((Control) overlay).setBounds(bounds);
}//for//
}//if//
}//if//
}//layout()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
return "FillLayout {type: " + (type == SWT.VERTICAL ? "VERTICAL; " : "HORIZONTAL; ") + "marginWidth: " + marginWidth + "; marginHeight: " + marginHeight + "; spacing: " + spacing + "}";
}//toString()//
}//FillLayout//

View File

@@ -0,0 +1,300 @@
/*
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*/
package com.foundation.view.swt.layout;
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
/**
* Instances of this class are used to define the edges of a control
* within a <code>FormLayout</code>.
* <p>
* <code>FormAttachments</code> are set into the top, bottom, left,
* and right fields of the <code>FormData</code> for a control.
* For example:
* <pre>
* FormData data = new FormData();
* data.top = new FormAttachment(0,5);
* data.bottom = new FormAttachment(100,-5);
* data.left = new FormAttachment(0,5);
* data.right = new FormAttachment(100,-5);
* button.setLayoutData(data);
* </pre>
* </p>
* <p>
* A <code>FormAttachment</code> defines where to attach the side of
* a control by using the equation, y = ax + b. The "a" term represents
* a fraction of the parent composite's width (from the left) or height
* (from the top). It can be defined using a numerator and denominator,
* or just a percentage value. If a percentage is used, the denominator
* is set to 100. The "b" term in the equation represents an offset, in
* pixels, from the attachment position. For example:
* <pre>
* FormAttachment attach = new FormAttachment (20, -5);
* </pre>
* specifies that the side to which the <code>FormAttachment</code>
* object belongs will lie at 20% of the parent composite, minus 5 pixels.
* </p>
* <p>
* Control sides can also be attached to another control.
* For example:
* <pre>
* FormAttachment attach = new FormAttachment (button, 10);
* </pre>
* specifies that the side to which the <code>FormAttachment</code>
* object belongs will lie in the same position as the adjacent side of
* the <code>button</code> control, plus 10 pixels. The control side can
* also be attached to the opposite side of the specified control.
* For example:
* <pre>
* FormData data = new FormData ();
* data.left = new FormAttachment (button, 0, SWT.LEFT);
* </pre>
* specifies that the left side of the control will lie in the same position
* as the left side of the <code>button</code> control. The control can also
* be attached in a position that will center the control on the specified
* control. For example:
* <pre>
* data.left = new FormAttachment (button, 0, SWT.CENTER);
* </pre>
* specifies that the left side of the control will be positioned so that it is
* centered between the left and right sides of the <code>button</code> control.
* If the alignment is not specified, the default is to attach to the adjacent side.
* </p>
*
* @see FormLayout
* @see FormData
*
* @since 2.0
*/
public final class FormAttachment {
/**
* numerator specifies the numerator of the "a" term in the
* equation, y = ax + b, which defines the attachment.
*/
public int numerator;
/**
* denominator specifies the denominator of the "a" term in the
* equation, y = ax + b, which defines the attachment.
*
* The default value is 100.
*/
public int denominator = 100;
/**
* offset specifies the offset, in pixels, of the control side
* from the attachment position.
* If the offset is positive, then the control side is offset
* to the right of or below the attachment position. If it is
* negative, then the control side is offset to the left of or
* above the attachment position.
*
* This is equivalent to the "b" term in the equation y = ax + b.
* The default value is 0.
*/
public int offset;
/**
* control specifies the control to which the control side is
* attached.
*/
public Control control;
/**
* alignment specifies the alignment of the control side that is
* attached to a control.
* <p>
* For top and bottom attachments, TOP, BOTTOM and CENTER are used. For left
* and right attachments, LEFT, RIGHT and CENTER are used. If any other case
* occurs, the default will be used instead.
* </p>
*
* <br>Possible values are: <ul>
* <li>TOP: Attach the side to the top side of the specified control.</li>
* <li>BOTTOM : Attach the side to the bottom side of the specified control.</li>
* <li>LEFT: Attach the side to the left side of the specified control.</li>
* <li>RIGHT: Attach the side to the right side of the specified control.</li>
* <li>CENTER: Attach the side at a position which will center the control on the specified control.</li>
* <li>DEFAULT: Attach the side to the adjacent side of the specified control.</li>
* </ul>
*/
public int alignment;
/**
* Constructs a new instance of this class.
* Since no numerator, denominator or offset is specified,
* the attachment is treated as a percentage of the form.
* The numerator is zero, the denominator is 100 and the
* offset is zero.
*
* @since 3.2
*/
public FormAttachment () {
}
/**
* Constructs a new instance of this class given a numerator
* Since no denominator or offset is specified, the default
* is to treat the numerator as a percentage of the form, with a
* denominator of 100. The offset is zero.
*
* @param numerator the percentage of the position
*
* @since 3.0
*/
public FormAttachment (int numerator) {
this (numerator, 100, 0);
}
/**
* Constructs a new instance of this class given a numerator
* and an offset. Since no denominator is specified, the default
* is to treat the numerator as a percentage of the form, with a
* denominator of 100.
*
* @param numerator the percentage of the position
* @param offset the offset of the side from the position
*/
public FormAttachment (int numerator, int offset) {
this (numerator, 100, offset);
}
/**
* Constructs a new instance of this class given a numerator
* and denominator and an offset. The position of the side is
* given by the fraction of the form defined by the numerator
* and denominator.
*
* @param numerator the numerator of the position
* @param denominator the denominator of the position
* @param offset the offset of the side from the position
*/
public FormAttachment (int numerator, int denominator, int offset) {
if (denominator == 0) SWT.error (SWT.ERROR_CANNOT_BE_ZERO);
this.numerator = numerator;
this.denominator = denominator;
this.offset = offset;
}
/**
* Constructs a new instance of this class given a control.
* Since no alignment is specified, the default alignment is
* to attach the side to the adjacent side of the specified
* control. Since no offset is specified, an offset of 0 is
* used.
*
* @param control the control the side is attached to
*/
public FormAttachment (Control control) {
this (control, 0, SWT.DEFAULT);
}
/**
* Constructs a new instance of this class given a control
* and an offset. Since no alignment is specified, the default
* alignment is to attach the side to the adjacent side of the
* specified control.
*
* @param control the control the side is attached to
* @param offset the offset of the side from the control
*/
public FormAttachment (Control control, int offset) {
this (control, offset, SWT.DEFAULT);
}
/**
* Constructs a new instance of this class given a control,
* an offset and an alignment.
*
* @param control the control the side is attached to
* @param offset the offset of the side from the control
* @param alignment the alignment of the side to the control it is attached to
*/
public FormAttachment (Control control, int offset, int alignment) {
this.control = control;
this.offset = offset;
this.alignment = alignment;
}
FormAttachment divide (int value) {
return new FormAttachment (numerator, denominator * value, offset / value);
}
int gcd (int m, int n) {
int temp;
m = Math.abs (m);
n = Math.abs (n);
if (m < n) {
temp = m;
m = n;
n = temp;
}
while (n != 0){
temp = m;
m = n;
n = temp % n;
}
return m;
}
FormAttachment minus (FormAttachment attachment) {
FormAttachment solution = new FormAttachment ();
solution.numerator = numerator * attachment.denominator - denominator * attachment.numerator;
solution.denominator = denominator * attachment.denominator;
int gcd = gcd (solution.denominator, solution.numerator);
solution.numerator = solution.numerator / gcd;
solution.denominator = solution.denominator / gcd;
solution.offset = offset - attachment.offset;
return solution;
}
FormAttachment minus (int value) {
return new FormAttachment (numerator, denominator, offset - value);
}
FormAttachment plus (FormAttachment attachment) {
FormAttachment solution = new FormAttachment ();
solution.numerator = numerator * attachment.denominator + denominator * attachment.numerator;
solution.denominator = denominator * attachment.denominator;
int gcd = gcd (solution.denominator, solution.numerator);
solution.numerator = solution.numerator / gcd;
solution.denominator = solution.denominator / gcd;
solution.offset = offset + attachment.offset;
return solution;
}
FormAttachment plus (int value) {
return new FormAttachment (numerator, denominator, offset + value);
}
int solveX (int value) {
if (denominator == 0) SWT.error (SWT.ERROR_CANNOT_BE_ZERO);
return ((numerator * value) / denominator) + offset;
}
int solveY (int value) {
if (numerator == 0) SWT.error (SWT.ERROR_CANNOT_BE_ZERO);
return (value - offset) * denominator / numerator;
}
/**
* Returns a string containing a concise, human-readable
* description of the receiver.
*
* @return a string representation of the FormAttachment
*/
public String toString () {
String string = control != null ? control.toString () : numerator + "/" + denominator;
return "{y = (" + string + (offset >= 0 ? ")x + " + offset: ")x - " + (-offset))+"}";
}
}

View File

@@ -0,0 +1,355 @@
/*
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Declarative Engineering - Major additions (overlays & minimum sizing) + maintenance, formatting, & commenting.
*/
package com.foundation.view.swt.layout;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
/**
* Instances of this class are used to define the attachments
* of a control in a <code>FormLayout</code>.
* <p>
* To set a <code>FormData</code> object into a control, you use the
* <code>setLayoutData ()</code> method. To define attachments for the
* <code>FormData</code>, set the fields directly, like this:
* <pre>
* FormData data = new FormData();
* data.left = new FormAttachment(0,5);
* data.right = new FormAttachment(100,-5);
* button.setLayoutData(formData);
* </pre>
* </p>
* <p>
* <code>FormData</code> contains the <code>FormAttachments</code> for
* each edge of the control that the <code>FormLayout</code> uses to
* determine the size and position of the control. <code>FormData</code>
* objects also allow you to set the width and height of controls within
* a <code>FormLayout</code>.
* </p>
* @see FormLayout
* @see FormAttachment
*/
public final class FormData {
/** Specifies the preferred width in pixels. This value is the wHint passed into Control.computeSize(int, int, boolean) to determine the preferred size of the control. */
public int width = SWT.DEFAULT;
/** Specifies the preferred height in pixels. This value is the hHint passed into Control.computeSize(int, int, boolean) to determine the preferred size of the control. */
public int height = SWT.DEFAULT;
/** Specifies the attachment of the left side of the control. */
public FormAttachment left;
/** Specifies the attachment of the right side of the control. */
public FormAttachment right;
/** Specifies the attachment of the top of the control. */
public FormAttachment top;
/** Specifies the attachment of the bottom of the control. */
public FormAttachment bottom;
int cacheWidth = -1;
int cacheHeight = -1;
int defaultWhint;
int defaultHhint;
int defaultWidth = -1;
int defaultHeight = -1;
int currentWhint;
int currentHhint;
int currentWidth = -1;
int currentHeight = -1;
FormAttachment cacheLeft;
FormAttachment cacheRight;
FormAttachment cacheTop;
FormAttachment cacheBottom;
boolean isVisited;
boolean needed;
/**
* Constructs a new instance of FormData using default values.
*/
public FormData() {
}//FormData()//
/**
* Constructs a new instance of FormData according to the parameters.
* A value of SWT.DEFAULT indicates that no minimum width or no minimum height is specified.
* @param width a minimum width for the control
* @param height a minimum height for the control
*/
public FormData(int width, int height) {
this.width = width;
this.height = height;
}//FormData()//
void computeSize(Control control, int wHint, int hHint, boolean flushCache) {
if(cacheWidth != -1 && cacheHeight != -1)
return;
if(wHint == this.width && hHint == this.height) {
if(defaultWidth == -1 || defaultHeight == -1 || wHint != defaultWhint || hHint != defaultHhint) {
Point size = control.computeSize(wHint, hHint, flushCache);
defaultWhint = wHint;
defaultHhint = hHint;
defaultWidth = size.x;
defaultHeight = size.y;
}
cacheWidth = defaultWidth;
cacheHeight = defaultHeight;
return;
}
if(currentWidth == -1 || currentHeight == -1 || wHint != currentWhint || hHint != currentHhint) {
Point size = control.computeSize(wHint, hHint, flushCache);
currentWhint = wHint;
currentHhint = hHint;
currentWidth = size.x;
currentHeight = size.y;
}
cacheWidth = currentWidth;
cacheHeight = currentHeight;
}//computeSize()//
void flushCache() {
cacheWidth = cacheHeight = -1;
defaultHeight = defaultWidth = -1;
currentHeight = currentWidth = -1;
}//flushCache()//
int getWidth(Control control, boolean flushCache) {
needed = true;
computeSize(control, width, height, flushCache);
return cacheWidth;
}//getWidth()//
int getHeight(Control control, boolean flushCache) {
computeSize(control, width, height, flushCache);
return cacheHeight;
}//getHeight()//
FormAttachment getBottomAttachment(Control control, int spacing, boolean flushCache) {
if(cacheBottom != null)
return cacheBottom;
if(isVisited)
return cacheBottom = new FormAttachment(0, getHeight(control, flushCache));
if(bottom == null) {
if(top == null)
return cacheBottom = new FormAttachment(0, getHeight(control, flushCache));
return cacheBottom = getTopAttachment(control, spacing, flushCache).plus(getHeight(control, flushCache));
}
Control bottomControl = bottom.control;
if(bottomControl != null) {
if(bottomControl.isDisposed()) {
bottom.control = bottomControl = null;
}
else {
if(bottomControl.getParent() != control.getParent()) {
bottomControl = null;
}
}
}
if(bottomControl == null)
return cacheBottom = bottom;
//Declarative Engineering: If the bottom control is not visible then use it's bottom attachment instead. This allows the invisible components to not waste space.//
if(!bottomControl.getVisible())
return ((FormData) bottomControl.getLayoutData()).getBottomAttachment(bottomControl, spacing, flushCache);
isVisited = true;
FormData bottomData = (FormData) bottomControl.getLayoutData();
FormAttachment bottomAttachment = bottomData.getBottomAttachment(bottomControl, spacing, flushCache);
switch(bottom.alignment) {
case SWT.BOTTOM:
cacheBottom = bottomAttachment.plus(bottom.offset);
break;
case SWT.CENTER: {
FormAttachment topAttachment = bottomData.getTopAttachment(bottomControl, spacing, flushCache);
FormAttachment bottomHeight = bottomAttachment.minus(topAttachment);
cacheBottom = bottomAttachment.minus(bottomHeight.minus(getHeight(control, flushCache)).divide(2));
break;
}
default: {
FormAttachment topAttachment = bottomData.getTopAttachment(bottomControl, spacing, flushCache);
cacheBottom = topAttachment.plus(bottom.offset - spacing);
break;
}
}
isVisited = false;
return cacheBottom;
}//getBottomAttachment()//
FormAttachment getLeftAttachment(Control control, int spacing, boolean flushCache) {
if(cacheLeft != null)
return cacheLeft;
if(isVisited)
return cacheLeft = new FormAttachment(0, 0);
if(left == null) {
if(right == null)
return cacheLeft = new FormAttachment(0, 0);
return cacheLeft = getRightAttachment(control, spacing, flushCache).minus(getWidth(control, flushCache));
}
Control leftControl = left.control;
if(leftControl != null) {
if(leftControl.isDisposed()) {
left.control = leftControl = null;
}
else {
if(leftControl.getParent() != control.getParent()) {
leftControl = null;
}
}
}
if(leftControl == null)
return cacheLeft = left;
isVisited = true;
FormData leftData = (FormData) leftControl.getLayoutData();
FormAttachment leftAttachment = leftData.getLeftAttachment(leftControl, spacing, flushCache);
switch(left.alignment) {
case SWT.LEFT:
cacheLeft = leftAttachment.plus(left.offset);
break;
case SWT.CENTER: {
FormAttachment rightAttachment = leftData.getRightAttachment(leftControl, spacing, flushCache);
FormAttachment leftWidth = rightAttachment.minus(leftAttachment);
cacheLeft = leftAttachment.plus(leftWidth.minus(getWidth(control, flushCache)).divide(2));
break;
}
default: {
FormAttachment rightAttachment = leftData.getRightAttachment(leftControl, spacing, flushCache);
cacheLeft = rightAttachment.plus(left.offset + spacing);
}
}
isVisited = false;
return cacheLeft;
}//getLeftAttachment()//
FormAttachment getRightAttachment(Control control, int spacing, boolean flushCache) {
if(cacheRight != null)
return cacheRight;
if(isVisited)
return cacheRight = new FormAttachment(0, getWidth(control, flushCache));
if(right == null) {
if(left == null)
return cacheRight = new FormAttachment(0, getWidth(control, flushCache));
return cacheRight = getLeftAttachment(control, spacing, flushCache).plus(getWidth(control, flushCache));
}
Control rightControl = right.control;
if(rightControl != null) {
if(rightControl.isDisposed()) {
right.control = rightControl = null;
}
else {
if(rightControl.getParent() != control.getParent()) {
rightControl = null;
}
}
}
if(rightControl == null)
return cacheRight = right;
isVisited = true;
FormData rightData = (FormData) rightControl.getLayoutData();
FormAttachment rightAttachment = rightData.getRightAttachment(rightControl, spacing, flushCache);
switch(right.alignment) {
case SWT.RIGHT:
cacheRight = rightAttachment.plus(right.offset);
break;
case SWT.CENTER: {
FormAttachment leftAttachment = rightData.getLeftAttachment(rightControl, spacing, flushCache);
FormAttachment rightWidth = rightAttachment.minus(leftAttachment);
cacheRight = rightAttachment.minus(rightWidth.minus(getWidth(control, flushCache)).divide(2));
break;
}
default: {
FormAttachment leftAttachment = rightData.getLeftAttachment(rightControl, spacing, flushCache);
cacheRight = leftAttachment.plus(right.offset - spacing);
break;
}
}
isVisited = false;
return cacheRight;
}//getRightAttachment()//
/**
* Gets the top attachment.
* @param control
* @param spacing
* @param flushCache
* @return
*/
FormAttachment getTopAttachment(Control control, int spacing, boolean flushCache) {
if(cacheTop == null) {
if(isVisited) {
cacheTop = new FormAttachment(0, 0);
}//if//
else if(top == null) {
if(bottom == null) {
cacheTop = new FormAttachment(0, 0);
}//if//
else {
cacheTop = getBottomAttachment(control, spacing, flushCache).minus(getHeight(control, flushCache));
}//else//
}//else if//
else {
Control topControl = top.control;
if(topControl != null) {
if(topControl.isDisposed()) {
top.control = topControl = null;
}//if//
else if(topControl.getParent() != control.getParent()) {
topControl = null;
}//else if//
}//if//
if(topControl == null) {
cacheTop = top;
}//if//
else {
isVisited = true;
FormData topData = (FormData) topControl.getLayoutData();
FormAttachment topAttachment = topData.getTopAttachment(topControl, spacing, flushCache);
switch(top.alignment) {
case SWT.TOP: {
cacheTop = topAttachment.plus(top.offset);
break;
}//case//
case SWT.CENTER: {
FormAttachment bottomAttachment = topData.getBottomAttachment(topControl, spacing, flushCache);
FormAttachment topHeight = bottomAttachment.minus(topAttachment);
cacheTop = topAttachment.plus(topHeight.minus(getHeight(control, flushCache)).divide(2));
break;
}//case//
default: {
FormAttachment bottomAttachment = topData.getBottomAttachment(topControl, spacing, flushCache);
cacheTop = bottomAttachment.plus(top.offset + spacing);
break;
}//default//
}//switch//
isVisited = false;
}//else//
}//else//
}//if//
return cacheTop;
}//getTopAttachment()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
String string = "FormData {";
if(width != SWT.DEFAULT)
string += "width=" + width + " ";
if(height != SWT.DEFAULT)
string += "height=" + height + " ";
if(left != null)
string += "left=" + left + " ";
if(right != null)
string += "right=" + right + " ";
if(top != null)
string += "top=" + top + " ";
if(bottom != null)
string += "bottom=" + bottom + " ";
string = string.trim();
string += "}";
return string;
}//toString()//
}//FormData//

View File

@@ -0,0 +1,543 @@
/*
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Declarative Engineering - Major additions (overlays & minimum sizing) + maintenance, formatting, & commenting.
*/
package com.foundation.view.swt.layout;
import java.util.Arrays;
import java.util.Comparator;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
import com.foundation.view.swt.IOverlay;
/**
* <p>This is a modified version of the Eclipse layout.</p>
* Instances of this class control the position and size of the
* children of a composite control by using <code>FormAttachments</code>
* to optionally configure the left, top, right and bottom edges of
* each child.
* <p>
* The following example code creates a <code>FormLayout</code> and then sets
* it into a <code>Shell</code>:
* <pre>
* Display display = new Display ();
* Shell shell = new Shell(display);
* FormLayout layout = new FormLayout();
* layout.marginWidth = 3;
* layout.marginHeight = 3;
* shell.setLayout(layout);
* </pre>
* </p>
* <p>
* To use a <code>FormLayout</code>, create a <code>FormData</code> with
* <code>FormAttachment</code> for each child of <code>Composite</code>.
* The following example code attaches <code>button1</code> to the top
* and left edge of the composite and <code>button2</code> to the right
* edge of <code>button1</code> and the top and right edges of the
* composite:
* <pre>
* FormData data1 = new FormData();
* data1.left = new FormAttachment(0, 0);
* data1.top = new FormAttachment(0, 0);
* button1.setLayoutData(data1);
* FormData data2 = new FormData();
* data2.left = new FormAttachment(button1);
* data2.top = new FormAttachment(0, 0);
* data2.right = new FormAttachment(100, 0);
* button2.setLayoutData(data2);
* </pre>
* </p>
* <p>
* Each side of a child control can be attached to a position in the parent
* composite, or to other controls within the <code>Composite</code> by
* creating instances of <code>FormAttachment</code> and setting them into
* the top, bottom, left, and right fields of the child's <code>FormData</code>.
* </p>
* <p>
* If a side is not given an attachment, it is defined as not being attached
* to anything, causing the child to remain at its preferred size. If a child
* is given no attachment on either the left or the right or top or bottom, it is
* automatically attached to the left and top of the composite respectively.
* The following code positions <code>button1</code> and <code>button2</code>
* but relies on default attachments:
* <pre>
* FormData data2 = new FormData();
* data2.left = new FormAttachment(button1);
* data2.right = new FormAttachment(100, 0);
* button2.setLayoutData(data2);
* </pre>
* </p>
* <p>
* IMPORTANT: Do not define circular attachments. For example, do not attach
* the right edge of <code>button1</code> to the left edge of <code>button2</code>
* and then attach the left edge of <code>button2</code> to the right edge of
* <code>button1</code>. This will over constrain the layout, causing undefined
* behavior. The algorithm will terminate, but the results are undefined.
* </p>
*
* @see FormData
* @see FormAttachment
*
* @since 2.0
*
*/
public final class FormLayout extends Layout {
/** Specifies the number of pixels of horizontal margin that will be placed along the left and right edges of the layout. */
public int marginWidth = 0;
/** Specifies the number of pixels of vertical margin that will be placed along the top and bottom edges of the layout. */
public int marginHeight = 0;
/** Specifies the number of pixels of horizontal margin that will be placed along the left edge of the layout. */
public int marginLeft = 0;
/** Specifies the number of pixels of vertical margin that will be placed along the top edge of the layout. */
public int marginTop = 0;
/** Specifies the number of pixels of horizontal margin that will be placed along the right edge of the layout. */
public int marginRight = 0;
/** Specifies the number of pixels of vertical margin that will be placed along the bottom edge of the layout. */
public int marginBottom = 0;
/** Specifies the number of pixels between the edge of one control and the edge of its neighbouring control. */
public int spacing = 0;
/** The cached minimum width. Saves us having to layout to figure it out. */
private int cachedMinWidth = -1;
/** The cached minimum height. Saves us having to layout to figure it out. */
private int cachedMinHeight = -1;
/**
* Constructs a new instance of this class.
*/
public FormLayout() {
}//FormLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#computeCurrentSize(org.eclipse.swt.widgets.Composite)
*/
public Point computeCurrentSize(Composite composite) {
Point result = super.computeCurrentSize(composite);
result.x += marginRight + marginWidth;
result.y += marginBottom + marginHeight;
return result;
}//computeCurrentSize()//
/**
* Computes the preferred height of the form with respect to the preferred height of the control.
* <p>Given that the equations for top (T) and bottom (B) of the control in terms of the height of the form (X) are:<pre>
* T = AX + B
* B = CX + D</pre></p>
* <p>The equation for the height of the control (H) is bottom (B) minus top (T) or (H = B - T) or:</pre>
* H = (CX + D) - (AX + B)</pre></p>
*
* <p>Solving for (X), the height of the form, we get:</pre>
* X = (H + B - D) / (C - A)</pre></p>
*
* When (A = C), (C - A = 0) and the equation has no
* solution for X. This is a special case meaning that
* the control does not constrain the height of the
* form. In this case, we need to arbitrarily define
* the height of the form (X):<pre>
*
* Case 1: A = C, A = 0, C = 0
*
* Let X = D, the distance from the top of the form
* to the bottom edge of the control. In this case,
* the control was attatched to the top of the form
* and the form needs to be large enough to show the
* bottom edge of the control.
*
* Case 2: A = C, A = 1, C = 1
*
* Let X = -B, the distance from the bottom of the
* form to the top edge of the control. In this case,
* the control was attached to the bottom of the form
* and the only way that the control would be visible
* is if the offset is negative. If the offset is
* positive, there is no possible height for the form
* that will show the control as it will always be
* below the bottom edge of the form.
*
* Case 3: A = C, A != 0, C != 0 and A != 1, C != 0
*
* Let X = D / (1 - C), the distance from the top of the
* form to the bottom edge of the control. In this case,
* since C is not 0 or 1, it must be a fraction, U / V.
* The offset D is the distance from CX to the bottom edge
* of the control. This represents a fraction of the form
* (1 - C)X. Since the height of a fraction of the form is
* known, the height of the entire form can be found by setting
* (1 - C)X = D. We solve this equation for X in terms of U
* and V, giving us X = (U * D) / (U - V). Similarily, if the
* offset D is negative, the control is positioned above CX.
* The offset -B is the distance from the top edge of the control
* to CX. We can find the height of the entire form by setting
* CX = -B. Solving in terms of U and V gives us X = (-B * V) / U.
* </pre>
*/
int computeHeight(Control control, FormData data, boolean flushCache) {
FormAttachment top = data.getTopAttachment(control, spacing, flushCache);
FormAttachment bottom = data.getBottomAttachment(control, spacing, flushCache);
FormAttachment height = bottom.minus(top);
int result;
if(height.numerator == 0) {
if(bottom.numerator == 0) {
result = bottom.offset;
}//if//
else if(bottom.numerator == bottom.denominator) {
result = -top.offset;
}//else if//
else if(bottom.offset <= 0) {
result = -top.offset * top.denominator / bottom.numerator;
}//else if//
else {
result = bottom.denominator * bottom.offset / (bottom.denominator - bottom.numerator);
}//else//
}//if//
else {
result = height.solveY(data.getHeight(control, flushCache));
}//else//
return result;
}//computeHeight()//
/**
* Computes the preferred width of the form with respect to the preferred width of the control.
*/
int computeWidth(Control control, FormData data, boolean flushCache) {
FormAttachment left = data.getLeftAttachment(control, spacing, flushCache);
FormAttachment right = data.getRightAttachment(control, spacing, flushCache);
FormAttachment width = right.minus(left);
int result;
if(width.numerator == 0) {
if(right.numerator == 0) {
result = right.offset;
}//if//
else if(right.numerator == right.denominator) {
result = -left.offset;
}//else if//
else if(right.offset <= 0) {
result = -left.offset * left.denominator / left.numerator;
}//else if//
else {
result = right.denominator * right.offset / (right.denominator - right.numerator);
}//else//
}//if//
else {
result = width.solveY(data.getWidth(control, flushCache));
}//else//
return result;
}//computeWidth()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int, boolean)
*/
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
Point size = layout(composite, false, 0, 0, wHint, hHint, flushCache);
if(wHint != SWT.DEFAULT) {
size.x = wHint;
}//if//
if(hHint != SWT.DEFAULT) {
size.y = hHint;
}//if//
return size;
}//computeSize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#computeMinSize(org.eclipse.swt.graphics.Point, org.eclipse.swt.widgets.Composite, boolean)
*/
public void computeMinSize(Point result, Composite composite, boolean flushCache) {
//TODO: Finish implementing - didn't finish because this layout is currently never used. The layout method will need modifications to get the minimum size and update the cached values.
// if(flushCache) {
// cachedMinWidth = -1;
// cachedMinHeight = -1;
// }//if//
//
// if(cachedMinWidth == -1 || cachedMinHeight == -1) {
// layout(composite, false, 0, 0, -1, -1, flushCache);
// }//if//
//
// result.x = cachedMinWidth;
// result.y = cachedMinHeight;
result.x = 0;
result.y = 0;
}//computeMinSize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#flushCache(org.eclipse.swt.widgets.Control)
*/
public boolean flushCache(Control control) {
Object data = control.getLayoutData();
if(data != null)
((FormData) data).flushCache();
return true;
}//flushCache()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
*/
protected void layout(Composite composite, boolean flushCache) {
Rectangle rect = composite.getClientArea();
int x = rect.x + marginLeft + marginWidth;
int y = rect.y + marginTop + marginHeight;
int width = Math.max(0, rect.width - marginLeft - 2 * marginWidth - marginRight);
int height = Math.max(0, rect.height - marginTop - 2 * marginHeight - marginBottom);
layout(composite, true, x, y, width, height, flushCache);
}//layout()//
/**
* Lays out the composite.
* @param composite
* @param move
* @param x
* @param y
* @param width
* @param height
* @param flushCache
* @return The size of the composite.
*/
Point layout(Composite composite, boolean move, int x, int y, int width, int height, boolean flushCache) {
Control[] children = composite.getChildren();
int count = 0;
IOverlay[] overlayChildren = new IOverlay[children.length];
int overlayCount = 0;
for(int index = 0; index < children.length; index++) {
if(children[index] instanceof IOverlay) {
overlayChildren[overlayCount++] = (IOverlay) children[index];
}//if//
else {
Control child = children[index];
FormData data = (FormData) child.getLayoutData();
if(data == null) {
child.setLayoutData(data = new FormData());
}//if//
if(flushCache) {
data.flushCache();
}//if//
data.cacheLeft = data.cacheRight = data.cacheTop = data.cacheBottom = null;
children[count++] = children[index];
}//else//
}//for//
boolean[] flush = null;
Rectangle[] area = null;
int w = 0;
int h = 0;
for(int i = 0; i < count; i++) {
Control child = children[i];
FormData data = (FormData) child.getLayoutData();
//Declarative Engineering: Set invisible children to have no size.//
if(!child.getVisible()) {
if(move) {
if(area == null) {
area = new Rectangle[count];
}//if//
area[i] = new Rectangle(0, 0, 0, 0);
area[i].x = x + data.getLeftAttachment(child, spacing, flushCache).solveX(width);
area[i].width = 0;
}//if//
}//if//
else {
if(width != SWT.DEFAULT) {
data.needed = false;
FormAttachment left = data.getLeftAttachment(child, spacing, flushCache);
FormAttachment right = data.getRightAttachment(child, spacing, flushCache);
int x1 = left.solveX(width);
int x2 = right.solveX(width);
if(data.height == SWT.DEFAULT && !data.needed) {
int trim = 0;
//TEMPORARY CODE
if(child instanceof Scrollable) {
Rectangle rect = ((Scrollable) child).computeTrim(0, 0, 0, 0);
trim = rect.width;
}//if//
else {
trim = child.getBorderWidth() * 2;
}//else//
data.cacheWidth = data.cacheHeight = -1;
int currentWidth = Math.max(0, x2 - x1 - trim);
data.computeSize(child, currentWidth, data.height, flushCache);
if(flush == null) {
flush = new boolean[count];
}//if//
flush[i] = true;
}//if//
w = Math.max(x2, w);
if(move) {
if(area == null) {
area = new Rectangle[count];
}//if//
area[i] = new Rectangle(0, 0, 0, 0);
area[i].x = x + x1;
area[i].width = x2 - x1;
}//if//
}//if//
else {
w = Math.max(computeWidth(child, data, flushCache), w);
}//else//
}//else//
}//for//
for(int i = 0; i < count; i++) {
Control child = children[i];
FormData data = (FormData) child.getLayoutData();
//Declarative Engineering: Set invisible children to have no size.//
if(!child.getVisible()) {
if(move) {
area[i].y = data.getTopAttachment(child, spacing, flushCache).solveX(height);
area[i].height = 0;
}//if//
}//if//
else {
if(height != SWT.DEFAULT) {
int y1 = data.getTopAttachment(child, spacing, flushCache).solveX(height);
int y2 = data.getBottomAttachment(child, spacing, flushCache).solveX(height);
h = Math.max(y2, h);
if(move) {
area[i].y = y + y1;
area[i].height = y2 - y1;
}//if//
}//if//
else {
h = Math.max(computeHeight(child, data, flushCache), h);
}//else//
}//else//
}//for//
for(int i = 0; i < count; i++) {
Control child = children[i];
FormData data = (FormData) child.getLayoutData();
if(flush != null && flush[i]) {
data.cacheWidth = data.cacheHeight = -1;
}//if//
data.cacheLeft = data.cacheRight = data.cacheTop = data.cacheBottom = null;
}//for//
if(move) {
for(int i = 0; i < count; i++) {
children[i].setBounds(area[i]);
}//for//
}//if//
w += marginLeft + marginWidth * 2 + marginRight;
h += marginTop + marginHeight * 2 + marginBottom;
if(overlayCount > 0) { //Declarative Engineering: Layout the overlays.//
int upperLeftOffset = 0;
int upperRightOffset = 0;
int lowerLeftOffset = 0;
int lowerRightOffset = 0;
Control lastPeer = null;
Arrays.sort(overlayChildren, 0, overlayCount, new Comparator() {
public int compare(Object arg0, Object arg1) {
return ((IOverlay) arg0).getPeerControl().hashCode() - ((IOverlay) arg1).getPeerControl().hashCode();
}//compare()//
});
for(int index = 0; index < overlayCount; index++) {
IOverlay overlay = overlayChildren[index];
Control peer = overlay.getPeerControl();
Rectangle bounds = peer.getBounds();
Point size = overlay.getSize();
if(peer != lastPeer) {
upperLeftOffset = 0;
upperRightOffset = 0;
lowerLeftOffset = 0;
lowerRightOffset = 0;
lastPeer = peer;
}//if//
switch(overlay.getPosition()) {
case IOverlay.POSITION_UPPER_LEFT: {
bounds.x += overlay.getHorizontalOffset() + upperLeftOffset;
bounds.y += overlay.getVerticalOffset();
bounds.width = size.x;
bounds.height = size.y;
upperLeftOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_UPPER_RIGHT: {
bounds.x += bounds.width + (overlay.getHorizontalOffset() * -1) - size.x - upperRightOffset;
bounds.y += overlay.getVerticalOffset();
bounds.width = size.x;
bounds.height = size.y;
upperRightOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_LOWER_RIGHT: {
bounds.x += bounds.width + (overlay.getHorizontalOffset() * -1) - size.x - lowerRightOffset;
bounds.y += bounds.height + (overlay.getVerticalOffset() * -1) - size.y;
bounds.width = size.x;
bounds.height = size.y;
lowerRightOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_LOWER_LEFT: {
bounds.x += overlay.getHorizontalOffset() + lowerLeftOffset;
bounds.y += bounds.height + (overlay.getVerticalOffset() * -1) - size.y;
bounds.width = size.x;
bounds.height = size.y;
lowerLeftOffset += bounds.width + 1;
break;
}//case//
}//switch//
((Control) overlay).setBounds(bounds);
}//for//
}//block//
return new Point(w, h);
}//layout()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
String string = "FormLayout {";
if(marginWidth != 0)
string += "marginWidth=" + marginWidth + " ";
if(marginHeight != 0)
string += "marginHeight=" + marginHeight + " ";
if(marginLeft != 0)
string += "marginLeft=" + marginLeft + " ";
if(marginRight != 0)
string += "marginRight=" + marginRight + " ";
if(marginTop != 0)
string += "marginTop=" + marginTop + " ";
if(marginBottom != 0)
string += "marginBottom=" + marginBottom + " ";
if(spacing != 0)
string += "spacing=" + spacing + " ";
string = string.trim();
string += "}";
return string;
}//toString()//
}//FormLayout//

View File

@@ -0,0 +1,619 @@
/*
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Declarative Engineering - Major additions (overlays & minimum sizing) + maintenance, formatting, & commenting.
*/
package com.foundation.view.swt.layout;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
/**
* <code>GridData</code> is the layout data object associated with
* <code>GridLayout</code>. To set a <code>GridData</code> object into a
* control, you use the <code>Control.setLayoutData(Object)</code> method.
* <p>
* There are two ways to create a <code>GridData</code> object with certain
* fields set. The first is to set the fields directly, like this:
* <pre>
* GridData gridData = new GridData();
* gridData.horizontalAlignment = GridData.FILL;
* gridData.grabExcessHorizontalSpace = true;
* button1.setLayoutData(gridData);
* </pre>
* The second is to take advantage of convenience style bits defined
* by <code>GridData</code>:
* <pre>
* button1.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
* </pre>
* </p>
* <p>
* NOTE: Do not reuse <code>GridData</code> objects. Every control in a
* <code>Composite</code> that is managed by a <code>GridLayout</code>
* must have a unique <code>GridData</code> object. If the layout data
* for a control in a <code>GridLayout</code> is null at layout time,
* a unique <code>GridData</code> object is created for it.
* </p>
*
* @see GridLayout
* @see Control#setLayoutData
*/
public final class GridData {
/**
* verticalAlignment specifies how controls will be positioned
* vertically within a cell.
*
* The default value is CENTER.
*
* Possible values are: <ul>
* <li>SWT.BEGINNING (or SWT.TOP): Position the control at the top of the cell</li>
* <li>SWT.CENTER: Position the control in the vertical center of the cell</li>
* <li>SWT.END (or SWT.BOTTOM): Position the control at the bottom of the cell</li>
* <li>SWT.FILL: Resize the control to fill the cell vertically</li>
* </ul>
*/
public int verticalAlignment = CENTER;
/**
* horizontalAlignment specifies how controls will be positioned
* horizontally within a cell.
*
* The default value is BEGINNING.
*
* Possible values are: <ul>
* <li>SWT.BEGINNING (or SWT.LEFT): Position the control at the left of the cell</li>
* <li>SWT.CENTER: Position the control in the horizontal center of the cell</li>
* <li>SWT.END (or SWT.RIGHT): Position the control at the right of the cell</li>
* <li>SWT.FILL: Resize the control to fill the cell horizontally</li>
* </ul>
*/
public int horizontalAlignment = BEGINNING;
/**
* widthHint specifies the preferred width in pixels. This value
* is the wHint passed into Control.computeSize(int, int, boolean)
* to determine the preferred size of the control.
*
* The default value is SWT.DEFAULT.
*
* @see Control#computeSize(int, int, boolean)
*/
public int widthHint = SWT.DEFAULT;
/**
* heightHint specifies the preferred height in pixels. This value
* is the hHint passed into Control.computeSize(int, int, boolean)
* to determine the preferred size of the control.
*
* The default value is SWT.DEFAULT.
*
* @see Control#computeSize(int, int, boolean)
*/
public int heightHint = SWT.DEFAULT;
/**
* horizontalIndent specifies the number of pixels of indentation
* that will be placed along the left side of the cell.
*
* The default value is 0.
*/
public int horizontalIndent = 0;
/**
* verticalIndent specifies the number of pixels of indentation
* that will be placed along the top side of the cell.
*
* The default value is 0.
*
* @since 3.1
*/
public int verticalIndent = 0;
/**
* horizontalSpan specifies the number of column cells that the control
* will take up.
*
* The default value is 1.
*/
public int horizontalSpan = 1;
/**
* verticalSpan specifies the number of row cells that the control
* will take up.
*
* The default value is 1.
*/
public int verticalSpan = 1;
/**
* <p>grabExcessHorizontalSpace specifies whether the width of the cell
* changes depending on the size of the parent Composite. If
* grabExcessHorizontalSpace is <code>true</code>, the following rules
* apply to the width of the cell:</p>
* <ul>
* <li>If extra horizontal space is available in the parent, the cell will
* grow to be wider than its preferred width. The new width
* will be "preferred width + delta" where delta is the extra
* horizontal space divided by the number of grabbing columns.</li>
* <li>If there is not enough horizontal space available in the parent, the
* cell will shrink until it reaches its minimum width as specified by
* GridData.minimumWidth. The new width will be the maximum of
* "minimumWidth" and "preferred width - delta", where delta is
* the amount of space missing divided by the number of grabbing columns.</li>
* <li>If the parent is packed, the cell will be its preferred width
* as specified by GridData.widthHint.</li>
* <li>If the control spans multiple columns and there are no other grabbing
* controls in any of the spanned columns, the last column in the span will
* grab the extra space. If there is at least one other grabbing control
* in the span, the grabbing will be spread over the columns already
* marked as grabExcessHorizontalSpace.</li>
* </ul>
*
* <p>The default value is false.</p>
*
* @see GridData#minimumWidth
* @see GridData#widthHint
*/
public boolean grabExcessHorizontalSpace = false;
/**
* <p>grabExcessVerticalSpace specifies whether the height of the cell
* changes depending on the size of the parent Composite. If
* grabExcessVerticalSpace is <code>true</code>, the following rules
* apply to the height of the cell:</p>
* <ul>
* <li>If extra vertical space is available in the parent, the cell will
* grow to be taller than its preferred height. The new height
* will be "preferred height + delta" where delta is the extra
* vertical space divided by the number of grabbing rows.</li>
* <li>If there is not enough vertical space available in the parent, the
* cell will shrink until it reaches its minimum height as specified by
* GridData.minimumHeight. The new height will be the maximum of
* "minimumHeight" and "preferred height - delta", where delta is
* the amount of space missing divided by the number of grabbing rows.</li>
* <li>If the parent is packed, the cell will be its preferred height
* as specified by GridData.heightHint.</li>
* <li>If the control spans multiple rows and there are no other grabbing
* controls in any of the spanned rows, the last row in the span will
* grab the extra space. If there is at least one other grabbing control
* in the span, the grabbing will be spread over the rows already
* marked as grabExcessVerticalSpace.</li>
* </ul>
*
* <p>The default value is false.</p>
*
* @see GridData#minimumHeight
* @see GridData#heightHint
*/
public boolean grabExcessVerticalSpace = false;
/**
* <p>TODO: This should really default to -1, and a value of -1 should be using the control's minimum. Currently 0 or -1 uses the control's minimum, but not for the layout - only for reporting a total minimum for the layout.</p>
* minimumWidth specifies the minimum width in pixels. This value
* applies only if grabExcessHorizontalSpace is true. A value of
* SWT.DEFAULT means that the minimum width will be the result
* of Control.computeSize(int, int, boolean) where wHint is
* determined by GridData.widthHint.
*
* The default value is 0.
*
* @since 3.1
* @see Control#computeSize(int, int, boolean)
* @see GridData#widthHint
*/
public int minimumWidth = 0;
/**
* <p>TODO: This should really default to -1, and a value of -1 should be using the control's minimum. Currently 0 or -1 uses the control's minimum, but not for the layout - only for reporting a total minimum for the layout.</p>
* minimumHeight specifies the minimum height in pixels. This value
* applies only if grabExcessVerticalSpace is true. A value of
* SWT.DEFAULT means that the minimum height will be the result
* of Control.computeSize(int, int, boolean) where hHint is
* determined by GridData.heightHint.
*
* The default value is 0.
*
* @since 3.1
* @see Control#computeSize(int, int, boolean)
* @see GridData#heightHint
*/
public int minimumHeight = 0;
/**
* exclude informs the layout to ignore this control when sizing
* and positioning controls. If this value is <code>true</code>,
* the size and position of the control will not be managed by the
* layout. If this value is <code>false</code>, the size and
* position of the control will be computed and assigned.
*
* The default value is <code>false</code>.
*
* @since 3.1
*/
public boolean exclude = false;
/**
* Value for horizontalAlignment or verticalAlignment.
* Position the control at the top or left of the cell.
* Not recommended. Use SWT.BEGINNING, SWT.TOP or SWT.LEFT instead.
*/
public static final int BEGINNING = SWT.BEGINNING;
/**
* Value for horizontalAlignment or verticalAlignment.
* Position the control in the vertical or horizontal center of the cell
* Not recommended. Use SWT.CENTER instead.
*/
public static final int CENTER = 2;
/**
* Value for horizontalAlignment or verticalAlignment.
* Position the control at the bottom or right of the cell
* Not recommended. Use SWT.END, SWT.BOTTOM or SWT.RIGHT instead.
*/
public static final int END = 3;
/**
* Value for horizontalAlignment or verticalAlignment.
* Resize the control to fill the cell horizontally or vertically.
* Not recommended. Use SWT.FILL instead.
*/
public static final int FILL = SWT.FILL;
/**
* Style bit for <code>new GridData(int)</code>.
* Position the control at the top of the cell.
* Not recommended. Use
* <code>new GridData(int, SWT.BEGINNING, boolean, boolean)</code>
* instead.
*/
public static final int VERTICAL_ALIGN_BEGINNING = 1 << 1;
/**
* Style bit for <code>new GridData(int)</code> to position the
* control in the vertical center of the cell.
* Not recommended. Use
* <code>new GridData(int, SWT.CENTER, boolean, boolean)</code>
* instead.
*/
public static final int VERTICAL_ALIGN_CENTER = 1 << 2;
/**
* Style bit for <code>new GridData(int)</code> to position the
* control at the bottom of the cell.
* Not recommended. Use
* <code>new GridData(int, SWT.END, boolean, boolean)</code>
* instead.
*/
public static final int VERTICAL_ALIGN_END = 1 << 3;
/**
* Style bit for <code>new GridData(int)</code> to resize the
* control to fill the cell vertically.
* Not recommended. Use
* <code>new GridData(int, SWT.FILL, boolean, boolean)</code>
* instead
*/
public static final int VERTICAL_ALIGN_FILL = 1 << 4;
/**
* Style bit for <code>new GridData(int)</code> to position the
* control at the left of the cell.
* Not recommended. Use
* <code>new GridData(SWT.BEGINNING, int, boolean, boolean)</code>
* instead.
*/
public static final int HORIZONTAL_ALIGN_BEGINNING = 1 << 5;
/**
* Style bit for <code>new GridData(int)</code> to position the
* control in the horizontal center of the cell.
* Not recommended. Use
* <code>new GridData(SWT.CENTER, int, boolean, boolean)</code>
* instead.
*/
public static final int HORIZONTAL_ALIGN_CENTER = 1 << 6;
/**
* Style bit for <code>new GridData(int)</code> to position the
* control at the right of the cell.
* Not recommended. Use
* <code>new GridData(SWT.END, int, boolean, boolean)</code>
* instead.
*/
public static final int HORIZONTAL_ALIGN_END = 1 << 7;
/**
* Style bit for <code>new GridData(int)</code> to resize the
* control to fill the cell horizontally.
* Not recommended. Use
* <code>new GridData(SWT.FILL, int, boolean, boolean)</code>
* instead.
*/
public static final int HORIZONTAL_ALIGN_FILL = 1 << 8;
/**
* Style bit for <code>new GridData(int)</code> to resize the
* control to fit the remaining horizontal space.
* Not recommended. Use
* <code>new GridData(int, int, true, boolean)</code>
* instead.
*/
public static final int GRAB_HORIZONTAL = 1 << 9;
/**
* Style bit for <code>new GridData(int)</code> to resize the
* control to fit the remaining vertical space.
* Not recommended. Use
* <code>new GridData(int, int, boolean, true)</code>
* instead.
*/
public static final int GRAB_VERTICAL = 1 << 10;
/**
* Style bit for <code>new GridData(int)</code> to resize the
* control to fill the cell vertically and to fit the remaining
* vertical space.
* FILL_VERTICAL = VERTICAL_ALIGN_FILL | GRAB_VERTICAL
* Not recommended. Use
* <code>new GridData(int, SWT.FILL, boolean, true)</code>
* instead.
*/
public static final int FILL_VERTICAL = VERTICAL_ALIGN_FILL | GRAB_VERTICAL;
/**
* Style bit for <code>new GridData(int)</code> to resize the
* control to fill the cell horizontally and to fit the remaining
* horizontal space.
* FILL_HORIZONTAL = HORIZONTAL_ALIGN_FILL | GRAB_HORIZONTAL
* Not recommended. Use
* <code>new GridData(SWT.FILL, int, true, boolean)</code>
* instead.
*/
public static final int FILL_HORIZONTAL = HORIZONTAL_ALIGN_FILL | GRAB_HORIZONTAL;
/**
* Style bit for <code>new GridData(int)</code> to resize the
* control to fill the cell horizontally and vertically and
* to fit the remaining horizontal and vertical space.
* FILL_BOTH = FILL_VERTICAL | FILL_HORIZONTAL
* Not recommended. Use
* <code>new GridData(SWT.FILL, SWT.FILL, true, true)</code>
* instead.
*/
public static final int FILL_BOTH = FILL_VERTICAL | FILL_HORIZONTAL;
int cacheWidth = -1;
int cacheHeight = -1;
int defaultWhint;
int defaultHhint;
int defaultWidth = -1;
int defaultHeight = -1;
int currentWhint;
int currentHhint;
int currentWidth = -1;
int currentHeight = -1;
//Declarative Engineering//
int cacheHSpan = -1;
int cacheVSpan = -1;
/**
* Constructs a new instance of GridData using default values.
*/
public GridData() {
super();
}//GridData()//
/**
* Constructs a new instance based on the GridData style.
* This constructor is not recommended.
*
* @param style the GridData style
*/
public GridData(int style) {
super();
if((style & VERTICAL_ALIGN_BEGINNING) != 0)
verticalAlignment = BEGINNING;
if((style & VERTICAL_ALIGN_CENTER) != 0)
verticalAlignment = CENTER;
if((style & VERTICAL_ALIGN_FILL) != 0)
verticalAlignment = FILL;
if((style & VERTICAL_ALIGN_END) != 0)
verticalAlignment = END;
if((style & HORIZONTAL_ALIGN_BEGINNING) != 0)
horizontalAlignment = BEGINNING;
if((style & HORIZONTAL_ALIGN_CENTER) != 0)
horizontalAlignment = CENTER;
if((style & HORIZONTAL_ALIGN_FILL) != 0)
horizontalAlignment = FILL;
if((style & HORIZONTAL_ALIGN_END) != 0)
horizontalAlignment = END;
grabExcessHorizontalSpace = (style & GRAB_HORIZONTAL) != 0;
grabExcessVerticalSpace = (style & GRAB_VERTICAL) != 0;
}//GridData()//
/**
* Constructs a new instance of GridData according to the parameters.
*
* @param horizontalAlignment how control will be positioned horizontally within a cell
* @param verticalAlignment how control will be positioned vertically within a cell
* @param grabExcessHorizontalSpace whether cell will be made wide enough to fit the remaining horizontal space
* @param grabExcessVerticalSpace whether cell will be made high enough to fit the remaining vertical space
*
* @since 3.0
*/
public GridData(int horizontalAlignment, int verticalAlignment, boolean grabExcessHorizontalSpace, boolean grabExcessVerticalSpace) {
this(horizontalAlignment, verticalAlignment, grabExcessHorizontalSpace, grabExcessVerticalSpace, 1, 1);
}//GridData()//
/**
* Constructs a new instance of GridData according to the parameters.
*
* @param horizontalAlignment how control will be positioned horizontally within a cell
* @param verticalAlignment how control will be positioned vertically within a cell
* @param grabExcessHorizontalSpace whether cell will be made wide enough to fit the remaining horizontal space
* @param grabExcessVerticalSpace whether cell will be made high enough to fit the remaining vertical space
* @param horizontalSpan the number of column cells that the control will take up
* @param verticalSpan the number of row cells that the control will take up
*
* @since 3.0
*/
public GridData(int horizontalAlignment, int verticalAlignment, boolean grabExcessHorizontalSpace, boolean grabExcessVerticalSpace, int horizontalSpan, int verticalSpan) {
super();
this.horizontalAlignment = horizontalAlignment;
this.verticalAlignment = verticalAlignment;
this.grabExcessHorizontalSpace = grabExcessHorizontalSpace;
this.grabExcessVerticalSpace = grabExcessVerticalSpace;
this.horizontalSpan = horizontalSpan;
this.verticalSpan = verticalSpan;
}//GridData()//
/**
* Computes the size of given control, described by this grid data.
* @param control The control referencing this grid data.
* @param wHint The width hint.
* @param hHint The height hint.
* @param flushCache Whether to flush the cache.
*/
void computeSize(Control control, int wHint, int hHint, boolean flushCache) {
if(cacheWidth == -1 || cacheHeight == -1) {
if(wHint == this.widthHint && hHint == this.heightHint) {
if(defaultWidth == -1 || defaultHeight == -1 || wHint != defaultWhint || hHint != defaultHhint) {
Point size = control.computeSize(wHint, hHint, flushCache);
defaultWhint = wHint;
defaultHhint = hHint;
defaultWidth = size.x;
defaultHeight = size.y;
}//if//
cacheWidth = defaultWidth;
cacheHeight = defaultHeight;
return;
}//if//
if(currentWidth == -1 || currentHeight == -1 || wHint != currentWhint || hHint != currentHhint) {
Point size = control.computeSize(wHint, hHint, flushCache);
currentWhint = wHint;
currentHhint = hHint;
currentWidth = size.x;
currentHeight = size.y;
}//if//
cacheWidth = currentWidth;
cacheHeight = currentHeight;
}//if//
}//computeSize()//
/**
* Clears any cached values.
*/
void flushCache() {
cacheWidth = cacheHeight = -1;
defaultWidth = defaultHeight = -1;
currentWidth = currentHeight = -1;
}//flushCache()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
String hAlign = "";
String vAlign = "";
String string;
switch(horizontalAlignment) {
case SWT.FILL:
hAlign = "SWT.FILL";
break;
case SWT.BEGINNING:
hAlign = "SWT.BEGINNING";
break;
case SWT.LEFT:
hAlign = "SWT.LEFT";
break;
case SWT.END:
hAlign = "SWT.END";
break;
case END:
hAlign = "GridData.END";
break;
case SWT.RIGHT:
hAlign = "SWT.RIGHT";
break;
case SWT.CENTER:
hAlign = "SWT.CENTER";
break;
case CENTER:
hAlign = "GridData.CENTER";
break;
default:
hAlign = "Undefined " + horizontalAlignment;
break;
}//switch//
switch(verticalAlignment) {
case SWT.FILL:
vAlign = "SWT.FILL";
break;
case SWT.BEGINNING:
vAlign = "SWT.BEGINNING";
break;
case SWT.TOP:
vAlign = "SWT.TOP";
break;
case SWT.END:
vAlign = "SWT.END";
break;
case END:
vAlign = "GridData.END";
break;
case SWT.BOTTOM:
vAlign = "SWT.BOTTOM";
break;
case SWT.CENTER:
vAlign = "SWT.CENTER";
break;
case CENTER:
vAlign = "GridData.CENTER";
break;
default:
vAlign = "Undefined " + verticalAlignment;
break;
}//switch//
string = "GridData {horizontalAlignment: " + hAlign + " ";
if(horizontalIndent != 0)
string += "horizontalIndent=" + horizontalIndent + " ";
if(horizontalSpan != 1)
string += "horizontalSpan=" + horizontalSpan + " ";
if(grabExcessHorizontalSpace)
string += "grabExcessHorizontalSpace=" + grabExcessHorizontalSpace + " ";
if(widthHint != SWT.DEFAULT)
string += "widthHint=" + widthHint + " ";
if(minimumWidth != 0)
string += "minimumWidth=" + minimumWidth + " ";
string += "verticalAlignment=" + vAlign + " ";
if(verticalIndent != 0)
string += "verticalIndent=" + verticalIndent + " ";
if(verticalSpan != 1)
string += "verticalSpan=" + verticalSpan + " ";
if(grabExcessVerticalSpace)
string += "grabExcessVerticalSpace=" + grabExcessVerticalSpace + " ";
if(heightHint != SWT.DEFAULT)
string += "heightHint=" + heightHint + " ";
if(minimumHeight != 0)
string += "minimumHeight=" + minimumHeight + " ";
if(exclude)
string += "exclude=" + exclude + " ";
string = string.trim();
string += "}";
return string;
}//toString()//
}//GridData//

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 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.layout;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
/**
* The layout base class.
*/
public abstract class Layout extends org.eclipse.swt.widgets.Layout {
/**
* Layout constructor.
*/
public Layout() {
}//Layout()//
/**
* Computes the current size of the composite using this layout.
* @param composite The composite that uses this layout.
* @return The current size of the composite.
*/
public Point computeCurrentSize(Composite composite) {
Point result = new Point(0, 0);
Control[] children = composite.getChildren();
//Note: This works well, but doesn't account for bottom and right margins. Subclasses can overload this to add the margins.//
for(int i = 0; i < children.length; i++) {
Rectangle rect = children[i].getBounds();
if(children[i].isVisible()) {
result.x = Math.max(result.x, rect.x + rect.width);
result.y = Math.max(result.y, rect.y + rect.height);
}//if//
}//for//
return result;
}//computeCurrentSize()//
}//Layout//

View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) 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.layout;
/**
* The base class for all layout data types.
*/
public abstract class LayoutData {
/**
* LayoutData constructor.
*/
public LayoutData() {
}//LayoutData()//
/**
* Flushes any cached data.
* This should be called when ever the component with the layout data changes state in such a way as to invalidate a previous layout of the component.
*/
public abstract void flushCache();
}//LayoutData//

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Declarative Engineering - Major additions (overlays & minimum sizing) + maintenance, formatting, & commenting.
*/
package com.foundation.view.swt.layout;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
/**
* Each control controlled by a <code>RowLayout</code> can have its initial width and height specified by setting a <code>RowData</code> object into the control.
* <p>
* The following code uses a <code>RowData</code> object to change the initial size of a <code>Button</code> in a <code>Shell</code>:
* <pre>
* Display display = new Display();
* Shell shell = new Shell(display);
* shell.setLayout(new RowLayout());
* Button button1 = new Button(shell, SWT.PUSH);
* button1.setText("Button 1");
* button1.setLayoutData(new RowData(50, 40));
* </pre>
* </p>
* @see RowLayout
*/
public final class RowData {
/** Specifies the desired width in pixels. This value is the wHint passed into Control.computeSize(int, int, boolean) to determine the preferred size of the control. */
public int width = SWT.DEFAULT;
/** Specifies the preferred height in pixels. This value is the hHint passed into Control.computeSize(int, int, boolean) to determine the preferred size of the control. */
public int height = SWT.DEFAULT;
/** Informs the layout to ignore this control when sizing and positioning controls. If this value is <code>true</code>, the size and position of the control will not be managed by the layout. If this value is <code>false</code>, the size and position of the control will be computed and assigned. */
public boolean exclude = false;
//TODO: Utilize the minimums... add them to the cml's
/** The minimum width. If the row data describes a composite and this value is >= zero, this will override the composite's calculated minimum. */
public int minimumWidth = -1;
/** The minimum height. If the row data describes a composite and this value is >= zero, this will override the composite's calculated minimum. */
public int minimumHeight = -1;
/** The alignment of the widget opposite the row layout's type (direction). A value of NONE will follow the layout's alignment. */
public int alignment = SWT.NONE;
/**
* Constructs a new instance of RowData using
* default values.
*/
public RowData() {
}//RowData()//
/**
* Constructs a new instance of RowData according to the parameters.
* A value of SWT.DEFAULT indicates that no minimum width or
* no minimum height is specified.
*
* @param width a minimum width for the control
* @param height a minimum height for the control
*/
public RowData(int width, int height) {
this.width = width;
this.height = height;
}//RowData()//
/**
* Constructs a new instance of RowData according to the parameter.
* A value of SWT.DEFAULT indicates that no minimum width or
* no minimum height is specified.
*
* @param point a point whose x coordinate specifies a minimum width for the control
* and y coordinate specifies a minimum height for the control
*/
public RowData(Point point) {
this(point.x, point.y);
}//RowData()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
String string = "RowData {";
if(width != SWT.DEFAULT)
string += "width=" + width + " ";
if(height != SWT.DEFAULT)
string += "height=" + height + " ";
if(exclude)
string += "exclude=" + exclude + " ";
string = string.trim();
string += "}";
return string;
}//toString()//
}//RowData//

View File

@@ -0,0 +1,822 @@
/*
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Declarative Engineering - Major additions (overlays & minimum sizing) + maintenance, formatting, & commenting.
*/
package com.foundation.view.swt.layout;
import java.util.Arrays;
import java.util.Comparator;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
import com.common.debug.Debug;
import com.foundation.view.swt.IOverlay;
/**
* Instances of this class determine the size and position of the
* children of a <code>Composite</code> by placing them either in
* horizontal rows or vertical columns within the parent <code>Composite</code>.
* <p>
* <code>RowLayout</code> aligns all controls in one row if the
* <code>type</code> is set to horizontal, and one column if it is
* set to vertical. It has the ability to wrap, and provides configurable
* margins and spacing. <code>RowLayout</code> has a number of configuration
* fields. In addition, the height and width of each control in a
* <code>RowLayout</code> can be specified by setting a <code>RowData</code>
* object into the control using <code>setLayoutData ()</code>.
* </p>
* <p>
* The following example code creates a <code>RowLayout</code>, sets all
* of its fields to non-default values, and then sets it into a
* <code>Shell</code>.
* <pre>
* RowLayout rowLayout = new RowLayout();
* rowLayout.wrap = false;
* rowLayout.pack = false;
* rowLayout.justify = true;
* rowLayout.type = SWT.VERTICAL;
* rowLayout.marginLeft = 5;
* rowLayout.marginTop = 5;
* rowLayout.marginRight = 5;
* rowLayout.marginBottom = 5;
* rowLayout.spacing = 0;
* shell.setLayout(rowLayout);
* </pre>
* If you are using the default field values, you only need one line of code:
* <pre>
* shell.setLayout(new RowLayout());
* </pre>
* </p>
*
* @see RowData
*/
public final class RowLayout extends Layout {
/** Specifies whether the layout places controls in rows or columns. Possible values are: <ul><li>HORIZONTAL: Position the controls horizontally from left to right</li><li>VERTICAL: Position the controls vertically from top to bottom</li></ul> */
public int type = SWT.HORIZONTAL;
/** Specifies the number of pixels of horizontal margin that will be placed along the left and right edges of the layout. */
public int marginWidth = 0;
/** Specifies the number of pixels of vertical margin that will be placed along the top and bottom edges of the layout. */
public int marginHeight = 0;
/** Specifies the number of pixels between the edge of one cell and the edge of its neighbouring cell. */
public int spacing = 3;
/** Specifies whether a control will be wrapped to the next row if there is insufficient space on the current row. */
public boolean wrap = true;
/** Specifies whether all controls in the layout take their preferred size. If pack is false, all controls will have the same size which is the size required to accommodate the largest preferred height and the largest preferred width of all the controls in the layout. */
public boolean pack = true;
/** Specifies a default alignment for all controls in the axis opposite the type (direction). */
public int alignment = SWT.BEGINNING;
/** Specifies whether the controls in a row should be fully justified, with any extra space placed between the controls. */
public boolean justify = false;
/** Specifies the number of pixels of horizontal margin that will be placed along the left edge of the layout. */
public int marginLeft = 3;
/** Specifies the number of pixels of vertical margin that will be placed along the top edge of the layout. */
public int marginTop = 3;
/** Specifies the number of pixels of horizontal margin that will be placed along the right edge of the layout. */
public int marginRight = 3;
/** Specifies the number of pixels of vertical margin that will be placed along the bottom edge of the layout. */
public int marginBottom = 3;
/**
* Constructs a new instance of this class.
*/
public RowLayout() {
}//RowLayout()//
/**
* Constructs a new instance of this class given the type.
* @param type the type of row layout
*/
public RowLayout(int type) {
this.type = type;
}//RowLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#computeCurrentSize(org.eclipse.swt.widgets.Composite)
*/
public Point computeCurrentSize(Composite composite) {
Point result = super.computeCurrentSize(composite);
result.x += marginRight + marginWidth;
result.y += marginBottom + marginHeight;
return result;
}//computeCurrentSize()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int, boolean)
*/
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
Point extent;
if(type == SWT.HORIZONTAL) {
extent = layoutHorizontal(composite, false, (wHint != SWT.DEFAULT) && wrap, wHint, flushCache);
}//if//
else {
extent = layoutVertical(composite, false, (hHint != SWT.DEFAULT) && wrap, hHint, flushCache);
}//else//
if(wHint != SWT.DEFAULT)
extent.x = wHint;
if(hHint != SWT.DEFAULT)
extent.y = hHint;
return extent;
}//computeSize()//
/**
* @param control
* @param flushCache
* @return
*/
Point computeSize(Control control, boolean flushCache) {
int wHint = SWT.DEFAULT, hHint = SWT.DEFAULT;
RowData data = (RowData) control.getLayoutData();
if(data != null) {
wHint = data.width;
hHint = data.height;
}//if//
return control.computeSize(wHint, hHint, flushCache);
}//computeSize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#flushCache(org.eclipse.swt.widgets.Control)
*/
public boolean flushCache(Control control) {
return true;
}//flushCache()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
*/
protected void layout(Composite composite, boolean flushCache) {
Rectangle clientArea = composite.getClientArea();
if(type == SWT.HORIZONTAL) {
layoutHorizontal(composite, true, wrap, clientArea.width, flushCache);
}//if//
else {
layoutVertical(composite, true, wrap, clientArea.height, flushCache);
}//else//
}//layout()//
/**
* @param composite
* @param move
* @param wrap
* @param width
* @param flushCache
* @return
*/
Point layoutHorizontal(Composite composite, boolean move, boolean wrap, int width, boolean flushCache) {
Control[] children = composite.getChildren();
int count = 0; //The child count.//
Control[] excluded = null;
int nextExcludedIndex = 0;
IOverlay[] overlayChildren = new IOverlay[children.length];
int overlayCount = 0;
int childWidth = 0;
int childHeight = 0;
int maxHeight = 0;
int clientX = 0;
int clientY = 0;
int[] wraps = null;
boolean wrapped = false;
Rectangle[] rectangle = null;
int maxX = 0;
int x = marginLeft + marginWidth;
int y = marginTop + marginHeight;
int availableHeight = composite.getClientArea().height;
//Declarative Engineering//
//Moved above the following for loop in order to include invisible children (which may become visible later - we don't want the layout to change all the sizes of the components if they do become visible).//
//Modified to exclude the specifically excluded controls.//
for(int index = 0; index < children.length; index++) {
Control child = children[index];
RowData data = (RowData) child.getLayoutData();
//Ignore excluded and overlay controls.//
if(data == null || (!data.exclude && !(child instanceof IOverlay))) {
Point size = computeSize(child, flushCache);
childWidth = Math.max(childWidth, size.x);
childHeight = Math.max(childHeight, size.y);
}//if//
}//for//
maxHeight = childHeight;
//Iterate over the controls and remove any that are not visible or excluded, and move any that are overlay controls into another collection.//
for(int index = 0; index < children.length; index++) {
Control child = children[index];
RowData data = (RowData) child.getLayoutData();
if(child instanceof IOverlay) {
overlayChildren[overlayCount++] = (IOverlay) children[index];
}//if//
else if(data != null && data.exclude) {
if(excluded == null) {
int excludeCount = 1;
for(int i = index + 1; i < children.length; i++) {
RowData childData = (RowData) children[i].getLayoutData();
if(childData != null && childData.exclude) {
excludeCount++;
}//if//
}//for//
excluded = new Control[excludeCount];
}//if//
excluded[nextExcludedIndex++] = children[index];
}//else if//
else if(child.getVisible()) {
children[count++] = children[index];
}//else if//
}//for//
if(move) {
Rectangle rect = composite.getClientArea();
clientX = rect.x;
clientY = rect.y;
}//if//
if(move && justify) {
rectangle = new Rectangle[count];
wraps = new int[count];
}//if//
availableHeight = Math.max(maxHeight, availableHeight);
for(int i = 0; i < count; i++) {
Control child = children[i];
RowData data = (RowData) child.getLayoutData();
if(pack) {
Point size = computeSize(child, flushCache);
childWidth = size.x;
childHeight = size.y;
}//if//
if(wrap && (i != 0) && (x + childWidth > width)) {
wrapped = true;
if(move && justify) {
wraps[i - 1] = maxHeight;
}//if//
x = marginLeft + marginWidth;
y += spacing + maxHeight;
if(pack) {
maxHeight = 0;
}//if//
}//if//
if(move) {
int childX = x + clientX;
int childY = y + clientY;
switch(data == null || data.alignment == SWT.NONE ? alignment : data.alignment) {
case SWT.FILL: {
childHeight = availableHeight - (marginBottom + marginTop + marginHeight);
break;
}//case//
case SWT.END: {
childY += availableHeight - (childHeight + marginBottom + marginTop + marginHeight);
break;
}//case//
case SWT.CENTER: {
childY += ((availableHeight - (childHeight + marginBottom + marginTop + marginHeight)) >> 1);
break;
}//case//
}//switch//
if(justify) {
rectangle[i] = new Rectangle(childX, childY, childWidth, childHeight);
}//if//
else {
child.setBounds(childX, childY, childWidth, childHeight);
}//else//
}//if//
x += spacing + childWidth;
maxX = Math.max(maxX, x);
}//for//
maxX = Math.max(clientX + marginLeft + marginWidth, maxX - spacing);
if(!wrapped) {
maxX += marginRight + marginWidth;
}//if//
if(move && justify) {
int space = 0, margin = 0;
if(!wrapped) {
space = Math.max(0, (width - maxX) / (count + 1));
margin = Math.max(0, ((width - maxX) % (count + 1)) / 2);
}//if//
else {
int last = 0;
if(count > 0) {
wraps[count - 1] = maxHeight;
}//if//
for(int i = 0; i < count; i++) {
if(wraps[i] != 0) {
int wrapCount = i - last + 1;
int wrapX = 0;
for(int j = last; j <= i; j++) {
wrapX += rectangle[j].width + spacing;
}//for//
space = Math.max(0, (width - wrapX) / (wrapCount + 1));
margin = Math.max(0, ((width - wrapX) % (wrapCount + 1)) / 2);
for(int j = last; j <= i; j++) {
rectangle[j].x += (space * (j - last + 1)) + margin;
}//for//
last = i + 1;
}//if//
}//for//
}//else//
for(int i = 0; i < count; i++) {
if(!wrapped) {
rectangle[i].x += (space * (i + 1)) + margin;
}//if//
children[i].setBounds(rectangle[i]);
}//for//
}//if//
//Layout the overlays.//
for(int index = 0; index < overlayCount; index++) {
IOverlay overlay = overlayChildren[index];
Control peer = overlay.getPeerControl();
Rectangle bounds = peer.getBounds();
Point size = overlay.getSize();
switch(overlay.getPosition()) {
case IOverlay.POSITION_UPPER_LEFT: {
bounds.x += overlay.getHorizontalOffset();
bounds.y += overlay.getVerticalOffset();
bounds.width = size.x;
bounds.height = size.y;
break;
}//case//
case IOverlay.POSITION_UPPER_RIGHT: {
bounds.x += bounds.width + (overlay.getHorizontalOffset() * -1) - size.x;
bounds.y += overlay.getVerticalOffset();
bounds.width = size.x;
bounds.height = size.y;
break;
}//case//
case IOverlay.POSITION_LOWER_RIGHT: {
bounds.x += bounds.width + (overlay.getHorizontalOffset() * -1) - size.x;
bounds.y += bounds.height + (overlay.getVerticalOffset() * -1) - size.y;
bounds.width = size.x;
bounds.height = size.y;
break;
}//case//
case IOverlay.POSITION_LOWER_LEFT: {
bounds.x += overlay.getHorizontalOffset();
bounds.y += bounds.height + (overlay.getVerticalOffset() * -1) - size.y;
bounds.width = size.x;
bounds.height = size.y;
break;
}//case//
}//switch//
((Control) overlay).setBounds(bounds);
}//for//
Point result = new Point(maxX, y + maxHeight + marginBottom + marginHeight);
//Declarative Engineering: Layout any excluded controls that are visible - they will be expanded to fill the entire space.//
if(excluded != null) {
//Ensure there is enough space for any visible overlays.//
for(int index = 0; index < excluded.length; index++) {
if(excluded[index].getVisible()) {
RowData next = (RowData) excluded[index].getLayoutData();
int minWidth = next.minimumWidth;
int minHeight = next.minimumHeight;
boolean calcMinWidth = minWidth <= 0;
boolean calcMinHeight = minHeight <= 0;
//Calculate the minimum width and/or height if necessary.//
if(calcMinWidth || calcMinHeight) {
Point size = null;
if(excluded[index] instanceof Composite) {
excluded[index].computeSize(0, 0, true);
if(((Composite) excluded[index]).getLayout() instanceof Layout) {
size = ((Layout) ((Composite) excluded[index]).getLayout()).computeCurrentSize((Composite) excluded[index]);
}//if//
else { //Note This should never be run (all Brainstorm layouts should extend the Layout base class in Brainstorm). Also this fails to account for margins.//
Debug.log(new RuntimeException("Only Brainstorm based layouts may be used. The layout must extend " + Layout.class.getName()));
}//else//
}//if//
else {
size = excluded[index].computeSize(0, 0, true);
}//else//
if(calcMinWidth) {
minWidth = Math.max(0, size.x);
}//if//
if(calcMinHeight) {
minHeight = Math.max(0, size.y);
}//if//
}//if//
result.x = Math.max(result.x, minWidth);
result.y = Math.max(result.y, minHeight);
}//if//
}//for//
//Force all excluded widgets that are visible to fill the entire space (overlays).//
for(int index = 0; index < excluded.length; index++) {
if(excluded[index].getVisible()) {
int cx = x + marginWidth + marginLeft;
int cy = y + marginHeight + marginTop;
int cw = result.x - ((marginWidth << 1) + marginRight + marginLeft);
int ch = result.y - ((marginHeight << 1) + marginTop + marginBottom);
//Set the widget to fill the entire space.//
excluded[index].setBounds(cx, cy, cw, ch);
}//if//
}//for//
}//if//
return result;
}//layoutHorizontal()//
/**
* @param composite
* @param move
* @param wrap
* @param height
* @param flushCache
* @return
*/
Point layoutVertical(Composite composite, boolean move, boolean wrap, int height, boolean flushCache) {
Control[] children = composite.getChildren();
int count = 0; //The child count.//
Control[] excluded = null;
int nextExcludedIndex = 0;
IOverlay[] overlayChildren = new IOverlay[children.length];
int overlayCount = 0;
int childWidth = 0;
int childHeight = 0;
int maxWidth = 0;
int clientX = 0;
int clientY = 0;
int[] wraps = null;
boolean wrapped = false;
Rectangle[] rectangle = null;
int maxY = 0;
int x = marginLeft + marginWidth;
int y = marginTop + marginHeight;
int availableWidth = composite.getClientArea().width;
//Declarative Engineering//
//Moved above the following for loop in order to include invisible children (which may become visible later - we don't want the layout to change all the sizes of the components if they do become visible).//
//Modified to exclude the specifically excluded controls.//
for(int index = 0; index < children.length; index++) {
Control child = children[index];
RowData data = (RowData) child.getLayoutData();
//Ignore excluded and overlay controls.//
if(data == null || (!data.exclude && !(child instanceof IOverlay))) {
Point size = computeSize(child, flushCache);
childWidth = Math.max(childWidth, size.x);
childHeight = Math.max(childHeight, size.y);
}//if//
}//for//
maxWidth = childWidth;
//Modified to exclude invisible children and move overlays to another collection.//
for(int index = 0; index < children.length; index++) {
Control child = children[index];
RowData data = (RowData) child.getLayoutData();
if(child instanceof IOverlay) {
overlayChildren[overlayCount++] = (IOverlay) children[index];
}//if//
else if(data != null && data.exclude) {
if(excluded == null) {
int excludeCount = 1;
for(int i = index + 1; i < children.length; i++) {
RowData childData = (RowData) children[i].getLayoutData();
if(childData != null && childData.exclude) {
excludeCount++;
}//if//
}//for//
excluded = new Control[excludeCount];
}//if//
excluded[nextExcludedIndex++] = children[index];
}//else if//
else if(child.getVisible()) {
children[count++] = children[index];
}//else if//
}//for//
if(count == 0) {
return new Point(marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom);
}//if//
if(move) {
Rectangle rect = composite.getClientArea();
clientX = rect.x;
clientY = rect.y;
}//if//
if(move && justify) {
rectangle = new Rectangle[count];
wraps = new int[count];
}//if//
availableWidth = Math.max(maxWidth, availableWidth);
for(int i = 0; i < count; i++) {
Control child = children[i];
RowData data = (RowData) child.getLayoutData();
if(pack) {
Point size = computeSize(child, flushCache);
childWidth = size.x;
childHeight = size.y;
}//if//
if(wrap && (i != 0) && (y + childHeight > height)) {
wrapped = true;
if(move && justify) {
wraps[i - 1] = maxWidth;
}//if//
x += spacing + maxWidth;
y = marginTop + marginHeight;
if(pack) {
maxWidth = 0;
}//if//
}//if//
if(move) {
int childX = x + clientX;
int childY = y + clientY;
switch(data == null || data.alignment == SWT.NONE ? alignment : data.alignment) {
case SWT.FILL: {
childWidth = availableWidth - ((marginWidth << 1) + marginLeft + marginRight);
break;
}//case//
case SWT.END: {
childX += availableWidth - (childWidth + (marginWidth << 1) + marginLeft + marginRight);
break;
}//case//
case SWT.CENTER: {
childX += ((availableWidth - (childWidth + (marginWidth << 1) + marginLeft + marginRight)) >> 1);
break;
}//case//
}//switch//
if(justify) {
rectangle[i] = new Rectangle(childX, childY, childWidth, childHeight);
}//if//
else {
child.setBounds(childX, childY, childWidth, childHeight);
}//else//
}//if//
y += spacing + childHeight;
maxY = Math.max(maxY, y);
}//for//
maxY = Math.max(clientY + marginTop + marginHeight, maxY - spacing);
if(!wrapped) {
maxY += marginBottom + marginHeight;
}//if//
if(move && justify) {
int space = 0, margin = 0;
if(!wrapped) {
space = Math.max(0, (height - maxY) / (count + 1));
margin = Math.max(0, ((height - maxY) % (count + 1)) / 2);
}//if//
else {
int last = 0;
if(count > 0) {
wraps[count - 1] = maxWidth;
}//if//
for(int i = 0; i < count; i++) {
if(wraps[i] != 0) {
int wrapCount = i - last + 1;
int wrapY = 0;
for(int j = last; j <= i; j++) {
wrapY += rectangle[j].height + spacing;
}//for//
space = Math.max(0, (height - wrapY) / (wrapCount + 1));
margin = Math.max(0, ((height - wrapY) % (wrapCount + 1)) / 2);
for(int j = last; j <= i; j++) {
rectangle[j].y += (space * (j - last + 1)) + margin;
}//for//
last = i + 1;
}//if//
}//for//
}//else//
for(int i = 0; i < count; i++) {
if(!wrapped) {
rectangle[i].y += (space * (i + 1)) + margin;
}//if//
children[i].setBounds(rectangle[i]);
}//for//
}//if//
if(overlayCount > 0) { //Layout the overlays.//
int upperLeftOffset = 0;
int upperRightOffset = 0;
int lowerLeftOffset = 0;
int lowerRightOffset = 0;
Control lastPeer = null;
Arrays.sort(overlayChildren, 0, overlayCount, new Comparator() {
public int compare(Object arg0, Object arg1) {
return ((IOverlay) arg0).getPeerControl().hashCode() - ((IOverlay) arg1).getPeerControl().hashCode();
}//compare()//
});
for(int index = 0; index < overlayCount; index++) {
IOverlay overlay = overlayChildren[index];
Control peer = overlay.getPeerControl();
Rectangle bounds = peer.getBounds();
Point size = overlay.getSize();
if(peer != lastPeer) {
upperLeftOffset = 0;
upperRightOffset = 0;
lowerLeftOffset = 0;
lowerRightOffset = 0;
lastPeer = peer;
}//if//
switch(overlay.getPosition()) {
case IOverlay.POSITION_UPPER_LEFT: {
bounds.x += overlay.getHorizontalOffset() + upperLeftOffset;
bounds.y += overlay.getVerticalOffset();
bounds.width = size.x;
bounds.height = size.y;
upperLeftOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_UPPER_RIGHT: {
bounds.x += bounds.width + (overlay.getHorizontalOffset() * -1) - size.x - upperRightOffset;
bounds.y += overlay.getVerticalOffset();
bounds.width = size.x;
bounds.height = size.y;
upperRightOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_LOWER_RIGHT: {
bounds.x += bounds.width + (overlay.getHorizontalOffset() * -1) - size.x - lowerRightOffset;
bounds.y += bounds.height + (overlay.getVerticalOffset() * -1) - size.y;
bounds.width = size.x;
bounds.height = size.y;
lowerRightOffset += bounds.width + 1;
break;
}//case//
case IOverlay.POSITION_LOWER_LEFT: {
bounds.x += overlay.getHorizontalOffset() + lowerLeftOffset;
bounds.y += bounds.height + (overlay.getVerticalOffset() * -1) - size.y;
bounds.width = size.x;
bounds.height = size.y;
lowerLeftOffset += bounds.width + 1;
break;
}//case//
}//switch//
((Control) overlay).setBounds(bounds);
}//for//
}//if//
Point result = new Point(x + maxWidth + marginRight + marginWidth, maxY);
//Declarative Engineering: Layout any excluded controls that are visible - they will be expanded to fill the entire space.//
if(excluded != null) {
//Ensure there is enough space for any visible overlays.//
for(int index = 0; index < excluded.length; index++) {
if(excluded[index].getVisible()) {
RowData next = (RowData) excluded[index].getLayoutData();
int minWidth = next.minimumWidth;
int minHeight = next.minimumHeight;
boolean calcMinWidth = minWidth <= 0;
boolean calcMinHeight = minHeight <= 0;
//Calculate the minimum width and/or height if necessary.//
if(calcMinWidth || calcMinHeight) {
Point size = null;
if(excluded[index] instanceof Composite) {
excluded[index].computeSize(0, 0, true);
if(((Composite) excluded[index]).getLayout() instanceof Layout) {
size = ((Layout) ((Composite) excluded[index]).getLayout()).computeCurrentSize((Composite) excluded[index]);
}//if//
else { //Note This should never be run (all Brainstorm layouts should extend the Layout base class in Brainstorm). Also this fails to account for margins.//
Debug.log(new RuntimeException("Only Brainstorm based layouts may be used. The layout must extend " + Layout.class.getName()));
}//else//
}//if//
else {
size = excluded[index].computeSize(0, 0, true);
}//else//
if(calcMinWidth) {
minWidth = Math.max(0, size.x);
}//if//
if(calcMinHeight) {
minHeight = Math.max(0, size.y);
}//if//
}//if//
result.x = Math.max(result.x, minWidth);
result.y = Math.max(result.y, minHeight);
}//if//
}//for//
//Force all excluded widgets that are visible to fill the entire space (overlays).//
for(int index = 0; index < excluded.length; index++) {
if(excluded[index].getVisible()) {
int cx = x + marginWidth + marginLeft;
int cy = y + marginHeight + marginTop;
int cw = result.x - ((marginWidth << 1) + marginRight + marginLeft);
int ch = result.y - ((marginHeight << 1) + marginTop + marginBottom);
//Set the widget to fill the entire space.//
excluded[index].setBounds(cx, cy, cw, ch);
}//if//
}//for//
}//if//
return result;
}//layoutVertical()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
String string = "RowLayout {";
string += "type=" + ((type != SWT.HORIZONTAL) ? "SWT.VERTICAL" : "SWT.HORIZONTAL") + " ";
if(marginWidth != 0)
string += "marginWidth=" + marginWidth + " ";
if(marginHeight != 0)
string += "marginHeight=" + marginHeight + " ";
if(marginLeft != 0)
string += "marginLeft=" + marginLeft + " ";
if(marginTop != 0)
string += "marginTop=" + marginTop + " ";
if(marginRight != 0)
string += "marginRight=" + marginRight + " ";
if(marginBottom != 0)
string += "marginBottom=" + marginBottom + " ";
if(spacing != 0)
string += "spacing=" + spacing + " ";
string += "wrap=" + wrap + " ";
string += "pack=" + pack + " ";
string += "alignment=" + alignment + " ";
string += "justify=" + justify + " ";
string = string.trim();
string += "}";
return string;
}//toString()//
}//RowLayout//

View File

@@ -0,0 +1,76 @@
/*
* 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.view.swt.layout;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
/*
* This layout is designed only for use in the wizard control. The layout will size the container to the largest control, and will resize visible controls to the container size.
*/
public class WizardLayout extends Layout {
/**
* WizardLayout constructor.
*/
public WizardLayout() {
}//WizardLayout()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#computeMinSize(org.eclipse.swt.graphics.Point, org.eclipse.swt.widgets.Composite, boolean)
*/
public void computeMinSize(Point result, Composite composite, boolean flushCache) {
//TODO:
}//computeMinSize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.layout.Layout#flushCache(org.eclipse.swt.widgets.Control)
*/
public boolean flushCache(Control child) {
//TODO:
return false;
}//flushCache()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int, boolean)
*/
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
Control[] children = composite.getChildren();
int count = children.length;
int maxWidth = 0, maxHeight = 0;
//Determine the maximum size of the container.//
//TODO: Should we only use the size of the currently visible control?//
for(int index = 0; index < count; index++) {
Control child = children[index];
Point point = child.computeSize(SWT.DEFAULT, SWT.DEFAULT, flushCache);
maxWidth = Math.max(maxWidth, point.x);
maxHeight = Math.max(maxHeight, point.y);
}//for//
return new Point(maxWidth, maxHeight);
}//computeSize()//
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
*/
protected void layout(Composite composite, boolean flushCache) {
Control[] children = composite.getChildren();
Rectangle clientArea = composite.getClientArea();
Control child = null;
for(int index = 0; ((child == null) && (index < children.length)); index++) {
//if(children[index].isVisible()) {
// child = children[index];
//}//if//
children[index].setBounds(clientArea);
}//for//
if(child != null) {
// child.setBounds(clientArea);
//child.moveAbove()
}//if//
}//layout()//
}//WizardLayout//

Some files were not shown because too many files have changed in this diff Show More