/* 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.logging.Level; import java.util.logging.Logger; import javax.swing.Box; import javax.swing.ButtonGroup; import javax.swing.JComboBox; import javax.swing.JRadioButton; import org.ensembl.mart.guiutils.QuickFrame; import org.ensembl.mart.lib.BooleanFilter; import org.ensembl.mart.lib.Filter; import org.ensembl.mart.lib.Query; 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.lib.config.QueryFilterSettings; import org.ensembl.mart.util.LoggingUtil; /** * A boolean filter widget has a description, an optional list, and three radio buttons; * "require", "ignore", "irrelevant". */ public class BooleanFilterWidget extends FilterWidget implements ActionListener { private String excludeFilterType; private String requireFilterType; private Box panel = Box.createHorizontalBox(); private JRadioButton require = new JRadioButton("require"); private JRadioButton exclude = new JRadioButton("exclude"); private JRadioButton irrelevant = new JRadioButton("irrelevant"); private JComboBox list = null; private ActionListener listSelectionListener = null; private Object lastSelectedComponent = null; private Object lastSelectedListItem = null; /** * @param query * @param filterDescription */ public BooleanFilterWidget( FilterGroupWidget filterGroupWidget, Query query, FilterDescription fd, QueryTreeView tree) { super(filterGroupWidget, query, fd, tree); if ("boolean".equals(fd.getType())) { requireFilterType = BooleanFilter.isNotNULL; excludeFilterType = BooleanFilter.isNULL; } else if ("boolean_num".equals(fd.getType())) { requireFilterType = BooleanFilter.isNotNULL_NUM; excludeFilterType = BooleanFilter.isNULL_NUM; } else if ("boolean_list".equals(fd.getType())) { requireFilterType = BooleanFilter.isNotNULL; excludeFilterType = BooleanFilter.isNULL; list = new JComboBox(); Dimension s = new Dimension( Constants.LIST_MAX_PIXEL_WIDTH, Constants.LIST_MAX_PIXEL_HEIGHT); list.setMaximumSize(s); // we need to set preferred because maximum is ignored by Boxcontainer (at least on JVM1.4@linux) list.setPreferredSize(s); list.setMinimumSize(s); setOptions(fd.getOptions()); } else new RuntimeException( "BooleanFilterWidget does not support filter description: " + fd + " becasue unrecognised type:" + fd.getType()); irrelevant.setSelected(true); lastSelectedComponent = irrelevant; ButtonGroup group = new ButtonGroup(); group.add(require); group.add(exclude); group.add(irrelevant); require.addActionListener(this); exclude.addActionListener(this); irrelevant.addActionListener(this); if (list != null) { Box left = Box.createVerticalBox(); left.add(createLabel()); left.add(list); panel.add(left); //panel.add(list); } else { panel.add(createLabel()); } panel.add(Box.createHorizontalGlue()); panel.add(require); panel.add(exclude); panel.add(irrelevant); add(panel); } /** * Responds to user selecting a button or selecting an item in the list. * * Adds and removes filters to/from query. * * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ public void actionPerformed(ActionEvent evt) { Object src = evt.getSource(); if (src == list) { Object item = list.getSelectedItem(); if (item == lastSelectedListItem) return; lastSelectedListItem = item; } else if (src == lastSelectedComponent) return; lastSelectedComponent = src; // stop listening to the query otherwise we will have changes // we make reflected back to us. query.removeQueryChangeListener(this); Filter newFilter = null; if (src == require || require.isSelected()) newFilter = createFilter(requireFilterType); else if (src == exclude || exclude.isSelected()) newFilter = createFilter(excludeFilterType); else if (src == irrelevant || irrelevant.isSelected()) newFilter = null; if (newFilter == null) { if (filter != null) query.removeFilter(filter); } else { if (filter != null) query.replaceFilter(filter, newFilter); else query.addFilter(newFilter); } filter = newFilter; query.addQueryChangeListener(this); } private Filter createFilter(String filterType) { QueryFilterSettings settings = filterDescription; if (list != null) { settings = ((OptionToStringWrapper) list.getSelectedItem()).option; // The fieldName will change if this is a list fieldName = settings.getFieldFromContext(); tableConstraint = settings.getTableConstraint(); key = settings.getKey(); } return new BooleanFilter( settings.getFieldFromContext(), settings.getTableConstraintFromContext(), settings.getKeyFromContext(), filterType); } public void setOptions(Option[] options) { if (list == null) return; list.removeActionListener(this); list.removeAllItems(); // add items for (int i = 0; i < options.length; i++) { Option o = options[i]; if (o.isSelectable()) list.addItem(new OptionToStringWrapper(this, o)); } list.addActionListener(this); list.validate(); } /** * Selects the button and item in list (if necessary) when filter changed. * This is a callback method called when a filter with the same fieldName * as this widget is added or * removed to/from the query. It is called from * filterAdded(...) and filterRemoved(...) in FilterWidget base class. * */ public void setFilter(Filter filter) { if (filter == null) { irrelevant.setSelected(true); } else { if (list != null) { int index = indexOfListItemMatchingFilter(filter); if (index > -1) { list.removeActionListener(this); list.setSelectedIndex(index); list.addActionListener(this); } } if (filter.getQualifier().equals(requireFilterType)) require.setSelected(true); else if (filter.getQualifier().equals(excludeFilterType)) exclude.setSelected(true); } } /** * 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", "test boolean", "someTableConstraint", "someKey", "someDescription", "", "","","","","","",""); BooleanFilterWidget bfw = new BooleanFilterWidget(fgw, q, fd, null); FilterDescription fd2 = new FilterDescription( "someInternalName", "someField_num", "boolean_num", "someQualifier", "someLegalQualifiers", "test boolean_num ", "someTableConstraint", "someKey", "someDescription", "", "","","","","","",""); BooleanFilterWidget bfw2 = new BooleanFilterWidget(fgw, q, fd2, null); FilterDescription fd3 = new FilterDescription( "someInternalName", "someField_list", "boolean_list", "someQualifier", "someLegalQualifiers", "test boolean_list Onfd3 ", "someTableConstraint Onfd3", "someKey Onfd3", "someDescription", "", "","","","","","",""); Option o = new Option("fred_id", "true"); o.setParent(fd3); o.setDisplayName("Fred"); o.setField("fred_field"); fd3.addOption(o); Option o2 = new Option("barney_id", "true"); o2.setParent(fd3); o2.setDisplayName("Barney"); o2.setField("barney"); fd3.addOption(o2); BooleanFilterWidget bfw3 = new BooleanFilterWidget(fgw, q, fd3, null); Box p = Box.createVerticalBox(); p.add(bfw); p.add(bfw2); p.add(bfw3); new QuickFrame("BooleanFilterWidget test", p); */ } protected boolean equivalentFilter(Object otherFilter) { if (super.equivalentFilter(otherFilter)) return true; if (otherFilter == null || !(otherFilter instanceof Filter)) return false; if (list != null) { if (indexOfListItemMatchingFilter((Filter) otherFilter) > -1) return true; } return false; } /** * * @param otherFilter * @return -1 if filter not relat */ private int indexOfListItemMatchingFilter(Filter filter) { // check that otherFilter does not correspond to one of the list items. final int n = list.getItemCount(); for (int i = 0; i < n; i++) { OptionToStringWrapper op = (OptionToStringWrapper) list.getItemAt(i); Option o = op.option; String f = filter.getField(); String tc = filter.getTableConstraint(); String k = filter.getKey(); if (f != null && tc != null && k != null && !"".equals(f) && !"".equals(k) && !"".equals(tc) && f.equals(o.getFieldFromContext()) && tc.equals(o.getTableConstraintFromContext()) && k.equals(o.getKeyFromContext())) return i; } return -1; } }