001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui;
003
004import java.util.Collection;
005import java.util.Collections;
006import java.util.HashSet;
007import java.util.Set;
008
009import javax.swing.Action;
010import javax.swing.JMenuItem;
011import javax.swing.JPopupMenu;
012import javax.swing.MenuElement;
013import javax.swing.event.PopupMenuListener;
014
015import org.openstreetmap.josm.actions.OsmPrimitiveAction;
016import org.openstreetmap.josm.data.osm.OsmPrimitive;
017
018/**
019 * Handler to ease management of actions in different popup menus.
020 * @since 5821
021 */
022public class PopupMenuHandler {
023
024    // Set of enabled osm primitives actions
025    private final Set<OsmPrimitiveAction> primitiveActions = new HashSet<>();
026    // Managed menu
027    private final JPopupMenu menu;
028
029    /**
030     * Constructs a new {@code RelationActionMenuHandler} for the specified popup menu.
031     *
032     * @param menu The menu to be managed
033     */
034    public PopupMenuHandler(JPopupMenu menu) {
035        this.menu = menu;
036    }
037
038    /**
039     * Appends a new separator at the end of the menu.
040     * @see JPopupMenu#addSeparator
041     */
042    public void addSeparator() {
043        menu.addSeparator();
044    }
045
046    /**
047     * Appends a new menu item to the end of the menu which dispatches the specified <code>Action</code> object.
048     *
049     * @param a the <code>Action</code> to add to the menu
050     * @return the new menu item
051     * @see JPopupMenu#add(Action)
052     */
053    public JMenuItem addAction(Action a) {
054        if (a != null) {
055            if (a instanceof OsmPrimitiveAction) {
056                primitiveActions.add((OsmPrimitiveAction) a);
057            }
058            return menu.add(a);
059        }
060        return null;
061    }
062
063    /**
064     * Removes the menu item which dispatches the specified <code>Action</code> object.
065     *
066     * @param a the <code>Action</code> to remove from the menu
067     * @see JPopupMenu#remove(int)
068     */
069    public void removeAction(Action a) {
070        if (a != null) {
071            if (a instanceof OsmPrimitiveAction) {
072                primitiveActions.remove(a);
073            }
074            MenuElement[] elements = menu.getSubElements();
075            for (int i = 0; i < elements.length; i++) {
076                if (elements[i] instanceof JMenuItem) {
077                    if (((JMenuItem) elements[i]).getAction() == a) {
078                        menu.remove(i);
079                        return;
080                    }
081                }
082            }
083        }
084    }
085
086    /**
087     *  Adds a <code>PopupMenu</code> listener.
088     *
089     *  @param l the <code>PopupMenuListener</code> to add
090     *  @see JPopupMenu#addPopupMenuListener
091     */
092    public void addListener(PopupMenuListener l) {
093        menu.addPopupMenuListener(l);
094    }
095
096    /**
097     * Removes a <code>PopupMenu</code> listener.
098     *
099     * @param l the <code>PopupMenuListener</code> to remove
100     *  @see JPopupMenu#removePopupMenuListener
101     */
102    public void removeListener(PopupMenuListener l) {
103        menu.removePopupMenuListener(l);
104    }
105
106    /**
107     * Returns all enabled primitive actions.
108     * @return All primitive actions that have been added.
109     * @see #addAction(Action)
110     */
111    public Collection<OsmPrimitiveAction> getPrimitiveActions() {
112        return Collections.unmodifiableCollection(primitiveActions);
113    }
114
115    /**
116     * Specifies the working set of primitives for all primitive actions.
117     * @param primitives The new working set of primitives. Can be null or empty
118     * @see OsmPrimitiveAction#setPrimitives
119     */
120    public void setPrimitives(Collection<? extends OsmPrimitive> primitives) {
121        for (OsmPrimitiveAction action : primitiveActions) {
122            action.setPrimitives(primitives);
123        }
124    }
125}