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