/*
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.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import org.ensembl.mart.guiutils.QuickFrame;
import org.ensembl.mart.lib.BasicFilter;
import org.ensembl.mart.lib.Filter;
import org.ensembl.mart.lib.Query;
import org.ensembl.mart.lib.config.BaseNamedConfigurationObject;
import org.ensembl.mart.lib.config.FilterDescription;
import org.ensembl.mart.lib.config.FilterGroup;
import org.ensembl.mart.lib.config.Option;
import org.ensembl.mart.util.LoggingUtil;
/**
* Represents a list of user options. Some options cause the
* options available in other widgets to be modified. Selecting
* an option causes a Filter to be added to query.
*
*/
public class ListFilterWidget extends FilterWidget implements ActionListener {
private Map filterValueToItem;
private JComboBox list;
private Object lastSelectedItem;
/**
* @param query model to bv synchronised
* @param filterDescription parameters for this widget
*/
public ListFilterWidget(
FilterGroupWidget filterGroupWidget,
Query query,
FilterDescription filterDescription,
QueryTreeView tree) {
super(filterGroupWidget, query, filterDescription, tree);
list = new JComboBox();
list.addActionListener(this);
configureList(list, filterDescription);
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
add(new JLabel(filterDescription.getDisplayName()));
add(Box.createHorizontalStrut(5));
add(list);
}
/**
* Configures the options based on the filterDescription.
* @param list
* @param filterDescription
*/
private void configureList(
JComboBox list,
FilterDescription filterDescription) {
String field = filterDescription.getField();
if (BaseNamedConfigurationObject.isInvalid(field))
throw new IllegalArgumentException(
"Invalid field in filterDescription: "
+ field
+ ", "
+ filterDescription);
setOptions(filterDescription.getOptions());
}
/**
* Attempts to select an item from the list corresponding to the filter.
* @param filter filter to assign, or null if filter is to be removed.
*/
protected void setFilter(Filter filter) {
this.filter = filter;
if (filter == null) {
setSelectedItem(emptySelection);
unassignPushOptions();
} else {
OptionWrapper ow =
(OptionWrapper) filterValueToItem.get(filter.getValue());
setSelectedItem(ow);
assignPushOptions(ow.option.getPushActions());
}
}
/**
* @param emptySelection
*/
private void setSelectedItem(OptionWrapper wrapper) {
list.removeActionListener(this);
list.setSelectedItem(wrapper);
list.addActionListener(this);
}
/**
* Handles user selecting an item from the list.
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
public void actionPerformed(ActionEvent e) {
Object selectedItem = list.getSelectedItem();
if (selectedItem == lastSelectedItem)
return;
unassignPushOptions();
Filter oldFilter = filter;
if (filter != null)
query.removeFilter(filter);
if (selectedItem != emptySelection) {
String value = null;
Option option = ((OptionWrapper) selectedItem).option;
if (option != null) {
String tmp = option.getValue();
if (tmp != null && !"".equals(tmp)) {
value = tmp;
}
if (value != null) {
filter =
new BasicFilter(
filterDescription.getFieldFromContext(),
option.getTableConstraintFromContext(),
option.getKeyFromContext(),
"=",
value);
query.addFilter(filter);
}
assignPushOptions(option.getPushActions());
}
}
lastSelectedItem = selectedItem;
}
/**
* Removes items from list and adds the empty selection to the empty selection.
* @param list list to reset
* @param options array of options to add to list. If null the list is reset to
* contain just the emptySelection entry.
* @return map from option.value to the item in the list it corresponds to.
*/
private Map resetList(JComboBox list, Option[] options) {
Map valueToItem = new HashMap();
// must stop listening otherwise propertyChange() is called fore every change we make
// to the list.
list.removeActionListener(this);
list.removeAllItems();
// make first option be empty
list.addItem(emptySelection);
// Add any options to list
if (options != null && options.length > 0) {
valueToItem = new HashMap();
for (int i = 0; i < options.length; i++) {
Option option = options[i];
if (option.getHidden() != null && option.getHidden().equals("true")) continue;
if (option.getAttribute("hideDisplay") != null && option.getAttribute("hideDisplay").equals("true")) continue;
String value = option.getValue();
String field = option.getField();
if (BaseNamedConfigurationObject.isInvalid(value)
&& BaseNamedConfigurationObject.isInvalid(field))
throw new RuntimeException("Invalid option = " + option);
// add each option, via a surrogate, to the list.
OptionWrapper ow = new OptionWrapper(option);
valueToItem.put(value, ow);
list.addItem(ow);
}
}
list.addActionListener(this);
return valueToItem;
}
/**
* @see org.ensembl.mart.explorer.FilterWidget#setOptions(org.ensembl.mart.lib.config.Option[])
*/
public void setOptions(Option[] options) {
unassignPushOptions();
if ( filter!=null ) query.removeFilter( filter );
filterValueToItem = resetList(list, options);
}
/**
* Test program; a simple GUI using test data.
* @param args
* @throws org.ensembl.mart.lib.config.ConfigurationException
*/
public static void main(String[] args)
throws org.ensembl.mart.lib.config.ConfigurationException {
// switch on logging for test purposes.
LoggingUtil.setAllRootHandlerLevelsToFinest();
Logger.getLogger(Query.class.getName()).setLevel(Level.FINE);
/*
Query q = new Query();
FilterGroup fg = new FilterGroup();
FilterGroupWidget fgw = new FilterGroupWidget(q, "fgw", fg, null);
FilterDescription fd =
new FilterDescription(
"someInternalName",
"someField",
"boolean",
"someQualifier",
"someLegalQualifiers",
"someDisplayName",
"someTableConstraint",
"someKey",
"someDescription",
"",
"","","","","","","");
fd.addOption(
new Option(
"optionInternalName1",
"true",
"displayName1",
"description1",
"field1",
"tableConstraint1",
"key1",
"value1",
"ref1",
"type1",
"qualifier1",
"legalQualifiers1",
"",
"","","","","","",""));
fd.addOption(
new Option(
"optionInternalName2",
"true",
"displayName2",
"description2",
"field2",
"tableConstraint2",
"key2",
"value2",
"ref2",
"type2",
"qualifier2",
"legalQualifiers2",
"",
"","","","","","",""));
// TODO handle "simple" Options.
// Either throw an exception in the following case OR
// use internalID>displayName?
// fd.addOption( new Option("optionInternalName3","true") );
new QuickFrame("List Filter Widget",new ListFilterWidget(fgw, q, fd, null));
*/
}
}