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