/******************************************************************************* * Mission Control Technologies, Copyright (c) 2009-2012, United States Government * as represented by the Administrator of the National Aeronautics and Space * Administration. All rights reserved. * The MCT platform is 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. * * MCT includes source code licensed under additional open source licenses. See * the MCT Open Source Licenses file included with this distribution or the About * MCT Licenses dialog available at runtime from the MCT Help menu for additional * information. *******************************************************************************/ package gov.nasa.arc.mct.dbpersistence.search; import gov.nasa.arc.mct.components.AbstractComponent; import gov.nasa.arc.mct.dbpersistence.access.InternalDBPersistenceAccess; import gov.nasa.arc.mct.dbpersistence.dao.ComponentSpec; import gov.nasa.arc.mct.gui.SelectionProvider; import gov.nasa.arc.mct.gui.View; import gov.nasa.arc.mct.gui.ViewRoleSelection; import gov.nasa.arc.mct.platform.spi.PlatformAccess; import gov.nasa.arc.mct.services.component.ViewType; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.awt.GridLayout; import java.awt.datatransfer.Transferable; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Properties; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicInteger; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.DefaultListCellRenderer; import javax.swing.DefaultListModel; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.ListSelectionModel; import javax.swing.SwingWorker; import javax.swing.TransferHandler; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; @SuppressWarnings("serial") public class DatabaseSearchUI extends JPanel implements SelectionProvider { // private final static ResourceBundle bundle = ResourceBundle.getBundle("Platform"); //NOI18N private static final int PADDING = 5; private JTextField baseDisplayedNameField; private DefaultListModel listModel = new DefaultListModel(); private JList list; private JButton goButton; private JLabel resultStatus; private JCheckBox findObjectsCreatedByMe; public DatabaseSearchUI() { setLayout(new BorderLayout()); JPanel displayNamePanel = new JPanel(new BorderLayout()); JLabel displayNameLabel = new JLabel("Base Displayed Name:"); baseDisplayedNameField = new JTextField(); baseDisplayedNameField.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (goButton.isEnabled()) goButton.doClick(); } }); displayNameLabel.setLabelFor(baseDisplayedNameField); displayNamePanel.add(baseDisplayedNameField, BorderLayout.CENTER); displayNamePanel.add(displayNameLabel, BorderLayout.WEST); goButton = new JButton(); String searchButtonText = "Search";//bundle.getString("SEARCH_BUTTON"); goButton.getAccessibleContext().setAccessibleName(searchButtonText); goButton.setAction(new AbstractAction(searchButtonText) { @Override public void actionPerformed(ActionEvent e) { goButton.setEnabled(false); SearchTask task = new SearchTask(); listModel.removeAllElements(); resultStatus.setText(null); task.execute(); } }); JPanel displayNameAndGoPanel = new JPanel(new BorderLayout()); displayNameAndGoPanel.add(displayNamePanel, BorderLayout.CENTER); displayNameAndGoPanel.add(goButton, BorderLayout.EAST); listModel = new DefaultListModel(); list = new JList(listModel); list.getAccessibleContext().setAccessibleName("Search Result List"); list.setCellRenderer(new DefaultListCellRenderer() { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { ComponentInfo ci = (ComponentInfo) value; JLabel label = (JLabel) super.getListCellRendererComponent(list, ci.name, index, isSelected, cellHasFocus); label.setIcon(getIconForComponentType(ci.type)); return label; } }); list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); list.addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { if (!e.getValueIsAdjusting()) { Collection<View> selectedManifestations = getSelectedManifestations(); if (!selectedManifestations.isEmpty()) { firePropertyChange(SelectionProvider.SELECTION_CHANGED_PROP, null, selectedManifestations); } // end if } // end if } }); list.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { Collection<View> selectedManifestations = getSelectedManifestations(); if (selectedManifestations.isEmpty()) return; View manifestation = selectedManifestations.iterator().next(); if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) { manifestation.getManifestedComponent().open(); return; } } }); list.setDragEnabled(true); list.setTransferHandler(new TransferHandler() { @Override protected Transferable createTransferable(JComponent c) { List<View> viewRoles = new ArrayList<View>(); Collection<View> selectedManifestations = getSelectedManifestations(); if (!selectedManifestations.isEmpty()) { for (View manifestation : getSelectedManifestations()) viewRoles.add(manifestation); return new ViewRoleSelection(viewRoles.toArray(new View[viewRoles.size()])); } else { return null; } // end if } @Override public int getSourceActions(JComponent c) { return TransferHandler.COPY; } }); JPanel controlPanel = new JPanel(new GridLayout(2, 1, 5, 5)); controlPanel.add(displayNameAndGoPanel); findObjectsCreatedByMe = new JCheckBox("Created By Me"); controlPanel.add(findObjectsCreatedByMe); JPanel descriptionPanel = new JPanel(new GridLayout(2, 1)); JLabel searchEverywhereLabel = new JLabel("Search everywhere"); searchEverywhereLabel.setFont(searchEverywhereLabel.getFont().deriveFont(Font.BOLD)); resultStatus = new JLabel(); resultStatus.setForeground(Color.BLUE); descriptionPanel.add(searchEverywhereLabel); descriptionPanel.add(resultStatus); JPanel upperPanel = new JPanel(new BorderLayout(PADDING, PADDING)); upperPanel.setBorder(BorderFactory.createEmptyBorder(PADDING, PADDING, PADDING, PADDING)); upperPanel.add(descriptionPanel, BorderLayout.NORTH); upperPanel.add(controlPanel, BorderLayout.CENTER); add(upperPanel, BorderLayout.NORTH); add(new JScrollPane(list), BorderLayout.CENTER); } QueryResult search(String pattern, boolean isFindObjectsCreatedByMe) { Properties props = new Properties(); if (isFindObjectsCreatedByMe) props.setProperty("creator", PlatformAccess.getPlatform().getCurrentUser().getUserId()); return InternalDBPersistenceAccess.getService().findComponentsByBaseDisplayedNamePattern(pattern, props); } private ImageIcon getIconForComponentType(String type) { AbstractComponent iconInstance = PlatformAccess.getPlatform().getComponentRegistry().newInstance(type); return iconInstance == null ? null : iconInstance.getAsset(ImageIcon.class); } private class SearchTask extends SwingWorker<List<ComponentInfo>, Void> { private AtomicInteger total = new AtomicInteger(); public SearchTask() { } @Override protected List<ComponentInfo> doInBackground() throws Exception { String displayNamePattern = baseDisplayedNameField.getText().trim(); List<ComponentInfo> list = new ArrayList<DatabaseSearchUI.ComponentInfo>(); QueryResult queryResult = search(displayNamePattern, findObjectsCreatedByMe.isSelected()); @SuppressWarnings("unchecked") List<ComponentSpec> daoObjects = (List<ComponentSpec>) queryResult.getRecords(); for (ComponentSpec cs : daoObjects) { ComponentInfo ci = new ComponentInfo(cs.getComponentId(), cs.getComponentName(), cs.getComponentType()); list.add(ci); } total.set(queryResult.getCount()); return list; } @Override public void done() { try { for (ComponentInfo ci : get()) { listModel.addElement(ci); } resultStatus.setText("Search Results: " + listModel.size() + " out of " + total.get()); } catch (InterruptedException e) { listModel.removeAllElements(); } catch (ExecutionException e) { listModel.removeAllElements(); } finally { goButton.setEnabled(true); } } } @Override public String getName() { return "Search Name"; } @Override public void addSelectionChangeListener(PropertyChangeListener listener) { addPropertyChangeListener(SelectionProvider.SELECTION_CHANGED_PROP, listener); } @Override public void removeSelectionChangeListener(PropertyChangeListener listener) { removePropertyChangeListener(SelectionProvider.SELECTION_CHANGED_PROP, listener); } //Harleigh108: this removes the warning received when we build with respect to java 7; getSelectedValues is now Deprecated in java7 //from java7 javadocs (for JList) 'As of JDK 1.7, replaced by getSelectedValuesList()' //Note: we suppress this warning to stay compatible with java6 @SuppressWarnings("deprecation") @Override public Collection<View> getSelectedManifestations() { Object[] selectedValues = list.getSelectedValues(); if (selectedValues == null || selectedValues.length == 0) return Collections.emptySet(); Collection<View> manifestations = new ArrayList<View>(); for (Object value : selectedValues) { ComponentInfo ci = (ComponentInfo) value; AbstractComponent component = AbstractComponent.getComponentById(ci.id); // JIRA 3809 - rvanhoof - Fix NPE when component was deleted from another view if (component != null) { manifestations.add(component.getViewInfos(ViewType.NODE).iterator().next().createView(component)); } // end if } return manifestations; } @Override public void clearCurrentSelections() { list.clearSelection(); } private static class ComponentInfo { public ComponentInfo(String id, String name, String type) { this.id = id; this.name = name; this.type = type; } private String id; private String name; private String type; } }