001 // License: GPL. For details, see LICENSE file.
002 package org.openstreetmap.josm.actions;
003
004 import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
005 import static org.openstreetmap.josm.tools.I18n.tr;
006
007 import java.awt.event.ActionEvent;
008 import java.awt.event.KeyEvent;
009 import java.util.Collection;
010 import java.util.Collections;
011 import java.util.List;
012
013 import org.openstreetmap.josm.Main;
014 import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
015 import org.openstreetmap.josm.gui.layer.Layer;
016 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
017 import org.openstreetmap.josm.gui.util.GuiHelper;
018 import org.openstreetmap.josm.tools.ImageProvider;
019 import org.openstreetmap.josm.tools.Shortcut;
020
021 public class MergeLayerAction extends AbstractMergeAction {
022
023 public MergeLayerAction() {
024 super(tr("Merge layer"), "dialogs/mergedown",
025 tr("Merge the current layer into another layer"),
026 Shortcut.registerShortcut("system:merge", tr("Edit: {0}",
027 tr("Merge")), KeyEvent.VK_M, Shortcut.CTRL),
028 true, "action/mergelayer", true);
029 putValue("help", ht("/Action/MergeLayer"));
030 }
031
032 protected void doMerge(List<Layer> targetLayers, final Collection<Layer> sourceLayers) {
033 final Layer targetLayer = askTargetLayer(targetLayers);
034 if (targetLayer == null)
035 return;
036 Main.worker.submit(new Runnable() {
037 @Override
038 public void run() {
039 boolean layerMerged = false;
040 for (Layer sourceLayer: sourceLayers) {
041 if (sourceLayer != null && sourceLayer != targetLayer) {
042 if (sourceLayer instanceof OsmDataLayer && targetLayer instanceof OsmDataLayer
043 && ((OsmDataLayer)sourceLayer).isUploadDiscouraged() != ((OsmDataLayer)targetLayer).isUploadDiscouraged()) {
044 if (warnMergingUploadDiscouragedLayers(sourceLayer, targetLayer)) {
045 break;
046 }
047 }
048 targetLayer.mergeFrom(sourceLayer);
049 Main.map.mapView.removeLayer(sourceLayer);
050 layerMerged = true;
051 }
052 }
053 if (layerMerged) {
054 Main.map.mapView.setActiveLayer(targetLayer);
055 }
056 }
057 });
058 }
059
060 public void merge(List<Layer> sourceLayers) {
061 doMerge(sourceLayers, sourceLayers);
062 }
063
064 public void merge(Layer sourceLayer) {
065 if (sourceLayer == null)
066 return;
067 List<Layer> targetLayers = LayerListDialog.getInstance().getModel().getPossibleMergeTargets(sourceLayer);
068 if (targetLayers.isEmpty()) {
069 warnNoTargetLayersForSourceLayer(sourceLayer);
070 return;
071 }
072 doMerge(targetLayers, Collections.singleton(sourceLayer));
073 }
074
075 public void actionPerformed(ActionEvent e) {
076 Layer sourceLayer = Main.main.getEditLayer();
077 if (sourceLayer == null)
078 return;
079 merge(sourceLayer);
080 }
081
082 @Override
083 protected void updateEnabledState() {
084 GuiHelper.runInEDT(new Runnable() {
085 @Override
086 public void run() {
087 if (getEditLayer() == null) {
088 setEnabled(false);
089 return;
090 }
091 setEnabled(!LayerListDialog.getInstance().getModel().getPossibleMergeTargets(getEditLayer()).isEmpty());
092 }
093 });
094 }
095
096 /**
097 * returns true if the user wants to cancel, false if they want to continue
098 */
099 public static final boolean warnMergingUploadDiscouragedLayers(Layer sourceLayer, Layer targetLayer) {
100 return GuiHelper.warnUser(tr("Merging layers with different upload policies"),
101 "<html>" +
102 tr("You are about to merge data between layers ''{0}'' and ''{1}''.<br /><br />"+
103 "These layers have different upload policies and should not been merged as it.<br />"+
104 "Merging them will result to enforce the stricter policy (upload discouraged) to ''{1}''.<br /><br />"+
105 "<b>This is not the recommended way of merging such data</b>.<br />"+
106 "You should instead check and merge each object, one by one, by using ''<i>Merge selection</i>''.<br /><br />"+
107 "Are you sure you want to continue?", sourceLayer.getName(), targetLayer.getName(), targetLayer.getName())+
108 "</html>",
109 ImageProvider.get("dialogs", "mergedown"), tr("Ignore this hint and merge anyway"));
110 }
111 }