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