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