org.jfree.ui.KeyedComboBoxModel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jtstand-common Show documentation
Show all versions of jtstand-common Show documentation
jtstand-common is a library derived from jcommon, used by jtstand-chart, which is derived from jfreechart
/*
* Copyright (c) 2009 Albert Kurucz.
*
* This file, KeyedComboBoxModel.java is part of JTStand.
*
* JTStand 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 3 of the License, or
* (at your option) any later version.
*
* JTStand 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 GTStand. If not, see .
*/
package org.jfree.ui;
import java.util.ArrayList;
import javax.swing.ComboBoxModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
/**
* The KeyedComboBox model allows to define an internal key (the data element)
* for every entry in the model.
*
* This class is usefull in all cases, where the public text differs from the
* internal view on the data. A separation between presentation data and
* processing data is a prequesite for localizing combobox entries. This model
* does not allow selected elements, which are not in the list of valid
* elements.
*
* @author Thomas Morgner
*/
public class KeyedComboBoxModel implements ComboBoxModel
{
/**
* The internal data carrier to map keys to values and vice versa.
*/
private static class ComboBoxItemPair
{
/**
* The key.
*/
private Object key;
/**
* The value for the key.
*/
private Object value;
/**
* Creates a new item pair for the given key and value. The value can be
* changed later, if needed.
*
* @param key the key
* @param value the value
*/
public ComboBoxItemPair(final Object key, final Object value)
{
this.key = key;
this.value = value;
}
/**
* Returns the key.
*
* @return the key.
*/
public Object getKey()
{
return this.key;
}
/**
* Returns the value.
*
* @return the value for this key.
*/
public Object getValue()
{
return this.value;
}
/**
* Redefines the value stored for that key.
*
* @param value the new value.
*/
public void setValue(final Object value)
{
this.value = value;
}
}
/**
* The index of the selected item.
*/
private int selectedItemIndex;
private Object selectedItemValue;
/**
* The data (contains ComboBoxItemPairs).
*/
private ArrayList data;
/**
* The listeners.
*/
private ArrayList listdatalistener;
/**
* The cached listeners as array.
*/
private transient ListDataListener[] tempListeners;
private boolean allowOtherValue;
/**
* Creates a new keyed combobox model.
*/
public KeyedComboBoxModel()
{
this.data = new ArrayList();
this.listdatalistener = new ArrayList();
}
/**
* Creates a new keyed combobox model for the given keys and values. Keys
* and values must have the same number of items.
*
* @param keys the keys
* @param values the values
*/
public KeyedComboBoxModel(final Object[] keys, final Object[] values)
{
this();
setData(keys, values);
}
/**
* Replaces the data in this combobox model. The number of keys must be
* equals to the number of values.
*
* @param keys the keys
* @param values the values
*/
public void setData(final Object[] keys, final Object[] values)
{
if (values.length != keys.length)
{
throw new IllegalArgumentException("Values and text must have the same length.");
}
this.data.clear();
this.data.ensureCapacity(keys.length);
for (int i = 0; i < values.length; i++)
{
add(keys[i], values[i]);
}
this.selectedItemIndex = -1;
final ListDataEvent evt = new ListDataEvent
(this, ListDataEvent.CONTENTS_CHANGED, 0, this.data.size() - 1);
fireListDataEvent(evt);
}
/**
* Notifies all registered list data listener of the given event.
*
* @param evt the event.
*/
protected synchronized void fireListDataEvent(final ListDataEvent evt)
{
if (this.tempListeners == null)
{
this.tempListeners = (ListDataListener[]) this.listdatalistener.toArray
(new ListDataListener[this.listdatalistener.size()]);
}
final ListDataListener[] listeners = this.tempListeners;
for (int i = 0; i < listeners.length; i++)
{
final ListDataListener l = listeners[i];
l.contentsChanged(evt);
}
}
/**
* Returns the selected item.
*
* @return The selected item or null
if there is no selection
*/
public Object getSelectedItem()
{
return this.selectedItemValue;
}
/**
* Defines the selected key. If the object is not in the list of values, no
* item gets selected.
*
* @param anItem the new selected item.
*/
public void setSelectedKey(final Object anItem)
{
if (anItem == null)
{
this.selectedItemIndex = -1;
this.selectedItemValue = null;
}
else
{
final int newSelectedItem = findDataElementIndex(anItem);
if (newSelectedItem == -1)
{
this.selectedItemIndex = -1;
this.selectedItemValue = null;
}
else
{
this.selectedItemIndex = newSelectedItem;
this.selectedItemValue = getElementAt(this.selectedItemIndex);
}
}
fireListDataEvent(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, -1, -1));
}
/**
* Set the selected item. The implementation of this method should notify
* all registered ListDataListener
s that the contents have
* changed.
*
* @param anItem the list object to select or null
to clear the
* selection
*/
public void setSelectedItem(final Object anItem)
{
if (anItem == null)
{
this.selectedItemIndex = -1;
this.selectedItemValue = null;
}
else
{
final int newSelectedItem = findElementIndex(anItem);
if (newSelectedItem == -1)
{
if (isAllowOtherValue())
{
this.selectedItemIndex = -1;
this.selectedItemValue = anItem;
}
else
{
this.selectedItemIndex = -1;
this.selectedItemValue = null;
}
}
else
{
this.selectedItemIndex = newSelectedItem;
this.selectedItemValue = getElementAt(this.selectedItemIndex);
}
}
fireListDataEvent(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, -1, -1));
}
private boolean isAllowOtherValue()
{
return this.allowOtherValue;
}
/**
* @param allowOtherValue
*/
public void setAllowOtherValue(final boolean allowOtherValue)
{
this.allowOtherValue = allowOtherValue;
}
/**
* Adds a listener to the list that's notified each time a change to the data
* model occurs.
*
* @param l the ListDataListener
to be added
*/
public synchronized void addListDataListener(final ListDataListener l)
{
if (l == null)
{
throw new NullPointerException();
}
this.listdatalistener.add(l);
this.tempListeners = null;
}
/**
* Returns the value at the specified index.
*
* @param index the requested index
* @return the value at index
*/
public Object getElementAt(final int index)
{
if (index >= this.data.size())
{
return null;
}
final ComboBoxItemPair datacon = (ComboBoxItemPair) this.data.get(index);
if (datacon == null)
{
return null;
}
return datacon.getValue();
}
/**
* Returns the key from the given index.
*
* @param index the index of the key.
* @return the the key at the specified index.
*/
public Object getKeyAt(final int index)
{
if (index >= this.data.size())
{
return null;
}
if (index < 0)
{
return null;
}
final ComboBoxItemPair datacon = (ComboBoxItemPair) this.data.get(index);
if (datacon == null)
{
return null;
}
return datacon.getKey();
}
/**
* Returns the selected data element or null if none is set.
*
* @return the selected data element.
*/
public Object getSelectedKey()
{
return getKeyAt(this.selectedItemIndex);
}
/**
* Returns the length of the list.
*
* @return the length of the list
*/
public int getSize()
{
return this.data.size();
}
/**
* Removes a listener from the list that's notified each time a change to
* the data model occurs.
*
* @param l the ListDataListener
to be removed
*/
public void removeListDataListener(final ListDataListener l)
{
this.listdatalistener.remove(l);
this.tempListeners = null;
}
/**
* Searches an element by its data value. This method is called by the
* setSelectedItem method and returns the first occurence of the element.
*
* @param anItem the item
* @return the index of the item or -1 if not found.
*/
private int findDataElementIndex(final Object anItem)
{
if (anItem == null)
{
throw new NullPointerException("Item to find must not be null");
}
for (int i = 0; i < this.data.size(); i++)
{
final ComboBoxItemPair datacon = (ComboBoxItemPair) this.data.get(i);
if (anItem.equals(datacon.getKey()))
{
return i;
}
}
return -1;
}
/**
* Tries to find the index of element with the given key. The key must not
* be null.
*
* @param key the key for the element to be searched.
* @return the index of the key, or -1 if not found.
*/
public int findElementIndex(final Object key)
{
if (key == null)
{
throw new NullPointerException("Item to find must not be null");
}
for (int i = 0; i < this.data.size(); i++)
{
final ComboBoxItemPair datacon = (ComboBoxItemPair) this.data.get(i);
if (key.equals(datacon.getValue()))
{
return i;
}
}
return -1;
}
/**
* Removes an entry from the model.
*
* @param key the key
*/
public void removeDataElement(final Object key)
{
final int idx = findDataElementIndex(key);
if (idx == -1)
{
return;
}
this.data.remove(idx);
final ListDataEvent evt = new ListDataEvent
(this, ListDataEvent.INTERVAL_REMOVED, idx, idx);
fireListDataEvent(evt);
}
/**
* Adds a new entry to the model.
*
* @param key the key
* @param cbitem the display value.
*/
public void add(final Object key, final Object cbitem)
{
final ComboBoxItemPair con = new ComboBoxItemPair(key, cbitem);
this.data.add(con);
final ListDataEvent evt = new ListDataEvent
(this, ListDataEvent.INTERVAL_ADDED, this.data.size() - 2, this.data.size() - 2);
fireListDataEvent(evt);
}
/**
* Removes all entries from the model.
*/
public void clear()
{
final int size = getSize();
this.data.clear();
final ListDataEvent evt = new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, 0, size - 1);
fireListDataEvent(evt);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy