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.List; 011 012import org.openstreetmap.josm.data.osm.OsmPrimitive; 013import org.openstreetmap.josm.data.osm.visitor.MergeSourceBuildingVisitor; 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; 020import org.openstreetmap.josm.tools.Utils; 021 022/** 023 * Merge the currently selected objects into another layer. 024 * @since 1890 025 */ 026public class MergeSelectionAction extends AbstractMergeAction { 027 028 /** 029 * Constructs a new {@code MergeSelectionAction}. 030 */ 031 public MergeSelectionAction() { 032 super(tr("Merge selection"), "dialogs/mergedown", tr("Merge the currently selected objects into another layer"), 033 Shortcut.registerShortcut("system:mergeselection", tr("Edit: {0}", tr("Merge selection")), 034 KeyEvent.VK_M, Shortcut.CTRL_SHIFT), 035 true /* register */ 036 ); 037 setHelpId(ht("/Action/MergeSelection")); 038 } 039 040 /** 041 * Merge the currently selected objects into another layer. 042 */ 043 public void mergeSelected() { 044 OsmDataLayer editLayer = getLayerManager().getEditLayer(); 045 List<Layer> targetLayers = LayerListDialog.getInstance().getModel().getPossibleMergeTargets(editLayer); 046 if (targetLayers.isEmpty()) { 047 warnNoTargetLayersForSourceLayer(editLayer); 048 return; 049 } 050 Layer targetLayer = askTargetLayer(targetLayers, false, null, false, tr("Merge selection")).selectedTargetLayer; 051 if (targetLayer == null) 052 return; 053 if (editLayer.isUploadDiscouraged() && targetLayer instanceof OsmDataLayer 054 && !((OsmDataLayer) targetLayer).isUploadDiscouraged() 055 && editLayer.data.getAllSelected().size() > 1 056 && warnMergingUploadDiscouragedObjects(targetLayer)) { 057 return; 058 } 059 MergeSourceBuildingVisitor builder = new MergeSourceBuildingVisitor(editLayer.getDataSet()); 060 ((OsmDataLayer) targetLayer).mergeFrom(builder.build()); 061 } 062 063 @Override 064 public void actionPerformed(ActionEvent e) { 065 OsmDataLayer editLayer = getLayerManager().getEditLayer(); 066 if (editLayer == null || editLayer.data.selectionEmpty()) 067 return; 068 mergeSelected(); 069 } 070 071 @Override 072 protected void updateEnabledState() { 073 updateEnabledStateOnCurrentSelection(); 074 } 075 076 @Override 077 protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) { 078 updateEnabledStateOnModifiableSelection(selection); 079 } 080 081 /** 082 * Warns the user about merging too many objects with different upload policies. 083 * @param targetLayer Target layer 084 * @return true if the user wants to cancel, false if they want to continue 085 */ 086 public final boolean warnMergingUploadDiscouragedObjects(Layer targetLayer) { 087 return GuiHelper.warnUser(tr("Merging too many objects with different upload policies"), 088 "<html>" + 089 tr("You are about to merge more than 1 object between layers ''{0}'' and ''{1}''.<br /><br />"+ 090 "<b>This is not the recommended way of merging such data</b>.<br />"+ 091 "You should instead check and merge each object, <b>one by one</b>.<br /><br />"+ 092 "Are you sure you want to continue?", 093 Utils.escapeReservedCharactersHTML(getLayerManager().getEditLayer().getName()), 094 Utils.escapeReservedCharactersHTML(targetLayer.getName()), 095 Utils.escapeReservedCharactersHTML(targetLayer.getName()))+ 096 "</html>", 097 ImageProvider.get("dialogs", "mergedown"), tr("Ignore this hint and merge anyway")); 098 } 099}