/* * org.openmicroscopy.shoola.util.ui.search.SearchContextMenu * *------------------------------------------------------------------------------ * Copyright (C) 2006-2014 University of Dundee. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *------------------------------------------------------------------------------ */ package org.openmicroscopy.shoola.util.ui.search; //Java imports import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.swing.ButtonGroup; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.JSeparator; //Third-party libraries //Application-internal dependencies /** * Popup menu displaying the possible context of a search. * * @author Jean-Marie Burel      * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @author Donald MacDonald      * <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a> * @version 3.0 * <small> * (<b>Internal version:</b> $Revision: $Date: $) * </small> * @since OME3.0 */ public class SearchContextMenu extends JPopupMenu implements ActionListener { /** Bound property indicating that a new item is selected. */ public static final String SEARCH_CONTEXT_PROPERTY = "searchContext"; /** The width of the component. */ private int width; /** The type of node to create. */ private Class type; /** Collections of UI nodes hosting the <code>SearchObject</code>s. */ private List items; private ButtonGroup group; /** * Builds and lays out the UI. * * @param nodes The context nodes to lay out. * @param ratedNodes The rated nodes if any. * @param selectedNode The default selected node. * @param singleSelection Pass <code>true</code> if only one context can * be selected at a time to <code>false</code> * otherwise. */ private void buildGUI(List<SearchObject> nodes, List<SearchObject> ratedNodes, SearchObject selectedNode, boolean singleSelection) { Iterator i; group = new ButtonGroup(); SearchObject node; if (type.equals(NodeRadioMenuItem.class)) { NodeRadioMenuItem uiNode; int index = -1; if (selectedNode != null) index = selectedNode.getIndex(); i = ratedNodes.iterator(); while (i.hasNext()) { node = (SearchObject) i.next(); uiNode = new NodeRadioMenuItem(node); if (node.getIndex() == index) uiNode.setSelected(true); uiNode.addActionListener(this); add(uiNode); items.add(uiNode); if (singleSelection) group.add(uiNode); } if (ratedNodes.size() > 0) add(new JSeparator()); i = nodes.iterator(); while (i.hasNext()) { node = (SearchObject) i.next(); uiNode = new NodeRadioMenuItem(node); if (node.getIndex() == index) uiNode.setSelected(true); uiNode.addActionListener(this); add(uiNode); items.add(uiNode); if (singleSelection) group.add(uiNode); } } else if (type.equals(NodeCheckMenuItem.class)) { NodeCheckMenuItem uiNode; int index = -1; if (selectedNode != null) index = selectedNode.getIndex(); i = ratedNodes.iterator(); while (i.hasNext()) { node = (SearchObject) i.next(); uiNode = new NodeCheckMenuItem(node); if (node.getIndex() == index) uiNode.setSelected(true); uiNode.addActionListener(this); add(uiNode); items.add(uiNode); if (singleSelection) group.add(uiNode); } if (ratedNodes.size() > 0) add(new JSeparator()); i = nodes.iterator(); while (i.hasNext()) { node = (SearchObject) i.next(); uiNode = new NodeCheckMenuItem(node); if (node.getIndex() == index) uiNode.setSelected(true); uiNode.addActionListener(this); add(uiNode); items.add(uiNode); if (singleSelection) group.add(uiNode); } } else { NodeMenuItem uiNode; i = ratedNodes.iterator(); while (i.hasNext()) { node = (SearchObject) i.next(); uiNode = new NodeMenuItem(node); uiNode.addActionListener(this); items.add(uiNode); add(uiNode); } if (ratedNodes.size() > 0) add(new JSeparator()); i = nodes.iterator(); while (i.hasNext()) { node = (SearchObject) i.next(); uiNode = new NodeMenuItem(node); uiNode.addActionListener(this); add(uiNode); items.add(uiNode); } } int n = nodes.size()+ratedNodes.size(); int height = getFontMetrics(getFont()).getHeight()*n+10; setPopupSize(new Dimension(width, height)); } /** * Creates a new instance. * * @param nodes The context nodes. * @param ratedNodes The rated nodes if any. * @param width The popup width. * @param singleSelection Pass <code>true</code> if only one context can * be selected at a time to <code>false</code> * otherwise. */ public SearchContextMenu(List<SearchObject> nodes, List<SearchObject> ratedNodes, int width, boolean singleSelection) { this(nodes, ratedNodes, width, NodeMenuItem.class, null, singleSelection); } /** * Creates a new instance. * * @param nodes The context nodes. * @param ratedNodes The rated nodes if any. * @param width The pop-up width. * @param selectedNode The default selected node. * @param singleSelection Pass <code>true</code> if only one context can * be selected at a time to <code>false</code> * otherwise. */ public SearchContextMenu(List<SearchObject> nodes, List<SearchObject> ratedNodes, int width, SearchObject selectedNode, boolean singleSelection) { this(nodes, ratedNodes, width, NodeRadioMenuItem.class, selectedNode, singleSelection); } /** * Creates a new instance. * * @param nodes The context nodes. * @param ratedNodes The rated nodes if any. * @param width The pop-up width. * @param type The type of item to create. * @param selectedNode The default selected node. * @param singleSelection Pass <code>true</code> if only one context can * be selected at a time to <code>false</code> * otherwise. */ SearchContextMenu(List<SearchObject> nodes, List<SearchObject> ratedNodes, int width, Class type, SearchObject selectedNode, boolean singleSelection) { this.type = type; this.width = width; items = new ArrayList(); buildGUI(nodes, ratedNodes, selectedNode, singleSelection); } /** * Selects the UI node corresponding to the passed * <code>SearchObject</code>. * * @param node The <code>SearchObject</code> to handle. */ public void setSelectedNode(SearchObject node) { if(node==null) { group.clearSelection(); } else { Iterator i = items.iterator(); Object uiNode; NodeMenuItem nmItem; NodeCheckMenuItem ncmItem; NodeRadioMenuItem rItem; while (i.hasNext()) { uiNode = i.next(); if (uiNode instanceof NodeMenuItem) { nmItem = (NodeMenuItem) uiNode; if (nmItem.getSearchObject().getIndex() == node.getIndex()) { nmItem.removeActionListener(this); nmItem.setSelected(true); nmItem.addActionListener(this); } } else if (uiNode instanceof NodeCheckMenuItem) { ncmItem = (NodeCheckMenuItem) uiNode; if (ncmItem.getSearchObject().getIndex() == node.getIndex()) { ncmItem.removeActionListener(this); ncmItem.setSelected(true); ncmItem.addActionListener(this); } } else if (uiNode instanceof NodeRadioMenuItem) { rItem = (NodeRadioMenuItem) uiNode; if (rItem.getSearchObject().getIndex() == node.getIndex()) { rItem.removeActionListener(this); rItem.setSelected(true); rItem.addActionListener(this); } } } } } /** * Fires a property change when a new menu item is selected. * @see ActionListener#actionPerformed(ActionEvent) */ public void actionPerformed(ActionEvent e) { Object src = e.getSource(); if (src instanceof NodeMenuItem) { NodeMenuItem item = (NodeMenuItem) src; firePropertyChange(SEARCH_CONTEXT_PROPERTY, null, item.getSearchObject()); } else if (src instanceof NodeCheckMenuItem) { NodeCheckMenuItem item = (NodeCheckMenuItem) src; firePropertyChange(SEARCH_CONTEXT_PROPERTY, null, item.getSearchObject()); } else if (src instanceof NodeRadioMenuItem) { NodeRadioMenuItem item = (NodeRadioMenuItem) src; firePropertyChange(SEARCH_CONTEXT_PROPERTY, null, item.getSearchObject()); } } }