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 transient Layer layer;
028    private 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}