001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.actions; 003 004import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 005import static org.openstreetmap.josm.tools.I18n.tr; 006 007import java.awt.event.ActionEvent; 008import java.awt.event.KeyEvent; 009import java.util.Collection; 010import java.util.Collections; 011import java.util.List; 012 013import org.openstreetmap.josm.Main; 014import org.openstreetmap.josm.gui.dialogs.LayerListDialog; 015import org.openstreetmap.josm.gui.layer.Layer; 016import org.openstreetmap.josm.gui.layer.OsmDataLayer; 017import org.openstreetmap.josm.gui.util.GuiHelper; 018import org.openstreetmap.josm.tools.ImageProvider; 019import org.openstreetmap.josm.tools.Shortcut; 020 021public 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.main.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 @Override 076 public void actionPerformed(ActionEvent e) { 077 Layer sourceLayer = Main.main.getEditLayer(); 078 if (sourceLayer == null) 079 return; 080 merge(sourceLayer); 081 } 082 083 @Override 084 protected void updateEnabledState() { 085 GuiHelper.runInEDT(new Runnable() { 086 @Override 087 public void run() { 088 if (getEditLayer() == null) { 089 setEnabled(false); 090 return; 091 } 092 setEnabled(!LayerListDialog.getInstance().getModel().getPossibleMergeTargets(getEditLayer()).isEmpty()); 093 } 094 }); 095 } 096 097 /** 098 * returns true if the user wants to cancel, false if they want to continue 099 */ 100 public static final boolean warnMergingUploadDiscouragedLayers(Layer sourceLayer, Layer targetLayer) { 101 return GuiHelper.warnUser(tr("Merging layers with different upload policies"), 102 "<html>" + 103 tr("You are about to merge data between layers ''{0}'' and ''{1}''.<br /><br />"+ 104 "These layers have different upload policies and should not been merged as it.<br />"+ 105 "Merging them will result to enforce the stricter policy (upload discouraged) to ''{1}''.<br /><br />"+ 106 "<b>This is not the recommended way of merging such data</b>.<br />"+ 107 "You should instead check and merge each object, one by one, by using ''<i>Merge selection</i>''.<br /><br />"+ 108 "Are you sure you want to continue?", sourceLayer.getName(), targetLayer.getName(), targetLayer.getName())+ 109 "</html>", 110 ImageProvider.get("dialogs", "mergedown"), tr("Ignore this hint and merge anyway")); 111 } 112}