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 && ((JMenuItem) elements[i]).getAction() == a) {
077                    menu.remove(i);
078                    return;
079                }
080            }
081        }
082    }
083
084    /**
085     *  Adds a <code>PopupMenu</code> listener.
086     *
087     *  @param l the <code>PopupMenuListener</code> to add
088     *  @see JPopupMenu#addPopupMenuListener
089     */
090    public void addListener(PopupMenuListener l) {
091        menu.addPopupMenuListener(l);
092    }
093
094    /**
095     * Removes a <code>PopupMenu</code> listener.
096     *
097     * @param l the <code>PopupMenuListener</code> to remove
098     *  @see JPopupMenu#removePopupMenuListener
099     */
100    public void removeListener(PopupMenuListener l) {
101        menu.removePopupMenuListener(l);
102    }
103
104    /**
105     * Returns all enabled primitive actions.
106     * @return All primitive actions that have been added.
107     * @see #addAction(Action)
108     */
109    public Collection<OsmPrimitiveAction> getPrimitiveActions() {
110        return Collections.unmodifiableCollection(primitiveActions);
111    }
112
113    /**
114     * Specifies the working set of primitives for all primitive actions.
115     * @param primitives The new working set of primitives. Can be null or empty
116     * @see OsmPrimitiveAction#setPrimitives
117     */
118    public void setPrimitives(Collection<? extends OsmPrimitive> primitives) {
119        for (OsmPrimitiveAction action : primitiveActions) {
120            action.setPrimitives(primitives);
121        }
122    }
123}