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