/* * Copyright [1999-2015] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute * Copyright [2016-2017] EMBL-European Bioinformatics Institute * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.ensembl.healthcheck.eg_gui; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.ensembl.healthcheck.DatabaseRegistry; import org.ensembl.healthcheck.DatabaseRegistryEntry; import org.ensembl.healthcheck.DatabaseType; import org.ensembl.healthcheck.eg_gui.DatabaseListPanel; import org.ensembl.healthcheck.eg_gui.DatabaseRadioButton; import org.ensembl.healthcheck.eg_gui.DatabaseTypeGUIComparator; import org.ensembl.healthcheck.eg_gui.TabChangeListener; /** * <p> * A class that extends JTabbedPane and provides a method for getting all the selected databases. * Also highlights currently-selected tab. * </p> * */ public class DatabaseTabbedPane extends JTabbedPane implements ActionListener { protected DatabaseRegistry databaseRegistry; protected final List<ActionListener> actionListener; /** * Updated automatically to always hold the currently selected DbButton. */ protected DatabaseRadioButton selectedDbButton; public DatabaseRadioButton getSelectedDbButton() { return selectedDbButton; } public void addActionListener(ActionListener l) { actionListener.add(l); } protected void fireActionEvent(ActionEvent actionEvent) { for(ActionListener currentActionListener : actionListener) { currentActionListener.actionPerformed(actionEvent); } } @Override public void actionPerformed(ActionEvent arg0) { String cmd = arg0.getActionCommand(); if (cmd.equals(Constants.selectedDatabaseChanged)) { selectedDbButton = (DatabaseRadioButton) arg0.getSource(); ActionEvent actionEvent = new ActionEvent( this, arg0.getID() +1, Constants.selectedDatabaseChanged ); fireActionEvent(actionEvent); } } /** * * <p> * Creates a map that maps a DatabaseRegistryEntry to the JRadioButton * that will represent for selection in the gui. * </p> * * @param allDbEntries * @return Map<DatabaseRegistryEntry, JRadioButton> * */ protected Map<DatabaseRegistryEntry, DatabaseRadioButton> createRadioButtonsForDb(DatabaseRegistryEntry[] allDbEntries) { Map<DatabaseRegistryEntry, DatabaseRadioButton> checkBoxMap = new HashMap<DatabaseRegistryEntry, DatabaseRadioButton>(); for (DatabaseRegistryEntry currentEntry : allDbEntries) { DatabaseRadioButton dbcb = new DatabaseRadioButton(currentEntry, false); dbcb.addActionListener(this); dbcb.setActionCommand(Constants.selectedDatabaseChanged); checkBoxMap.put(currentEntry, dbcb); } return checkBoxMap; } /** * * <p> * Searches through an array of allDbEntries and creates a list of * DatabaseRegistryEntry with the specified filterForType. * </p> * * @param allDbEntries * @param filterForType * @return * */ private List<DatabaseRegistryEntry> filterForDbsOfType(DatabaseRegistryEntry[] allDbEntries, DatabaseType filterForType) { List<DatabaseRegistryEntry> dbRegistryEntryWithOfType = new ArrayList<DatabaseRegistryEntry>(); for (DatabaseRegistryEntry currentEntry : allDbEntries) { if (currentEntry.getType() == filterForType) { dbRegistryEntryWithOfType.add(currentEntry); } } return dbRegistryEntryWithOfType; } /** * * <p> * Creates the database tabbed pane from which the user can select the * database on which he wants to run his tests. * </p> * * @param databaseRegistry * */ public DatabaseTabbedPane(DatabaseRegistry databaseRegistry) { this.databaseRegistry = databaseRegistry; actionListener = new LinkedList<ActionListener>(); init(); } public DatabaseTabbedPane( DatabaseRegistry databaseRegistry, ActionListener radioActionListener ) { this(databaseRegistry); this.addActionListener(radioActionListener); } public void setMessage(String caption, String message) { this.removeAll(); addTab(caption, new JLabel(message)); } public void init(DatabaseRegistry databaseRegistry) { this.databaseRegistry = databaseRegistry; init(); } public synchronized void init() { this.removeAll(); selectedDbButton = null; DatabaseRegistryEntry[] allDbEntries = databaseRegistry.getAll(); if (allDbEntries.length==0) { addTab( "Problem", new JLabel("No databases available.") ); } Map<DatabaseRegistryEntry, DatabaseRadioButton> checkBoxMap = createRadioButtonsForDb(allDbEntries); DatabaseType[] types = databaseRegistry.getTypes(); Arrays.sort(types, new DatabaseTypeGUIComparator()); // One Buttongroup for all radio buttons across all the database // tabs. // ButtonGroup myOneAndOnlyButtonGroup = new ButtonGroup(); for (DatabaseType currentDbType : types) { // Create a list of databases on the server with the currentDbType. // List<DatabaseRegistryEntry> dbsOnServerWithThisType = filterForDbsOfType( databaseRegistry.getAll(), currentDbType ); // Create Radiobuttons for them for the user to select. // List<DatabaseRadioButton> checkBoxesTabForCurrentType = new ArrayList<DatabaseRadioButton>(); for (DatabaseRegistryEntry currentEntry : dbsOnServerWithThisType) { checkBoxesTabForCurrentType.add(checkBoxMap.get(currentEntry)); } addTab( currentDbType.toString(), new DatabaseListPanel(checkBoxesTabForCurrentType, myOneAndOnlyButtonGroup) ); } addChangeListener(new TabChangeListener()); if (getTabCount()>0) { setEnabledAt(0, true); } } public void applySearchtermFilter(List<String> SearchTerm) { int index = this.getSelectedIndex(); // Returns a JLabel when the JTabbedPane is not fully initialised yet. // Object careful = this.getComponentAt(index); if (!(careful instanceof DatabaseListPanel)) { return; } DatabaseListPanel p = (DatabaseListPanel) careful; if (p!=null) { p.applySearchtermFilter(SearchTerm); } } // ------------------------------------------------------------------------- public DatabaseRegistryEntry[] getSelectedDatabases() { return new DatabaseRegistryEntry[] { getSelectedDbButton().getDatabase() }; // List result = new ArrayList(); // // // get all the selected databases for each tab in turn // for (int i = 0; i < getTabCount(); i++) { // // DatabaseListPanel dblp = (DatabaseListPanel) getComponentAt(i); // DatabaseRegistryEntry[] panelSelected = dblp.getSelected(); // for (int j = 0; j < panelSelected.length; j++) { // result.add(panelSelected[j]); // } // } // // return (DatabaseRegistryEntry[]) result.toArray(new DatabaseRegistryEntry[result.size()]); } // getSelectedDatabases // ------------------------------------------------------------------------- } // DatabaseTabbedPane /** * <p> * A JRadioButton with a reference to a DatabaseRegistryEntry. * </p> * */ class DatabaseRadioButton extends JRadioButton { private DatabaseRegistryEntry database; public DatabaseRadioButton(DatabaseRegistryEntry database, boolean selected) { super(database.getName(), selected); this.database = database; } public DatabaseRegistryEntry getDatabase() { return database; } public void setDatabase(DatabaseRegistryEntry database) { this.database = database; } } /** * * <p> * A class that creates a panel (in a JScrollPane) containing a list of * DatabaseRadioButton, and provides methods for accessing the selected ones. * </p> * */ class DatabaseListPanel extends JScrollPane { private List<DatabaseRadioButton> dbSelectionRadioButtons; private final ButtonGroup buttonGroup; /** * * <p> * This constructor allows the user to set a ButtonGroup explicitly. That * way the same ButtonGroup can be used * </p> * * @param dbSelectionRadioButtons * @param buttonGroup * */ public DatabaseListPanel(List<DatabaseRadioButton> dbSelectionRadioButtons, ButtonGroup buttonGroup) { this.dbSelectionRadioButtons = dbSelectionRadioButtons; this.buttonGroup = buttonGroup; Iterator<DatabaseRadioButton> it = dbSelectionRadioButtons.iterator(); JPanel radioButtonPanel = new JPanel(); radioButtonPanel.setLayout(new BoxLayout(radioButtonPanel, BoxLayout.Y_AXIS)); while (it.hasNext()) { DatabaseRadioButton currentDatabaseRadioButton = it.next(); radioButtonPanel.add(currentDatabaseRadioButton); buttonGroup .add(currentDatabaseRadioButton); } setViewportView(radioButtonPanel); } public void applySearchtermFilter(List<String> SearchTerm) { Iterator<DatabaseRadioButton> it = dbSelectionRadioButtons.iterator(); while (it.hasNext()) { DatabaseRadioButton currentDatabaseRadioButton = it.next(); boolean allSearchTermsPresent = true; for (String currentSearchTerm : SearchTerm) { boolean searchTermNotFound = currentDatabaseRadioButton.getDatabase().getName().indexOf(currentSearchTerm)==-1; if (searchTermNotFound) { allSearchTermsPresent = false; break; } } currentDatabaseRadioButton.setVisible(allSearchTermsPresent); } } /** * <p> * Default Constructor. * </p> * * @param dbSelectionRadioButtons * */ public DatabaseListPanel(List<DatabaseRadioButton> dbSelectionRadioButtons) { this(dbSelectionRadioButtons, new ButtonGroup()); } // ------------------------------------------------------------------------- /** * Get the databases that are selected on this panel. * * @return the selected databases. */ public DatabaseRegistryEntry[] getSelected() { List selected = new ArrayList(); Iterator it = dbSelectionRadioButtons.iterator(); while (it.hasNext()) { DatabaseRadioButton dbcb = (DatabaseRadioButton) it.next(); if (dbcb.isSelected()) { selected.add(dbcb.getDatabase()); } } return (DatabaseRegistryEntry[]) selected.toArray(new DatabaseRegistryEntry[selected.size()]); } } /** * <p> * Fiddle things so that generic database types are moved to the front. * </p> */ class DatabaseTypeGUIComparator implements Comparator { public int compare(Object o1, Object o2) { if (!(o1 instanceof DatabaseType) || !(o2 instanceof DatabaseType)) { throw new RuntimeException("Arguments to DatabaseTypeGUIComparator must be DatabaseType!"); } DatabaseType t1 = (DatabaseType) o1; DatabaseType t2 = (DatabaseType) o2; if (t1.isGeneric() && !t2.isGeneric()) { return -1; } else if (!t1.isGeneric() && t2.isGeneric()) { return 1; } else { return t1.toString().compareTo(t2.toString()); } } } /** * Highlight the currently-selected tab of a JTabbedPane. */ class TabChangeListener implements ChangeListener { public void stateChanged(ChangeEvent e) {} }