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 }