Initial commit from SVN.
This commit is contained in:
529
Foundation SWT/src/com/foundation/view/swt/Button.java
Normal file
529
Foundation SWT/src/com/foundation/view/swt/Button.java
Normal 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//
|
||||
Reference in New Issue
Block a user