001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.dialogs;
003
004import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
005import static org.openstreetmap.josm.tools.I18n.tr;
006
007import java.awt.Component;
008import java.awt.Dimension;
009import java.awt.event.ActionEvent;
010import java.util.ArrayList;
011import java.util.Arrays;
012import java.util.List;
013
014import javax.swing.AbstractAction;
015import javax.swing.Action;
016import javax.swing.JMenuItem;
017import javax.swing.JOptionPane;
018import javax.swing.JPopupMenu;
019
020import org.openstreetmap.josm.Main;
021import org.openstreetmap.josm.gui.ExtendedDialog;
022import org.openstreetmap.josm.gui.layer.Layer;
023import org.openstreetmap.josm.gui.layer.Layer.LayerAction;
024import org.openstreetmap.josm.gui.layer.Layer.MultiLayerAction;
025import org.openstreetmap.josm.gui.layer.Layer.SeparatorLayerAction;
026import org.openstreetmap.josm.tools.ImageProvider;
027
028/**
029 * Popup menu handler for the layer list.
030 */
031public class LayerListPopup extends JPopupMenu {
032
033    public static final class InfoAction extends AbstractAction {
034        private final transient Layer layer;
035
036        /**
037         * Constructs a new {@code InfoAction} for the given layer.
038         * @param layer The layer
039         */
040        public InfoAction(Layer layer) {
041            super(tr("Info"), ImageProvider.get("info"));
042            putValue("help", ht("/Action/LayerInfo"));
043            this.layer = layer;
044        }
045
046        @Override
047        public void actionPerformed(ActionEvent e) {
048            Object object = layer.getInfoComponent();
049            if (object instanceof Component) {
050                ExtendedDialog ed = new ExtendedDialog(
051                        Main.parent, tr("Information about layer"),
052                        new String[] {tr("OK")});
053                ed.setButtonIcons(new String[] {"ok"});
054                ed.setIcon(JOptionPane.INFORMATION_MESSAGE);
055                ed.setContent((Component) object);
056                ed.setResizable(layer.isInfoResizable());
057                ed.setMinimumSize(new Dimension(270, 170));
058                ed.showDialog();
059            } else {
060                JOptionPane.showMessageDialog(
061                        Main.parent, object,
062                        tr("Information about layer"),
063                        JOptionPane.INFORMATION_MESSAGE
064                        );
065            }
066        }
067    }
068
069    /**
070     * Constructs a new {@code LayerListPopup}.
071     * @param selectedLayers list of selected layers
072     */
073    public LayerListPopup(List<Layer> selectedLayers) {
074
075        List<Action> actions;
076        if (selectedLayers.size() == 1) {
077            actions = Arrays.asList(selectedLayers.get(0).getMenuEntries());
078        } else {
079            // Very simple algorithm - first selected layer has actions order as in getMenuEntries, actions from other layers go to the end
080            actions = new ArrayList<>();
081            boolean separatorAdded = true;
082            for (Action a: selectedLayers.get(0).getMenuEntries()) {
083                if (!separatorAdded && a instanceof SeparatorLayerAction) {
084                    separatorAdded = true;
085                    actions.add(a);
086                } else if (a instanceof LayerAction && ((LayerAction) a).supportLayers(selectedLayers)) {
087                    separatorAdded = false;
088                    if (a instanceof MultiLayerAction)
089                        a = ((MultiLayerAction) a).getMultiLayerAction(selectedLayers);
090                    actions.add(a);
091                }
092            }
093            // This will usually add no action, because if some action support all selected layers then it was probably used also in first layer
094            for (int i = 1; i < selectedLayers.size(); i++) {
095                separatorAdded = false;
096                for (Action a: selectedLayers.get(i).getMenuEntries()) {
097                    if (a instanceof LayerAction && !(a instanceof MultiLayerAction)
098                    && ((LayerAction) a).supportLayers(selectedLayers) && !actions.contains(a)) {
099                        if (!separatorAdded) {
100                            separatorAdded = true;
101                            actions.add(SeparatorLayerAction.INSTANCE);
102                        }
103                        actions.add(a);
104                    }
105                }
106            }
107        }
108        if (!actions.isEmpty() && actions.get(actions.size() - 1) instanceof SeparatorLayerAction) {
109            actions.remove(actions.size() - 1);
110        }
111        for (Action a : actions) {
112            if (a instanceof LayerAction) {
113                add(((LayerAction) a).createMenuComponent());
114            } else {
115                add(new JMenuItem(a));
116            }
117        }
118    }
119}