| 1 | // License: GPL. For details, see LICENSE file.
|
|---|
| 2 | package org.openstreetmap.josm.gui.dialogs;
|
|---|
| 3 |
|
|---|
| 4 | import static java.util.Collections.emptyList;
|
|---|
| 5 | import static java.util.stream.Collectors.toCollection;
|
|---|
| 6 | import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
|
|---|
| 7 | import static org.openstreetmap.josm.tools.I18n.tr;
|
|---|
| 8 |
|
|---|
| 9 | import java.awt.Component;
|
|---|
| 10 | import java.awt.Dimension;
|
|---|
| 11 | import java.awt.event.ActionEvent;
|
|---|
| 12 | import java.util.ArrayList;
|
|---|
| 13 | import java.util.List;
|
|---|
| 14 | import java.util.stream.Stream;
|
|---|
| 15 |
|
|---|
| 16 | import javax.swing.AbstractAction;
|
|---|
| 17 | import javax.swing.Action;
|
|---|
| 18 | import javax.swing.JMenuItem;
|
|---|
| 19 | import javax.swing.JOptionPane;
|
|---|
| 20 | import javax.swing.JPopupMenu;
|
|---|
| 21 |
|
|---|
| 22 | import org.openstreetmap.josm.gui.ExtendedDialog;
|
|---|
| 23 | import org.openstreetmap.josm.gui.MainApplication;
|
|---|
| 24 | import org.openstreetmap.josm.gui.layer.Layer;
|
|---|
| 25 | import org.openstreetmap.josm.gui.layer.Layer.LayerAction;
|
|---|
| 26 | import org.openstreetmap.josm.gui.layer.Layer.MultiLayerAction;
|
|---|
| 27 | import org.openstreetmap.josm.gui.layer.Layer.SeparatorLayerAction;
|
|---|
| 28 | import org.openstreetmap.josm.tools.ImageProvider;
|
|---|
| 29 |
|
|---|
| 30 | /**
|
|---|
| 31 | * Popup menu handler for the layer list.
|
|---|
| 32 | */
|
|---|
| 33 | public class LayerListPopup extends JPopupMenu {
|
|---|
| 34 |
|
|---|
| 35 | /**
|
|---|
| 36 | * An action that displays the layer information.
|
|---|
| 37 | * @see Layer#getInfoComponent()
|
|---|
| 38 | */
|
|---|
| 39 | public static final class InfoAction extends AbstractAction {
|
|---|
| 40 | private final transient Layer layer;
|
|---|
| 41 |
|
|---|
| 42 | /**
|
|---|
| 43 | * Constructs a new {@code InfoAction} for the given layer.
|
|---|
| 44 | * @param layer The layer
|
|---|
| 45 | */
|
|---|
| 46 | public InfoAction(Layer layer) {
|
|---|
| 47 | super(tr("Info"));
|
|---|
| 48 | new ImageProvider("info").getResource().attachImageIcon(this, true);
|
|---|
| 49 | putValue("help", ht("/Action/LayerInfo"));
|
|---|
| 50 | this.layer = layer;
|
|---|
| 51 | }
|
|---|
| 52 |
|
|---|
| 53 | @Override
|
|---|
| 54 | public void actionPerformed(ActionEvent e) {
|
|---|
| 55 | Object object = layer.getInfoComponent();
|
|---|
| 56 | if (object instanceof Component) {
|
|---|
| 57 | ExtendedDialog ed = new ExtendedDialog(
|
|---|
| 58 | MainApplication.getMainFrame(), tr("Information about layer"),
|
|---|
| 59 | tr("OK"));
|
|---|
| 60 | ed.setButtonIcons("ok");
|
|---|
| 61 | ed.setIcon(JOptionPane.INFORMATION_MESSAGE);
|
|---|
| 62 | ed.setContent((Component) object);
|
|---|
| 63 | ed.setResizable(layer.isInfoResizable());
|
|---|
| 64 | ed.setMinimumSize(new Dimension(270, 170));
|
|---|
| 65 | ed.showDialog();
|
|---|
| 66 | } else {
|
|---|
| 67 | JOptionPane.showMessageDialog(
|
|---|
| 68 | MainApplication.getMainFrame(), object,
|
|---|
| 69 | tr("Information about layer"),
|
|---|
| 70 | JOptionPane.INFORMATION_MESSAGE
|
|---|
| 71 | );
|
|---|
| 72 | }
|
|---|
| 73 | }
|
|---|
| 74 | }
|
|---|
| 75 |
|
|---|
| 76 | /**
|
|---|
| 77 | * Constructs a new {@code LayerListPopup}.
|
|---|
| 78 | * @param selectedLayers list of selected layers
|
|---|
| 79 | */
|
|---|
| 80 | public LayerListPopup(List<Layer> selectedLayers) {
|
|---|
| 81 |
|
|---|
| 82 | List<Action> actions;
|
|---|
| 83 | if (selectedLayers.size() == 1) {
|
|---|
| 84 | Action[] entries = selectedLayers.get(0).getMenuEntries();
|
|---|
| 85 | // Since we may add to the array later, we cannot use Arrays.asList -- it prohibits the use of `add` or `remove`.
|
|---|
| 86 | actions = entries != null ? Stream.of(entries).collect(toCollection(ArrayList::new)) : emptyList();
|
|---|
| 87 | } else {
|
|---|
| 88 | // Very simple algorithm - first selected layer has actions order as in getMenuEntries, actions from other layers go to the end
|
|---|
| 89 | actions = new ArrayList<>();
|
|---|
| 90 | boolean separatorAdded = true;
|
|---|
| 91 | for (Action a: selectedLayers.get(0).getMenuEntries()) {
|
|---|
| 92 | if (!separatorAdded && a instanceof SeparatorLayerAction) {
|
|---|
| 93 | separatorAdded = true;
|
|---|
| 94 | actions.add(a);
|
|---|
| 95 | } else if (a instanceof LayerAction && ((LayerAction) a).supportLayers(selectedLayers)) {
|
|---|
| 96 | separatorAdded = false;
|
|---|
| 97 | if (a instanceof MultiLayerAction)
|
|---|
| 98 | a = ((MultiLayerAction) a).getMultiLayerAction(selectedLayers);
|
|---|
| 99 | actions.add(a);
|
|---|
| 100 | }
|
|---|
| 101 | }
|
|---|
| 102 | // This will usually add no action, because if some action support all selected layers then it was probably used also in first layer
|
|---|
| 103 | for (int i = 1; i < selectedLayers.size(); i++) {
|
|---|
| 104 | separatorAdded = false;
|
|---|
| 105 | for (Action a: selectedLayers.get(i).getMenuEntries()) {
|
|---|
| 106 | if (a instanceof LayerAction && !(a instanceof MultiLayerAction)
|
|---|
| 107 | && ((LayerAction) a).supportLayers(selectedLayers) && !actions.contains(a)) {
|
|---|
| 108 | if (!separatorAdded) {
|
|---|
| 109 | separatorAdded = true;
|
|---|
| 110 | actions.add(SeparatorLayerAction.INSTANCE);
|
|---|
| 111 | }
|
|---|
| 112 | actions.add(a);
|
|---|
| 113 | }
|
|---|
| 114 | }
|
|---|
| 115 | }
|
|---|
| 116 | }
|
|---|
| 117 | if (!actions.isEmpty() && actions.get(actions.size() - 1) instanceof SeparatorLayerAction) {
|
|---|
| 118 | actions.remove(actions.size() - 1);
|
|---|
| 119 | }
|
|---|
| 120 | for (Action a : actions) {
|
|---|
| 121 | if (a instanceof LayerAction) {
|
|---|
| 122 | add(((LayerAction) a).createMenuComponent());
|
|---|
| 123 | } else {
|
|---|
| 124 | add(new JMenuItem(a));
|
|---|
| 125 | }
|
|---|
| 126 | }
|
|---|
| 127 | }
|
|---|
| 128 | }
|
|---|