home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programming Languages Suite
/
ProgLangD.iso
/
VCAFE.3.0A
/
Main.bin
/
ComboBox.java
< prev
next >
Wrap
Text File
|
1998-09-23
|
54KB
|
1,747 lines
package symantec.itools.awt;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.LayoutManager;
import java.awt.AWTEvent;
import java.awt.AWTEventMulticaster;
import java.awt.event.MouseEvent;
import java.awt.event.FocusEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyVetoException;
import java.beans.PropertyChangeListener;
import java.beans.VetoableChangeListener;
import symantec.itools.beans.VetoableChangeSupport;
import symantec.itools.beans.PropertyChangeSupport;
// 01/29/97 TWB Integrated changes from Macintosh
// 04/15/97 LAB Added 1 line in deselect() to clear
// the textbox if deselect is called.
// 05/20/97 CAR Changed handleEvent for the following cases:
// removed case for Event.KEY_ACTION_RELEASE
// case Event.KEY_PRESS checks for ENTER key
// case Event.ACTION_EVENT has the list request focus if it is dropped
// case Event.LIST_SELECT does not "undrop" the list while selection is
// being made with keys
// 05/21/97 CAR Changed handleEvent to hide list if it loses focus.
// Changed Event.LOST_FOCUS to not hide list if the arrow
// loses focus while the pointer is not over the list.
// 05/30/97 RKM Made it compile with some of the 1.1 component changes (added catches)
// 06/06/97 LAB Updated to support Java 1.1
// 06/11/97 LAB Fixed setText(String) and getText() to be for the EditBox and setListText(int, String)
// and getListText(int) to be for the List.
// 07/11/97 LAB Updated calls to the deprecated methods enable() and disable() in DirectionButton
// to the new call setEnabled(boolean).
// 07/13/97 RKM Changed implementations of getPreferredSize & getMinimumSize
// Extracted reshapes from paint override into reshapeInternals
// Added call to reshapeInternals inside of reshape override
// Changed the way getters & setters for font properties worked
// Removed Font variables, used getFont instead (fixed getFont returned null if not set bug)
// 07/14/97 RKM Height of editText is always preferred height
// Removed EVT_IMAGE_SELECT (it's not used)
// Hid the list before adding it (why take the change of flicker?)
// Added setLayout override so users could not change layout on us
// Eliminated misc font properties, used Component's font
// Eliminated DropDownFont property
// Eliminated EditFieldFont property
// Eliminated ComboBoxFont property
// Changed bOsFlag to be not a Mac, I think the original developer wanted to check for Solaris
// 07/15/97 RKM Directionbutton is screwed on expand until I can get a descent preferredSize from it
// 07/19/97 LAB Added add/removeNotify for event listener registration.
// 07/19/97 RKM Changed addLastBottomUp, added case for Macintosh
// Moved addLastBottomUp into isFirstDrawnOverSecond in ZOrderUtils
// 07/30/97 CAR marked fields transient as needed
// inner adaptor classes implement java.io.Serializable
// unable to completely test serializablity in BeanBox as drop down will not work
// 10/01/97 LAB Changed setListItems to call list.clear() instead of clear() to prevent
// the text in the text area from being deleted (Addresses Mac Bug #7995).
// Changed names of strings in PropertyChangeEvent handling to follow Bean Spec
// naming conventions. Made searchable work (Addresses Mac Bug #8000).
// Removed Macintosh specific code to deal with textbox offset problem in MRJ.
// Fixed default state problem causing vertical scroll bar never to appear
// (Addresses Mac Bug #7538).Added code to more gracefully handle the case
// when the combobox list doesn't have enough room to extend fully.
// 10/03/97 LAB Made getPreferredSize calculate the size it should be to see the largest item
// in the list.
/**
* A ComboBox is a text field with an attached drop-down list box. It may be
* user-editable, "searchable", have horizontal and/or vertical scroll
* bars, and can use different fonts for the text box and the drop-down list.
* Also each list box item can have an image in addition to text.
* A user-editable ComboBox allows the user to enter any desired text into
* the text field. A searchable ComboBox allows the user to enter text into
* the text field as long as it matches one of the existing list items.
* This allows the user to select from a non-editable list by typing instead
* of dropping-down the list and selecting with the mouse.
* <p>
* Use a ComboBox to:
* <UL>
* <LI>Compactly provide a list of items for the user to select from.
* <LI>Have a text field that maintains a history of what's been entered in it.
* <LI>Allow the user to either select from a list or enter a new value.
* </UL>
* @version 1.1, June 6, 1997
* @author Symantec
*/
public class ComboBox extends Panel
{
/**
* Constructs a new default ComboBox. The ComboBox is not editable and
* not searchable by default.
*/
public ComboBox()
{
this(false, false);
}
/**
* Constructs a new editable and/or searchable ComboBox.
* @param editable true = editable, false = non-editable
* @param searchable true = searchable, false = non-searchable
*/
public ComboBox(boolean editable, boolean searchable)
{
vPad = 0;
hPad = 1;
super.setLayout(null);
editBox = new TextField("");
editBox.setEditable(false);
editBox.setBackground(Color.white);
arrow = new DirectionButton(DirectionButton.DOWN);
try
{
arrow.setShowFocus(false);
}
catch(java.beans.PropertyVetoException veto) {}
arrow.setEnabled(false);
list = new ImageListBox("ILB");
list.hide();
try
{
list.setComboMode(true);
list.setShowHorizontalScroll(false);
list.setShowVerticalScroll(true);
}
catch(PropertyVetoException e) {}
add(list);
add(editBox);
add(arrow);
lheight = 0;
try
{
setEditable(editable);
setSearchable(searchable);
}
catch(java.beans.PropertyVetoException veto) {}
bCaseSensitive = true;
}
/**
* Conditionally sets the ComboBox to be user-editable.
* @param editable true = editable, false = non-editable
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #isEditable
*/
public void setEditable(boolean editable) throws PropertyVetoException
{
if(bEditable != editable)
{
Boolean oldValue = new Boolean(bEditable);
Boolean newValue = new Boolean(editable);
vetos.fireVetoableChange("editable", oldValue, newValue);
bEditable = editable;
editBox.setEditable(bEditable || bSearchable);
changes.firePropertyChange("editable", oldValue, newValue);
}
}
/**
* Gets whether the ComboBox is user-editable.
* @return true if it is user-editable, false otherwise
* @see #setEditable
*/
public boolean isEditable()
{
return bEditable;
}
/**
* @deprecated
* @see #isEditable
*/
public boolean getEditable()
{
return isEditable();
}
/**
* Conditionally sets the ComboBox to be searchable.
* A searchable ComboBox allows the user to enter text into
* the text field as long as it matches one of the existing list items.
* This allows the user to select from a non-editable list by typing instead
* of dropping-down the list and selecting with the mouse.
* @param searchable true = searchable, false = non-searchable
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #isSearchable
*/
public void setSearchable(boolean searchable) throws PropertyVetoException
{
if(bSearchable != searchable)
{
Boolean oldValue = new Boolean(bSearchable);
Boolean newValue = new Boolean(searchable);
vetos.fireVetoableChange("searchable", oldValue, newValue);
bSearchable = searchable;
editBox.setEditable(bEditable || bSearchable);
changes.firePropertyChange("searchable", oldValue, newValue);
}
}
/**
* Returns the current ComboBox "searchable" status.
* A searchable ComboBox allows the user to enter text into
* the text field as long as it matches one of the existing list items.
* This allows the user to select from a non-editable list by typing instead
* of dropping-down the list and selecting with the mouse.
* @see #setSearchable
*/
public boolean isSearchable()
{
return bSearchable;
}
/**
* @deprecated
* @see #isSearchable
*/
public boolean getSearchable()
{
return isSearchable();
}
/**
* Conditionally set the ComboBox to be case sensitive during searches.
* @param bCaseSensitive true = case-sensitive, false = case-insensitive
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #getCaseSensitive
*/
public void setCaseSensitive(boolean bCaseSensitive) throws PropertyVetoException
{
if (this.bCaseSensitive != bCaseSensitive)
{
Boolean oldValue = new Boolean(this.bCaseSensitive);
Boolean newValue = new Boolean(bCaseSensitive);
vetos.fireVetoableChange("caseSensitive", oldValue, newValue);
this.bCaseSensitive = bCaseSensitive;
changes.firePropertyChange("caseSensitive", oldValue, newValue);
}
}
/**
* Returns the current ComboBox case-sensitive search status.
* @see #setSearchable
*/
public boolean isCaseSensitive()
{
return bCaseSensitive;
}
/**
* @deprecated
* @see #isSearchable
*/
public boolean getCaseSensitive()
{
return isCaseSensitive();
}
/**
* Sets whether or not the horizontal scrollbar should be made visible when
* necessary or should never be made visible.
* @param cond true = show when necessary, false = never show
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #isShowHorizontalScroll
*/
public void setShowHorizontalScroll(boolean cond) throws PropertyVetoException
{
if(showHScroll != cond)
{
Boolean oldValue = new Boolean(showHScroll);
Boolean newValue = new Boolean(cond);
vetos.fireVetoableChange("showHorizontalScroll", oldValue, newValue);
showHScroll = cond;
list.setShowHorizontalScroll(cond);
changes.firePropertyChange("showHorizontalScroll", oldValue, newValue);
}
}
/**
* Gets the current horizontal scrollbar display option.
* @return true if the horizontal scrollbar should be displayed when necessary,
* false if the scrollbar should never be shown
* @see #setShowHorizontalScroll
*/
public boolean isShowHorizontalScroll()
{
return showHScroll;
}
/**
* @deprecated
* @see #isShowHorizontalScroll
*/
public boolean getShowHorizontalScroll()
{
return isShowHorizontalScroll();
}
/**
* Sets whether or not the vertical scrollbar should be made visible when
* necessary or should never be made visible.
* @param cond true = show when necessary, false = never show
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #isShowVerticalScroll
*/
public void setShowVerticalScroll(boolean cond) throws PropertyVetoException
{
if(showVScroll != cond)
{
Boolean oldValue = new Boolean(showVScroll);
Boolean newValue = new Boolean(cond);
vetos.fireVetoableChange("showVerticalScroll", oldValue, newValue);
showVScroll = cond;
list.setShowVerticalScroll(cond);
changes.firePropertyChange("showVerticalScroll", oldValue, newValue);
}
}
/**
* Gets the current vertical scrollbar display option.
* @return true if the vertical scrollbar should be displayed when necessary,
* false if the scrollbar should never be shown
* @see #setShowVerticalScroll
*/
public boolean isShowVerticalScroll()
{
return showVScroll;
}
/**
* @deprecated
* @see #isShowVerticalScroll
*/
public boolean getShowVerticalScroll()
{
return isShowVerticalScroll();
}
/**
* Adds the string array to the list.
* @param items items to add to the list
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #getListItems
* @see #addItem(java.lang.String)
* @see #addItem(java.lang.String, boolean)
* @see #addItem(java.awt.Image, java.lang.String)
* @see #addItem(java.awt.Image, java.lang.String, boolean)
*/
public void setListItems(String[] items) throws PropertyVetoException
{
String[] oldValue = getListItems();
if(!symantec.itools.util.GeneralUtils.objectsEqual(oldValue, items))
{
vetos.fireVetoableChange("listItems", oldValue, items);
list.clear();
for (int i = 0; i < items.length; ++i)
{
addItem(items[i]);
}
updateMaxNumChars();
changes.firePropertyChange("listItems", oldValue, items);
}
}
/**
* Returns the current list as an array.
* @see #setListItems
*/
public String[] getListItems()
{
int len = countItems();
String[] items = new String[len];
for (int i = 0; i < len; ++i)
items[i] = getItem(i);
return items;
}
/**
* Sets the font of the component.
* @param f the font
* @see java.awt.Component#getFont
*/
public synchronized void setFont(Font newFont)
{
super.setFont(newFont);
editBox.setFont(newFont);
list.setFont(newFont);
repaint();
}
/**
* @deprecated
* @see #getListText(int)
*/
public String getItem(int index)
{
return getListText(index);
}
/**
* Returns the text associated with a drop-down item.
* @return the text associated with the drop-down item at index
* @see #setListText(int, java.lang.String)
*/
public String getListText(int index)
{
return list.getText(index);
}
/**
* Sets the text in the edit field portion of the ComboBox
* is not editable.
* @param text to replace the text of the EditBox
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #getSelectedItem
*/
public void setText(String newText) throws java.beans.PropertyVetoException
{
String oldValue = getText();
if(!symantec.itools.util.GeneralUtils.objectsEqual(oldValue, newText))
{
vetos.fireVetoableChange("text", oldValue, newText);
editBox.setText(newText);
changes.firePropertyChange("text", oldValue, newText);
}
}
/**
* Returns the text in the edit field portion of the ComboBox, unless the ComboBox
* is not editable.
* @return the edit field text if editable, or null if this ComboBox is not editable
* @see #getSelectedItem
*/
public String getText()
{
verify();
return editBox.getText();
}
/**
* Returns the selected item on the drop-down list.
* @return the text of the selected item, or null if no item is selected
* @see #getText
* @see #getSelectedIndex
*/
public String getSelectedItem()
{
return list.getSelectedItem();
}
/**
* Gets the zero-relative index of the currently selected item in the drop-down list.
* @return the zero-relative index of the current selection, or -1 if no item is selected
* @see #getSelectedItem
*/
public int getSelectedIndex()
{
return list.getSelectedIndex();
}
/**
* Returns the selection state of the list item at the given zero-relative index.
* @param index the zero-relative index of the drop-down list item to be checked
* @return true if the drop-down list item at the specified index has been
* selected; false otherwise
* @see #select
*/
public synchronized boolean isSelected(int index)
{
return list.isSelected(index);
}
/**
* Determines whether the ComboBox should be the first component added to
* its container, or the last. This varies from system to system depending
* on the native user interface. If this method returns true, add the
* ComboBox before adding other components. If it returns false, add other
* components before adding the ComboBox. If the ComboBox is added in the
* wrong order, the drop-down list box will be drawn under the other
* components instead of on top of them.
* @return if true add the ComboBox to its container before other components,
* otherwise add after all other components
* @see #addLastBottomUp
*/
public static boolean addFirstTopDown()
{
return !addLastBottomUp();
}
/**
* Determines whether the ComboBox should be the last component added to
* its container, or the first. This varies from system to system depending
* on the native user interface. If this method returns true, add the
* ComboBox after adding other components. If it returns false, add other
* components after adding the ComboBox. If the ComboBox is added in the
* wrong order, the drop-down list box will be drawn under the other
* components instead of on top of them.
* @return if true add the ComboBox to its container after other components,
* otherwise add before all other components
* @see #addFirstTopDown
*/
public static boolean addLastBottomUp()
{
return symantec.itools.util.ZOrderUtils.isFirstDrawnOverSecond();
}
/**
* Use this method to set a flag for use in your handleEvent to determine if
* the ComboBox needs help in "un-dropping". This will improve useability
* under platforms which do not provide proper focus events. For best
* performance assign a variable in your class once to avoid repeated function
* calls to this method, like this:
* <pre>
* boolean bNeedsPlatformHelp = ComboBox.needsPlatformHelp();
*
* public boolean handleEvent(Event evt)
* {
* switch (evt.id)
* {
* case Event.MOUSE_UP:
* // do it on mouse up, which indicates a full click somewhere other than
* // the ComboBox that could be currently dropped down.
* if (bNeedsPlatformHelp && ComboBox.isListDown)
* ComboBox.setListDown(false);
* break; // or other MOUSE_UP processing as necessary
*
* ...
* }
*
* ...
* }
* </pre>
* @see #setListDown
*/
public static boolean needsPlatformHelp()
{
return bOsFlag;
}
/**
* Clears all items from the drop-down list.
*/
public void clear()
{
list.clear();
editBox.setText("");
updateMaxNumChars();
}
/**
* Adds the specified item to the end of the drop-down list and enables the item.
* @param item the item to be added
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #addItem(java.lang.String, boolean)
* @see #addItem(java.awt.Image, java.lang.String)
* @see #addItem(java.awt.Image, java.lang.String, boolean)
* @see #setListItems(java.lang.String[])
*/
public synchronized void addItem(String item) throws PropertyVetoException
{
addItem((Image)null, item, true);
}
/**
* Adds the specified item to the end of the drop-down list and conditionally enables it.
* @param item the item to be added
* @param bEnabled true = enable the item, false = disable it
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #addItem(java.lang.String)
* @see #addItem(java.awt.Image, java.lang.String)
* @see #addItem(java.awt.Image, java.lang.String, boolean)
* @see #setListItems(java.lang.String[])
*/
public synchronized void addItem(String item, boolean bEnabled) throws PropertyVetoException
{
addItem((Image)null, item, bEnabled);
}
/**
* Adds the specified item with an image to the end of the drop-down list and enables it.
* @param image the image to display on the item line
* @param item the item to be added
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #addItem(java.lang.String)
* @see #addItem(java.lang.String, boolean)
* @see #addItem(java.awt.Image, java.lang.String, boolean)
* @see #setListItems(java.lang.String[])
*/
public synchronized void addItem(Image image, String item) throws PropertyVetoException
{
addItem(image, item, true);
}
/**
* Adds the specified item with an image to the end of the drop-down list and
* conditionally enables it.
* @param image the image to display on the item line
* @param item the item to be added
* @param bEnabled true = enable the item, false = disable it
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #addItem(java.lang.String)
* @see #addItem(java.lang.String, boolean)
* @see #addItem(java.awt.Image, java.lang.String)
* @see #setListItems(java.lang.String[])
*/
public synchronized void addItem(Image image, String item, boolean bEnabled) throws PropertyVetoException
{
list.addItem(image, item, bEnabled);
arrow.setEnabled(true);
updateMaxNumChars();
}
/**
* Returns the total number of items in the drop-down list.
*/
public int countItems()
{
return list.countItems();
}
/**
* Changes the image associated with a drop-down item.
* @param index the zero-relative index of the drop-down item
* @param image the image to associate with the drop-down item
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void setImage(int index, Image image) throws PropertyVetoException
{
list.setImage(index, image);
}
/**
* @deprecated
* @see #setImage(int, java.awt.Image)
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void changeImage(int index, Image image) throws PropertyVetoException
{
setImage(index, image);
}
/**
* Changes the text associated with a drop-down item.
* @param index the zero-relative index of the drop-down item
* @param text the text to associate with the drop-down item
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void setListText(int index, String text) throws PropertyVetoException
{
list.setText(index, text);
updateMaxNumChars();
}
/**
* @deprecated
* @see #setListText(int, java.lang.String)
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void changeText(int index, String text) throws PropertyVetoException
{
setListText(index, text);
}
/**
* Enables a drop-down list item at a given zero-relative index.
* @param index the zero-relative index of the drop-down list item
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void setEnabled(int index) throws PropertyVetoException
{
setEnabled(index, true);
}
/**
* @deprecated
* @see #setEnabled(int)
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void enable(int index) throws PropertyVetoException
{
setEnabled(index);
}
/**
* @deprecated
* @see #setEnabled(int, boolean)
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void disable(int index) throws PropertyVetoException
{
setEnabled(index, false);
}
/**
* Conditionally enables a drop-down list item at a given zero-relative index.
* @param index the zero-relative index of the drop-down list item
* @param cond true = enable the item, false = disable it
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void setEnabled(int index, boolean cond) throws PropertyVetoException
{
list.setEnabled(index, cond);
}
/**
* @deprecated
* @see #setEnabled(int, boolean)
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void enable(int index, boolean cond) throws PropertyVetoException
{
setEnabled(index, cond);
}
/**
* Deletes an item from the drop-down list.
* @param position the zero-relative index of the item
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #delItems
* @see #addItem(java.lang.String)
* @see #addItem(java.lang.String, boolean)
* @see #addItem(java.awt.Image, java.lang.String)
* @see #addItem(java.awt.Image, java.lang.String, boolean)
* @see #setListItems(java.lang.String[])
*/
public synchronized void delItem(int position) throws PropertyVetoException
{
list.delItem(position);
if (list.countItems() == 0)
{
arrow.setEnabled(false);
dropList(false);
}
updateMaxNumChars();
}
/**
* Deletes multiple items from the drop-down list.
* (Note: the end position must be greater than or equal to the start position.)
* @param start the starting zero-relative index of the items
* @param end the ending zero-relative index of the items
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #delItem
* @see #addItem(java.lang.String)
* @see #addItem(java.lang.String, boolean)
* @see #addItem(java.awt.Image, java.lang.String)
* @see #addItem(java.awt.Image, java.lang.String, boolean)
* @see #setListItems(java.lang.String[])
*/
public synchronized void delItems(int start, int end) throws PropertyVetoException
{
list.delItems(start, end);
if (list.countItems() == 0)
{
arrow.setEnabled(false);
dropList(false);
}
updateMaxNumChars();
}
/**
* Deletes the currently selected item from the list.
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #addItem(java.lang.String)
* @see #addItem(java.lang.String, boolean)
* @see #addItem(java.awt.Image, java.lang.String)
* @see #addItem(java.awt.Image, java.lang.String, boolean)
* @see #setListItems(java.lang.String[])
*/
public synchronized void delSelectedItem() throws PropertyVetoException
{
list.delSelectedItems();
updateMaxNumChars();
}
/**
* Selects the drop-down list item with the specified zero-relative index.
* @param index the zero-relative index of the drop-down list item to select
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #deselect
*/
public synchronized void select(int index) throws PropertyVetoException
{
if (index >= 0 && index <= list.countItems())
{
list.setSelectedIndex(index, true);
editBox.setText(list.getSelectedItem());
if (bOsFlag)
{
repaint();
}
}
}
/**
* Selects the first drop-down item in the list which has exactly matching text.
* @param str the String to match
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #deselect
*/
public void select(String str) throws PropertyVetoException
{
list.setSelectedItem(str, true);
editBox.setText(list.getSelectedItem());
if (bOsFlag)
{
repaint();
}
}
/**
* Deselects the drop-down list item at the specified zero-relative index.
* @param index the zero-relative index of the drop-down item to deselect
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #select
*/
public synchronized void deselect(int index) throws PropertyVetoException
{
list.setSelectedIndex(index, false);
editBox.setText("");
}
/**
* Handles dropping and "un-dropping" the ComboBox list.
* @param isDown true to drop the list, false to "un-drop" the list.
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #isListDown
*/
public void setListDown(boolean isDown) throws PropertyVetoException
{
if (bDown != isDown)
{
Boolean oldValue = new Boolean(bDown);
Boolean newValue = new Boolean(isDown);
vetos.fireVetoableChange("listDown", oldValue, newValue);
bDown = isDown;
if (bDown)
{
list.show();
vPad = 1;
}
else
{
list.hide();
vPad = 0;
}
reshapeInternals();
super.reshape(ix, iy, iwidth, lheight + arrowDim + vPad);
invalidate();
changes.firePropertyChange("listDown", oldValue, newValue);
}
}
/**
* Is the list up or down?
* @return true if the list is down, false if not.
* @see #setListDown
*/
public boolean isListDown()
{
return bDown;
}
/**
* @deprecated
* @see #setListDown
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void dropList(boolean bDown) throws PropertyVetoException
{
setListDown(bDown);
}
/**
* Moves and/or resizes this component.
* This is a standard Java AWT method which gets called to move and/or
* resize this component. Components that are in containers with layout
* managers should not call this method, but rely on the layout manager
* instead.
*
* @param x horizontal position in the parent's coordinate space
* @param y vertical position in the parent's coordinate space
* @param width the new width
* @param height the new height
*/
public synchronized void reshape(int x, int y, int width, int height)
{
super.reshape(x, y, width, height);
ix = x;
iy = y;
iwidth = width;
reshapeInternals();
}
/**
* Paints this component using the given graphics context.
* This is a standard Java AWT method which typically gets called
* by the AWT to handle painting this component. It paints this component
* using the given graphics context. The graphics context clipping region
* is set to the bounding rectangle of this component and its [0,0]
* coordinate is this component's top-left corner.
*
* @param g the graphics context used for painting
* @see java.awt.Component#repaint
* @see java.awt.Component#update
*/
public void paint(Graphics g)
{
super.paint(g);
reshapeInternals();
}
/**
* Returns the recommended dimensions to properly display this component.
* This is a standard Java AWT method which gets called to determine
* the recommended size of this component.
* Preferred size is .
*
* @see #getMinimumSize
*/
public Dimension getPreferredSize()
{
reshapeInternals();
int editBoxPreferredWidth = editBox.getPreferredSize(maxNumChars).width;
if(bDown)
return new Dimension(editBoxPreferredWidth + arrowDim + hPad, arrowDim + vPad + lheight);
else
return new Dimension(editBoxPreferredWidth + arrowDim + hPad, arrowDim);
}
/**
* Returns the minimum dimensions to properly display this component.
* This is a standard Java AWT method which gets called to determine
* the minimum size of this component.
* Returns the results of a call to getPreferredSize.
* @see #getPreferredSize
*/
public Dimension getMinimumSize()
{
return getPreferredSize();
}
/**
* Sets the command name of the action event fired by this button.
* @param command The name of the action event command fired by this button
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void setActionCommand(String command) throws PropertyVetoException
{
String oldValue = actionCommand;
vetos.fireVetoableChange("actionCommand", oldValue, command);
actionCommand = command;
changes.firePropertyChange("actionCommand", oldValue, command);
}
/**
* @return the command name of the action event fired by this button.
*/
public String getActionCommand()
{
return actionCommand;
}
/**
* Tells this component that it has been added to a container.
* This is a standard Java AWT method which gets called by the AWT when
* this component is added to a container. Typically, it is used to
* create this component's peer.
*
* It has been overridden here to hook-up event listeners.
*
* @see #removeNotify
*/
public synchronized void addNotify()
{
super.addNotify();
//Hook up listeners
if (mouse == null)
{
mouse = new Mouse();
list.addMouseListener(mouse);
editBox.addMouseListener(mouse);
}
if (keyList == null)
{
keyList = new KeyList();
list.addKeyListener(keyList);
}
if (keyBox == null)
{
keyBox = new KeyBox();
editBox.addKeyListener(keyBox);
}
if (item == null)
{
item = new Item();
list.addItemListener(item);
}
if (action == null)
{
action = new Action();
arrow.addActionListener(action);
}
if (focus == null)
{
focus = new Focus();
addFocusListener(focus);
arrow.addFocusListener(focus);
editBox.addFocusListener(focus);
}
}
/**
* Tells this component that it is being removed from a container.
* This is a standard Java AWT method which gets called by the AWT when
* this component is removed from a container. Typically, it is used to
* destroy the peers of this component and all its subcomponents.
*
* It has been overridden here to unhook event listeners.
*
* @see #addNotify
*/
public synchronized void removeNotify()
{
//Unhook listeners
if (mouse != null)
{
list.removeMouseListener(mouse);
editBox.removeMouseListener(mouse);
mouse = null;
}
if (keyList != null)
{
list.removeKeyListener(keyList);
keyList = null;
}
if (keyBox != null)
{
editBox.removeKeyListener(keyBox);
keyBox = null;
}
if (item != null)
{
list.removeItemListener(item);
item = null;
}
if (action != null)
{
arrow.removeActionListener(action);
action = null;
}
if (focus != null)
{
removeFocusListener(focus);
arrow.removeFocusListener(focus);
editBox.removeFocusListener(focus);
focus = null;
}
super.removeNotify();
}
/**
* Takes no action.
* This is a standard Java AWT method which gets called to specify
* which layout manager should be used to layout the components in
* standard containers.
*
* Since layout managers CANNOT BE USED with this container the standard
* setLayout has been OVERRIDDEN for this container and does nothing.
*
* @param lm the layout manager to use to layout this container's components
* (IGNORED)
* @see java.awt.Container#getLayout
**/
public void setLayout(LayoutManager lm)
{
}
public void validate()
{
super.validate();
reshapeInternals();
}
/**
* Adds the specified action listener to receive action events
* @param l the action listener
*/
public synchronized void addActionListener(ActionListener l)
{
actionListener = AWTEventMulticaster.add(actionListener, l);
}
/**
* Removes the specified action listener so it no longer receives
* action events.
* @param l the action listener
*/
public synchronized void removeActionListener(ActionListener l)
{
actionListener = AWTEventMulticaster.remove(actionListener, l);
}
/**
* Adds a listener for all event changes.
* @param listener the listener to add.
* @see #removePropertyChangeListener
*/
public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
{
changes.addPropertyChangeListener(listener);
}
/**
* Removes a listener for all event changes.
* @param listener the listener to remove.
* @see #addPropertyChangeListener
*/
public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
{
changes.removePropertyChangeListener(listener);
}
/**
* Adds a vetoable listener for all event changes.
* @param listener the listener to add.
* @see #removeVetoableChangeListener
*/
public synchronized void addVetoableChangeListener(VetoableChangeListener listener)
{
vetos.addVetoableChangeListener(listener);
}
/**
* Removes a vetoable listener for all event changes.
* @param listener the listener to remove.
* @see #addVetoableChangeListener
*/
public synchronized void removeVetoableChangeListener(VetoableChangeListener listener)
{
vetos.removeVetoableChangeListener(listener);
}
/**
* This is the Mouse Event handling innerclass.
*/
class Mouse extends java.awt.event.MouseAdapter implements java.io.Serializable
{
boolean wasPressed = false;
/**
* Handles Mouse Entered events
* @param e the MouseEvent
*/
public void mouseEntered(MouseEvent e)
{
Object source = e.getSource();
if(source == list)
bOverList = true;
}
/**
* Handles Mouse Exited events
* @param e the MouseEvent
*/
public void mouseExited(MouseEvent e)
{
//We are only listening to the list...
bOverList = false;
}
public void mousePressed(MouseEvent e)
{
Object source = e.getSource();
if(source == editBox)
{
wasPressed = true;
}
else
wasPressed = false;
}
public void mouseReleased(MouseEvent e)
{
Object source = e.getSource();
if(source == editBox && wasPressed && !(bEditable || bSearchable))
{
try
{
setListDown(!bDown);
}
catch (PropertyVetoException exc) {}
}
wasPressed = false;
}
}
/**
* This is the Adjustment Event handling innerclass.
*/
class Action implements java.awt.event.ActionListener, java.io.Serializable
{
/**
* Handles Action events
* @param e the ActionEvent
*/
public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
if(source instanceof DirectionButton)
{
try
{
setListDown(!bDown);
}
catch (PropertyVetoException exc) {}
}
else if(e.getActionCommand().equals("ImageSelected"))
{
sourceActionEvent("ImageSelected");
}
}
}
/**
* This is the Key Event handling innerclass for handling
* KeyEvents from the editBox.
*/
class KeyBox extends java.awt.event.KeyAdapter implements java.io.Serializable
{
/**
* Handles Key Pressed events
* @param e the KeyEvent
*/
public void keyPressed(KeyEvent e)
{
sLastText = editBox.getText();
}
/**
* Handles Key Released events
* @param e the KeyEvent
*/
public void keyReleased(KeyEvent e)
{
verify();
}
}
/**
* This is the Key Event handling innerclass for handling
* KeyEvents from the list.
*/
class KeyList extends java.awt.event.KeyAdapter implements java.io.Serializable
{
/**
* Handles Key Pressed events
* @param e the KeyEvent
*/
public void keyPressed(KeyEvent e)
{
sLastText = editBox.getText();
}
/**
* Handles Key Released events
* @param e the KeyEvent
*/
public void keyReleased(KeyEvent e)
{
//We are only listening to the list...
switch(e.getKeyCode())
{
case KeyEvent.VK_HOME:
try { list.setSelectedIndex(0, true); } catch(PropertyVetoException exc) {}
break;
case KeyEvent.VK_END:
try { list.setSelectedIndex(list.countItems() - 1, true); } catch(PropertyVetoException exc) {}
break;
case KeyEvent.VK_PAGE_UP:
case KeyEvent.VK_UP:
try { list.setSelectedIndex(list.getSelectedIndex() - 1, true); } catch(PropertyVetoException exc) {}
break;
case KeyEvent.VK_PAGE_DOWN:
case KeyEvent.VK_DOWN:
try { list.setSelectedIndex(list.getSelectedIndex() + 1, true); } catch(PropertyVetoException exc) {}
break;
}
editBox.setText(list.getSelectedItem());
editBox.selectAll();
verify();
}
}
/**
* This is the Focus Event handling innerclass.
*/
class Focus implements java.awt.event.FocusListener, java.io.Serializable
{
/**
* Handles Focus Gained events
* @param e the FocusEvent
*/
public void focusGained(FocusEvent e)
{
Object source = e.getSource();
if (source instanceof ComboBox && !bDown)
{
editBox.selectAll();
editBox.requestFocus();
}
if (bOsFlag)
{
if (source == editBox)
{
try
{
setListDown(false);
}
catch (PropertyVetoException exc) {}
}
}
}
/**
* Handles Focus Lost events
* @param e the FocusEvent
*/
public void focusLost(FocusEvent e)
{
if ((e.getSource() == arrow) && !bOverList)
{
try
{
setListDown(false);
}
catch (PropertyVetoException exc) {}
}
}
}
/**
* This is the Item Event handling innerclass.
*/
class Item implements java.awt.event.ItemListener, java.io.Serializable
{
/**
* Handles Item State Changed events
* @param e the ItemEvent
*/
public void itemStateChanged(ItemEvent e)
{
editBox.setText(list.getSelectedItem());
sourceActionEvent();
try
{
setListDown(false);
}
catch (PropertyVetoException exc) {}
}
}
/**
* Fire an action event to the listeners
* @param command the string containing the command to send
* with the event.
* @see #sourceActionEvent()
*/
protected void sourceActionEvent(String command)
{
if (actionListener != null)
actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, command));
}
/**
* Fire an action event to the listeners
* with the actionCommand
* @see #sourceActionEvent(java.lang.String)
*/
protected void sourceActionEvent()
{
sourceActionEvent(actionCommand);
}
/**
* Used to calculate the preferred size of the text field to
* determine overall preferred size.
* Should be called after any manipulation of the list items.
* @see #getPreferredSize
*/
protected void updateMaxNumChars()
{
maxNumChars = 0;
String[] listItems = getListItems();
if(listItems != null)
{
int listLength = listItems.length;
for (int i = 0; i < listLength; ++i)
{
maxNumChars = Math.max(listItems[i].length(), maxNumChars);
}
}
}
/**
* A utility routine to resize the sub-components that make up a ComboBox.
*/
protected void reshapeInternals()
{
Dimension s = size();
Dimension arrowSize = arrow.getPreferredSize();
Dimension editBoxPreferredSize = editBox.getPreferredSize();
arrowDim = Math.max(arrowSize.width, arrowSize.height);
if (editBoxPreferredSize.height > arrowDim)
arrowDim = editBoxPreferredSize.height;
editBox.reshape(0,0, s.width - 1 - arrowDim - hPad, editBoxPreferredSize.height);
arrow.setBounds(s.width - arrowDim, 0, arrowDim, arrowDim);
arrow.shrinkTriangle(1, 1, 4, 3);
if (bDown)
{
if (getParent() != null)
{
int availableHeight = getParent().bounds().height - iy - arrowDim - vPad;
int preferredHeight = list.getMinimumSize().height;
if(availableHeight < preferredHeight)
{
//Get the height of the number of rows that will fit in the available height.
lheight = list.getMinimumSize( (availableHeight - list.getBorderWidth()) / list.getCellHeight() ).height;
}
else
{
lheight = preferredHeight;
}
}
else
{
lheight = list.getMinimumSize().height;
}
list.reshape(0, arrowDim + vPad, s.width, lheight);
}
else
lheight = 0;
}
/**
* Verify that at least one list item starts with the edit field's text.
* If a match is found, the edit field's text is set to that item's value.
* This is done only if searching is enabled.
*/
protected void verify()
{
if (bSearchable == true)
{
searchIndex = editBox.getSelectionStart();
sSearchOrig = editBox.getText().substring(0, searchIndex);
if (bCaseSensitive)
{
sSearchText = sSearchOrig;
}
else
{
sSearchText = sSearchOrig.toUpperCase();
}
searchLen = list.countItems();
searchI = 0;
int stLength = sSearchText.length();
int matchIndex = 0;
int maxMatch = 0;
String matchString;
String matchItem = "";
boolean isBreak;
if (stLength > 0)
{
while(searchI < searchLen)
{
if (bCaseSensitive)
{
sSearchItem = list.getText(searchI);
}
else
{
sSearchItem = list.getText(searchI).toUpperCase();
}
isBreak = false;
matchIndex = 1;
while(matchIndex <= stLength)
{
matchString = sSearchText.substring(0, matchIndex);
if (sSearchItem.startsWith(matchString))
{
try { list.setSelectedIndex(searchI, true); } catch(PropertyVetoException e) {}
if(maxMatch < matchIndex)
{
maxMatch = matchIndex;
matchItem = sSearchItem;
}
isBreak = true;
++matchIndex;
}
else //It doesn't match. Go on to the next list item...
{
isBreak = false;
++searchI;
break;
}
}
if(isBreak)
{
break;
}
}
if (!bEditable) //if not editable and
{
editBox.setText(matchItem);
if(searchI == searchLen) //search failed
{
editBox.select(maxMatch, maxMatch);
}
else //search success
{
editBox.select(searchIndex, searchIndex);
}
//If the cursor is at the beginning of the box there should be nothing found...
if (editBox.getSelectionStart() == 0)
editBox.setText("");
}
}
}
sLastText = editBox.getText();
}
/**
* The command name of the action event fired by this component.
*/
protected String actionCommand;
/**
* The action listener to keep track of listeners for our action event.
*/
protected ActionListener actionListener = null;
/** The text field part of this ComboBox.
*/
protected TextField editBox;
/** The button on the right part of this ComboBox that controls dopping the list.
*/
protected DirectionButton arrow;
/** The list part of this ComboBox.
*/
protected ImageListBox list;
/**
* The number of characters of the longest item in the list.
* Used to calculate preferred size.
* @see #updateMaxNumChars
*/
protected int maxNumChars = 0;
/** True if the mouse is over the ComboBox.
*/
transient protected boolean bOverList = false;
/** True if the list is currently dropped (displayed).
*/
transient protected boolean bDown = false;
/** The latest user-entered text.
*/
transient protected String sLastText;
/** If true this ComboBox has a user-editable text field.
*/
protected boolean bEditable;
/** If true this ComboBox is searchable.
*/
protected boolean bSearchable;
/** If true search compares are case-sensitive.
*/
protected boolean bCaseSensitive;
/** The x parameter value in the latest reshape() call.
*/
protected int ix;
/** The y parameter value in the latest reshape() call.
*/
protected int iy;
/** The width parameter value in the latest reshape() call.
*/
protected int iwidth;
/** The current height of the list.
*/
protected int lheight;
/** The dimension of the arrow button.
*/
protected int arrowDim;
/** The distance between the direction button and the edit text box.
*/
protected int hPad;
/** The distance between the edit text box and the drop down list.
*/
protected int vPad;
/** If true the horizontal scroll bar is shown as needed.
*/
protected boolean showHScroll = false;
/** If true the vertical scroll bar is shown as needed.
*/
protected boolean showVScroll = true;
/** True if running under Windows.
*/
transient protected static boolean bOsFlag;
/** The case-normalized user-entered string used to match during searches.
*/
protected String sSearchText;
/** The list item string used to match during searches.
*/
protected String sSearchItem;
/** The user-entered string used to match during searches.
* Not case normalized.
*/
protected String sSearchOrig;
/** Where the selected area starts in the user-entered text.
*/
protected int searchIndex;
/** The number of items in the list to seach (all).
*/
protected int searchLen;
/** The list item currently being checked for search match.
*/
protected int searchI;
private Mouse mouse = null;
private KeyList keyList = null;
private KeyBox keyBox = null;
private Action action = null;
private Focus focus = null;
private Item item = null;
private VetoableChangeSupport vetos = new VetoableChangeSupport(this);
private PropertyChangeSupport changes = new PropertyChangeSupport(this);
static
{
bOsFlag = !symantec.itools.lang.OS.isWindows() && !symantec.itools.lang.OS.isMacintosh();
}
}