// FilterElementChooser
package org.javamoney.examples.ez.money.gui.chooser;
import static java.awt.event.MouseEvent.BUTTON1;
import static java.util.Arrays.binarySearch;
import static org.javamoney.examples.ez.money.gui.GUIConstants.CELL_HEIGHT;
import static org.javamoney.examples.ez.money.gui.GUIConstants.COLOR_BACKGROUND_FILL;
import static org.javamoney.examples.ez.money.utility.RenderHelper.setLookFor;
import java.awt.Component;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import org.javamoney.examples.ez.money.model.DataElement;
import org.javamoney.examples.ez.money.model.dynamic.SelectableElement;
import org.javamoney.examples.ez.money.model.dynamic.total.TotalFilter;
import org.javamoney.examples.ez.money.model.persisted.category.Category;
import org.javamoney.examples.ez.common.gui.CheckBox;
/**
* This class facilitates providing a list for selecting elements.
*/
public
final
class
FilterElementChooser
extends JList
{
/**
* Constructs a new chooser for the specified collection.
*
* @param collection The collection of elements to display.
*/
public
FilterElementChooser(Collection<DataElement> collection)
{
super(new DefaultListModel());
setAutoscrolls(true);
setCellRenderer(new CellRenderer());
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
addElements(collection);
setBackground(COLOR_BACKGROUND_FILL);
setFixedCellHeight(CELL_HEIGHT);
// Add listeners.
addKeyListener(new KeyHandler());
addMouseListener(new MouseHandler());
}
/**
* This method returns the selected values. If all the values are selected,
* then CategoryTotalsFilter.ALL is returned. This signals to not constrain
* the transactions. It is the equivalent of having nothing selected.
* <p>
* There is an exception to this when there is only one item in the list and
* it is selected. In this case, an array containing the one value is
* returned. This is to ensure that all transactions are constrained to that
* value.
*
* @return The selected values.
*/
@Override
public
String[]
getSelectedValues()
{
String[] values = TotalFilter.ALL;
Enumeration<?> enumeration = getDefaultListModel().elements();
if(isEnabled() == true)
{
ArrayList<String> list = new ArrayList<String>();
int size = getDefaultListModel().getSize();
// Find selected elements.
while(enumeration.hasMoreElements() == true)
{
SelectableElement element = (SelectableElement)enumeration.nextElement();
if(element.isSelected() == true)
{
list.add(element.toString());
}
}
if(list.size() != 0)
{
if(list.size() != size || (list.size() == 1 && size == 1))
{
values = new String[list.size()];
for(int len = 0; len < list.size(); ++len)
{
values[len] = list.get(len);
}
}
}
}
return values;
}
/**
* This method selects all the elements contained in the specified array.
*
* @param values The array of elements to select.
*/
public
void
selectValues(String[] values)
{
int max = getDefaultListModel().getSize();
for(int len = 0; len < max; ++len)
{
SelectableElement element = getElementAt(len);
if(binarySearch(values, element.toString()) >= 0)
{
element.setIsSelected(true);
}
}
}
/**
* This method sets whether or not the chooser is enabled.
*
* @param value true or false.
*/
@Override
public
void
setEnabled(boolean value)
{
super.setEnabled(value);
clearSelection();
}
//////////////////////////////////////////////////////////////////////////////
// Start of private methods.
//////////////////////////////////////////////////////////////////////////////
private
void
addElement(Object object)
{
getDefaultListModel().addElement(object);
}
private
void
addElements(Collection<DataElement> collection)
{
for(DataElement element : collection)
{
if(element instanceof Category)
{
Category category = (Category)element;
addElement(new SelectableElement(category.getQIFName()));
addElements(category.getSubcategories());
}
else
{
addElement(new SelectableElement(element.toString()));
}
}
}
private
SelectableElement
getElementAt(int index)
{
return (SelectableElement)getDefaultListModel().getElementAt(index);
}
private
DefaultListModel
getDefaultListModel()
{
return (DefaultListModel)getModel();
}
private
void
selectElement()
{
SelectableElement element = (SelectableElement)getSelectedValue();
if(element != null)
{
element.setIsSelected(!element.isSelected());
repaint();
}
}
//////////////////////////////////////////////////////////////////////////////
// Start of inner classes.
//////////////////////////////////////////////////////////////////////////////
private
class
CellRenderer
extends CheckBox
implements ListCellRenderer
{
public
Component
getListCellRendererComponent(JList list, Object value, int index,
boolean isSelected, boolean hasFocus)
{
SelectableElement element = (SelectableElement)value;
// Customize look.
setLookFor(this, index, isSelected, false);
setEnabled(list.isEnabled());
setHorizontalAlignment(SwingConstants.LEFT);
setSelected(element.isSelected());
setText(element.toString());
return this;
}
}
private
class
KeyHandler
extends KeyAdapter
{
@Override
public
void
keyReleased(KeyEvent event)
{
if(event.getKeyCode() == KeyEvent.VK_SPACE)
{
selectElement();
}
}
}
private
class
MouseHandler
extends MouseAdapter
{
@Override
public
void
mouseClicked(MouseEvent event)
{
if(event.getButton() == BUTTON1)
{
int xCoordinate = event.getPoint().x;
// Simulate that only the box itself is clickable.
if(xCoordinate > 4 && xCoordinate < 20)
{
selectElement();
}
}
}
}
}