/* * 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//