Ignore:
Timestamp:
2016-07-23T14:54:19+02:00 (8 years ago)
Author:
Don-vip
Message:

fix #12478, fix #12565, fix #11114 - Use ​Swing Copy/Paste instead of CopyAction/PasteAction with custom buffer (patch by michael2402, modified) - gsoc-core

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/PasteAction.java

    r10413 r10604  
    88import java.awt.MouseInfo;
    99import java.awt.Point;
     10import java.awt.datatransfer.FlavorEvent;
     11import java.awt.datatransfer.FlavorListener;
    1012import java.awt.event.ActionEvent;
    1113import java.awt.event.KeyEvent;
    12 import java.util.ArrayList;
    13 import java.util.HashMap;
    14 import java.util.List;
    15 import java.util.Map;
    1614
    1715import org.openstreetmap.josm.Main;
    18 import org.openstreetmap.josm.command.AddPrimitivesCommand;
    1916import org.openstreetmap.josm.data.coor.EastNorth;
    20 import org.openstreetmap.josm.data.osm.NodeData;
    21 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    22 import org.openstreetmap.josm.data.osm.PrimitiveData;
    23 import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy;
    24 import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy.PasteBufferChangedListener;
    25 import org.openstreetmap.josm.data.osm.RelationData;
    26 import org.openstreetmap.josm.data.osm.RelationMemberData;
    27 import org.openstreetmap.josm.data.osm.WayData;
    28 import org.openstreetmap.josm.gui.ExtendedDialog;
    29 import org.openstreetmap.josm.gui.layer.Layer;
     17import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils;
     18import org.openstreetmap.josm.gui.datatransfer.OsmTransferHandler;
    3019import org.openstreetmap.josm.tools.Shortcut;
    3120
     
    3423 * @since 404
    3524 */
    36 public final class PasteAction extends JosmAction implements PasteBufferChangedListener {
     25public final class PasteAction extends JosmAction implements FlavorListener {
     26
     27    private final OsmTransferHandler transferHandler;
    3728
    3829    /**
     
    4637        Main.registerActionShortcut(this,
    4738                Shortcut.registerShortcut("system:paste:cua", tr("Edit: {0}", tr("Paste")), KeyEvent.VK_INSERT, Shortcut.SHIFT));
    48         Main.pasteBuffer.addPasteBufferChangedListener(this);
     39        transferHandler = new OsmTransferHandler();
     40        ClipboardUtils.getClipboard().addFlavorListener(this);
    4941    }
    5042
    5143    @Override
    5244    public void actionPerformed(ActionEvent e) {
    53         if (!isEnabled())
    54             return;
    55         pasteData(Main.pasteBuffer, Main.pasteSource, e);
    56     }
    57 
    58     /**
    59      * Paste OSM primitives from the given paste buffer and OSM data layer source to the current edit layer.
    60      * @param pasteBuffer The paste buffer containing primitive ids to copy
    61      * @param source The OSM data layer used to look for primitive ids
    62      * @param e The ActionEvent that triggered this operation
    63      */
    64     public void pasteData(PrimitiveDeepCopy pasteBuffer, Layer source, ActionEvent e) {
    65         /* Find the middle of the pasteBuffer area */
    66         double maxEast = -1E100;
    67         double minEast = 1E100;
    68         double maxNorth = -1E100;
    69         double minNorth = 1E100;
    70         boolean incomplete = false;
    71         for (PrimitiveData data : pasteBuffer.getAll()) {
    72             if (data instanceof NodeData) {
    73                 NodeData n = (NodeData) data;
    74                 if (n.getEastNorth() != null) {
    75                     double east = n.getEastNorth().east();
    76                     double north = n.getEastNorth().north();
    77                     if (east > maxEast) {
    78                         maxEast = east;
    79                     }
    80                     if (east < minEast) {
    81                         minEast = east;
    82                     }
    83                     if (north > maxNorth) {
    84                         maxNorth = north;
    85                     }
    86                     if (north < minNorth) {
    87                         minNorth = north;
    88                     }
    89                 }
    90             }
    91             if (data.isIncomplete()) {
    92                 incomplete = true;
    93             }
    94         }
    95 
    96         // Allow to cancel paste if there are incomplete primitives
    97         if (incomplete && !confirmDeleteIncomplete()) {
    98             return;
    99         }
    100 
    10145        // default to paste in center of map (pasted via menu or cursor not in MapView)
    10246        EastNorth mPosition = Main.map.mapView.getCenter();
     
    11357        }
    11458
    115         double offsetEast = mPosition.east() - (maxEast + minEast)/2.0;
    116         double offsetNorth = mPosition.north() - (maxNorth + minNorth)/2.0;
    117 
    118         // Make a copy of pasteBuffer and map from old id to copied data id
    119         List<PrimitiveData> bufferCopy = new ArrayList<>();
    120         List<PrimitiveData> toSelect = new ArrayList<>();
    121         Map<Long, Long> newNodeIds = new HashMap<>();
    122         Map<Long, Long> newWayIds = new HashMap<>();
    123         Map<Long, Long> newRelationIds = new HashMap<>();
    124         for (PrimitiveData data: pasteBuffer.getAll()) {
    125             if (data.isIncomplete()) {
    126                 continue;
    127             }
    128             PrimitiveData copy = data.makeCopy();
    129             copy.clearOsmMetadata();
    130             if (data instanceof NodeData) {
    131                 newNodeIds.put(data.getUniqueId(), copy.getUniqueId());
    132             } else if (data instanceof WayData) {
    133                 newWayIds.put(data.getUniqueId(), copy.getUniqueId());
    134             } else if (data instanceof RelationData) {
    135                 newRelationIds.put(data.getUniqueId(), copy.getUniqueId());
    136             }
    137             bufferCopy.add(copy);
    138             if (pasteBuffer.getDirectlyAdded().contains(data)) {
    139                 toSelect.add(copy);
    140             }
    141         }
    142 
    143         // Update references in copied buffer
    144         for (PrimitiveData data:bufferCopy) {
    145             if (data instanceof NodeData) {
    146                 NodeData nodeData = (NodeData) data;
    147                 if (Main.getLayerManager().getEditLayer() == source) {
    148                     nodeData.setEastNorth(nodeData.getEastNorth().add(offsetEast, offsetNorth));
    149                 }
    150             } else if (data instanceof WayData) {
    151                 List<Long> newNodes = new ArrayList<>();
    152                 for (Long oldNodeId: ((WayData) data).getNodes()) {
    153                     Long newNodeId = newNodeIds.get(oldNodeId);
    154                     if (newNodeId != null) {
    155                         newNodes.add(newNodeId);
    156                     }
    157                 }
    158                 ((WayData) data).setNodes(newNodes);
    159             } else if (data instanceof RelationData) {
    160                 List<RelationMemberData> newMembers = new ArrayList<>();
    161                 for (RelationMemberData member: ((RelationData) data).getMembers()) {
    162                     OsmPrimitiveType memberType = member.getMemberType();
    163                     Long newId;
    164                     switch (memberType) {
    165                     case NODE:
    166                         newId = newNodeIds.get(member.getMemberId());
    167                         break;
    168                     case WAY:
    169                         newId = newWayIds.get(member.getMemberId());
    170                         break;
    171                     case RELATION:
    172                         newId = newRelationIds.get(member.getMemberId());
    173                         break;
    174                     default: throw new AssertionError();
    175                     }
    176                     if (newId != null) {
    177                         newMembers.add(new RelationMemberData(member.getRole(), memberType, newId));
    178                     }
    179                 }
    180                 ((RelationData) data).setMembers(newMembers);
    181             }
    182         }
    183 
    184         /* Now execute the commands to add the duplicated contents of the paste buffer to the map */
    185         Main.main.undoRedo.add(new AddPrimitivesCommand(bufferCopy, toSelect));
    186         Main.map.mapView.repaint();
    187     }
    188 
    189     private static boolean confirmDeleteIncomplete() {
    190         ExtendedDialog ed = new ExtendedDialog(Main.parent,
    191                 tr("Delete incomplete members?"),
    192                 new String[] {tr("Paste without incomplete members"), tr("Cancel")});
    193         ed.setButtonIcons(new String[] {"dialogs/relation/deletemembers", "cancel"});
    194         ed.setContent(tr("The copied data contains incomplete objects.  "
    195                 + "When pasting the incomplete objects are removed.  "
    196                 + "Do you want to paste the data without the incomplete objects?"));
    197         ed.showDialog();
    198         return ed.getValue() == 1;
     59        transferHandler.pasteOn(Main.getLayerManager().getEditLayer(), mPosition);
    19960    }
    20061
    20162    @Override
    20263    protected void updateEnabledState() {
    203         if (getLayerManager().getEditDataSet() == null || Main.pasteBuffer == null) {
    204             setEnabled(false);
    205             return;
    206         }
    207         setEnabled(!Main.pasteBuffer.isEmpty());
     64        setEnabled(getLayerManager().getEditDataSet() != null && transferHandler.isDataAvailable());
    20865    }
    20966
    21067    @Override
    211     public void pasteBufferChanged(PrimitiveDeepCopy pasteBuffer) {
     68    public void flavorsChanged(FlavorEvent e) {
    21269        updateEnabledState();
    21370    }
Note: See TracChangeset for help on using the changeset viewer.