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}