001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.dialogs.layer; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.Component; 007import java.awt.event.ActionEvent; 008import java.util.List; 009 010import javax.swing.AbstractAction; 011import javax.swing.JMenuItem; 012 013import org.openstreetmap.josm.actions.MergeLayerAction; 014import org.openstreetmap.josm.gui.MainApplication; 015import org.openstreetmap.josm.gui.dialogs.IEnabledStateUpdating; 016import org.openstreetmap.josm.gui.dialogs.LayerListDialog.LayerListModel; 017import org.openstreetmap.josm.gui.help.HelpUtil; 018import org.openstreetmap.josm.gui.layer.Layer; 019import org.openstreetmap.josm.gui.layer.Layer.LayerAction; 020import org.openstreetmap.josm.tools.CheckParameterUtil; 021import org.openstreetmap.josm.tools.ImageProvider; 022 023/** 024 * The action to merge the currently selected layer into another layer. 025 */ 026public final class MergeAction extends AbstractAction implements IEnabledStateUpdating, LayerAction, Layer.MultiLayerAction { 027 private final transient Layer layer; 028 private final transient List<Layer> layers; 029 private final LayerListModel model; 030 031 /** 032 * Constructs a new {@code MergeAction}. 033 * @param layer the layer 034 * @param model layer list model 035 * @throws IllegalArgumentException if {@code layer} is null 036 */ 037 public MergeAction(Layer layer, LayerListModel model) { 038 this(layer, null, model); 039 CheckParameterUtil.ensureParameterNotNull(layer, "layer"); 040 } 041 042 /** 043 * Constructs a new {@code MergeAction}. 044 * @param layers the layer list 045 * @param model layer list model 046 * @throws IllegalArgumentException if {@code layers} is null 047 */ 048 public MergeAction(List<Layer> layers, LayerListModel model) { 049 this(null, layers, model); 050 CheckParameterUtil.ensureParameterNotNull(layers, "layers"); 051 } 052 053 /** 054 * Constructs a new {@code MergeAction}. 055 * @param layer the layer (null if layer list if specified) 056 * @param layers the layer list (null if a single layer is specified) 057 * @param model layer list model 058 */ 059 private MergeAction(Layer layer, List<Layer> layers, LayerListModel model) { 060 this.layer = layer; 061 this.layers = layers; 062 this.model = model; 063 putValue(NAME, tr("Merge")); 064 new ImageProvider("dialogs", "mergedown").getResource().attachImageIcon(this, true); 065 putValue(SHORT_DESCRIPTION, tr("Merge this layer into another layer")); 066 putValue("help", HelpUtil.ht("/Dialog/LayerList#MergeLayer")); 067 updateEnabledState(); 068 } 069 070 @Override 071 public void actionPerformed(ActionEvent e) { 072 MergeLayerAction mergeLayerAction = MainApplication.getMenu().merge; 073 if (layer != null) { 074 mergeLayerAction.merge(layer); 075 } else if (layers != null) { 076 mergeLayerAction.merge(layers); 077 } else { 078 if (model.getSelectedLayers().size() == 1) { 079 Layer selectedLayer = model.getSelectedLayers().get(0); 080 mergeLayerAction.merge(selectedLayer); 081 } else { 082 mergeLayerAction.merge(model.getSelectedLayers()); 083 } 084 } 085 } 086 087 @Override 088 public void updateEnabledState() { 089 if (layer == null && layers == null) { 090 if (model.getSelectedLayers().isEmpty()) { 091 setEnabled(false); 092 } else if (model.getSelectedLayers().size() > 1) { 093 setEnabled(supportLayers(model.getSelectedLayers())); 094 } else { 095 Layer selectedLayer = model.getSelectedLayers().get(0); 096 List<Layer> targets = model.getPossibleMergeTargets(selectedLayer); 097 setEnabled(!targets.isEmpty()); 098 } 099 } else if (layer != null) { 100 List<Layer> targets = model.getPossibleMergeTargets(layer); 101 setEnabled(!targets.isEmpty()); 102 } else { 103 setEnabled(supportLayers(layers)); 104 } 105 } 106 107 @Override 108 public boolean supportLayers(List<Layer> layers) { 109 if (layers.isEmpty()) { 110 return false; 111 } else { 112 final Layer firstLayer = layers.get(0); 113 final List<Layer> remainingLayers = layers.subList(1, layers.size()); 114 return model.getPossibleMergeTargets(firstLayer).containsAll(remainingLayers); 115 } 116 } 117 118 @Override 119 public Component createMenuComponent() { 120 return new JMenuItem(this); 121 } 122 123 @Override 124 public MergeAction getMultiLayerAction(List<Layer> layers) { 125 return new MergeAction(layers, model); 126 } 127}