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