/*
Copyright (C) 2003 EBI, GRL
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.ensembl.mart.explorer;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collection;
import java.util.Iterator;
import java.util.prefs.Preferences;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.ComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
* Compound widget that contains a JComboBox and optional radio button.
* Additional behaviour includes broadcasting change events to listeners
* when state changes and support for converting list of items to/from
* strings (useful for storing in history files).
*
*/
public class LabelledComboBox extends Box implements ActionListener {
private final int GAP = 5;
private ChangeListenerManager changeListenerManager;
private ChangeEvent changeEvent = null;
private JRadioButton radioButton = null;
private JComboBox combo = null;
private String preferenceKey = null;
public LabelledComboBox(String label) {
this( label, null, null);
}
public LabelledComboBox(String label, ChangeListener listener) {
this(label, listener, null);
}
public LabelledComboBox(String label, ChangeListener listener, ButtonGroup group) {
super( BoxLayout.X_AXIS);
changeListenerManager = new ChangeListenerManager();
if ( group!=null ) {
radioButton = new JRadioButton( label );
radioButton.addActionListener( this );
add( radioButton );
} else {
add( new JLabel( label ) );
}
if ( listener!=null ) {
changeListenerManager.addChangeListener( listener );
}
changeEvent = new ChangeEvent(this);
add( Box.createHorizontalStrut( GAP*2 ) );
combo = new JComboBox();
combo.setEditable( true );
combo.addActionListener( this );
add( combo );
Dimension dim = new Dimension(500, 35);
setPreferredSize( dim );
setMaximumSize( dim );
setBorder( new EmptyBorder(GAP, GAP, GAP, GAP) );
}
/**
* Called when the user alters the contents of the Component. Sets the radio button to selected
* (if it is available) and broadcasts change messages to all change listeners.
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
public void actionPerformed(ActionEvent e) {
// this enables us to select the radio button if the combobox value changes
if ( radioButton!=null ) {
radioButton.setSelected( true );
}
changeListenerManager.stateChanged( changeEvent );
}
/**
* @param listener
*/
public void addChangeListener(ChangeListener listener) {
changeListenerManager.addChangeListener(listener);
}
/**
* @param listener
* @return
*/
public boolean removeChangeListener(ChangeListener listener) {
return changeListenerManager.removeChangeListener(listener);
}
/**
* Currently selected text.
* @return currently selected text, or "" if none selected.
*/
public String getText() {
String text="";
if ( combo.getSelectedItem()!=null ) {
text = combo.getSelectedItem().toString();
}
return text;
}
/**
* Sets the currently selected text.
* @param text currently selected string.
*/
public void setText(String text) {
combo.setSelectedItem( text );
}
/**
* Synonym for removeAllItems.
*/
public void clear() {
removeAllItems();
}
/**
* Whether the (optional) radio button is selected.
* @return true if radio button is available and selected, otherwise false.
*/
public boolean isSelected() {
if ( radioButton!=null ) return radioButton.isSelected();
else return false;
}
/**
* Adds item to list. Does nothing if item is present.
* @param anObject object to be added to list.
*/
public void addItem(Object anObject) {
if ( !hasItem(anObject) )
combo.addItem(anObject);
}
/**
* Adds all items to list.
* @param anObject object to be added to list.
*/
public void addAll(Collection c) {
for (Iterator iter = c.iterator(); iter.hasNext();)
combo.addItem( iter.next() );
}
/**
* Removes all items from list.
*/
public void removeAllItems() {
combo.removeAllItems();
}
/**
* Resets the list according to the contents of the string.
* @see #toPreferenceString(int)
* @param list of strings separated by commas.
*/
public void parsePreferenceString(String list) {
clear();
String[] hosts = list.split(",");
for (int i = 0, n = hosts.length; i < n; i++) {
addItem( hosts[i] );
}
}
/**
* Combo box option list represented as a string.
* Format of String is strings separated by commas e.g. "item1,item2,item3"
* @param limit maximum number of items to include in string.
* @return string representation of first items in combo box.
*/
private String toPreferenceString(int limit) {
StringBuffer buf = new StringBuffer();
// add the currently selected item
String text = getText();
buf.append( text );
// add the rest of the items so long as the number is less than the max
int max = Math.min( combo.getItemCount(), limit-1);
for (int i = 0; i < max; i++) {
Object item = combo.getItemAt(i);
// don't add duplicates items.
if ( !text.equals(item) ) buf.append(",").append( item );
}
return buf.toString();
}
public void setPreferenceKey(String preferencesKey) {
this.preferenceKey = preferencesKey;
}
public String getPreferenceKey() {
return preferenceKey;
}
/**
* Stores the item list in preferences.
* @param preferences place to store items.
* @param limit maximum number of items from list to store.
* @throws RuntimeException if preferenceKey is not set.
*/
public void store(Preferences preferences, int limit) {
if ( preferenceKey==null ) {
throw new RuntimeException("PreferenceKey must be set first.");
}
String value = toPreferenceString(limit);
if ( value!=null )
preferences.put(preferenceKey, value );
}
/**
* Loads the item list from preferences.
* @param preferences object to retrieve list from.
* @throws RuntimeException if preferenceKey is not set.
*/
public void load(Preferences preferences) {
if ( preferenceKey==null ) {
throw new RuntimeException("PreferenceKey must be set first.");
}
parsePreferenceString( preferences.get( preferenceKey, "" ));
}
/**
* Determines whether combo box is editable by User. If not it behaves like a
* drop down list.
* @param editabale whether the user can enter text in the combo box.
*/
public void setEditable(boolean editable) {
combo.setEditable( editable );
}
/**
* @return selected item.
*/
public Object getSelectedItem() {
return combo.getSelectedItem();
}
/**
* @param anObject
*/
public void setSelectedItem(Object anObject) {
if ( combo.getSelectedItem()==anObject) return;
combo.setSelectedItem(anObject);
}
/**
* @param item
* @return true if item in combo list, otherwise false
*/
public boolean hasItem(Object item) {
return indexOfItem(item)!=-1;
}
/**
* @param item
* @return index of item or -1 if not found
*/
public int indexOfItem(Object item) {
int index = -1;
ComboBoxModel model = combo.getModel();
for (int i = 0; index==-1 && i < model.getSize(); i++) {
if ( model.getElementAt(i).equals(item) ) index = i;
}
return index;
}
/**
* @param index
* @return
*/
public Object getItemAt(int index) {
return combo.getItemAt(index);
}
/**
* @return
*/
public int getItemCount() {
return combo.getItemCount();
}
}