[626] | 1 | // License: GPL. Copyright 2007 by Immanuel Scholz and others
|
---|
| 2 | // Author: David Earl
|
---|
| 3 | package org.openstreetmap.josm.actions;
|
---|
| 4 |
|
---|
| 5 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
| 6 |
|
---|
| 7 | import java.awt.event.ActionEvent;
|
---|
| 8 | import java.awt.event.KeyEvent;
|
---|
| 9 | import java.util.ArrayList;
|
---|
| 10 | import java.util.HashMap;
|
---|
| 11 | import java.util.List;
|
---|
| 12 | import java.util.LinkedList;
|
---|
| 13 | import java.util.Collection;
|
---|
| 14 |
|
---|
| 15 | import javax.swing.JOptionPane;
|
---|
| 16 |
|
---|
| 17 | import org.openstreetmap.josm.Main;
|
---|
| 18 | import org.openstreetmap.josm.data.SelectionChangedListener;
|
---|
| 19 | import org.openstreetmap.josm.data.osm.DataSet;
|
---|
| 20 | import org.openstreetmap.josm.data.osm.Relation;
|
---|
| 21 | import org.openstreetmap.josm.data.osm.RelationMember;
|
---|
| 22 | import org.openstreetmap.josm.data.osm.Node;
|
---|
| 23 | import org.openstreetmap.josm.data.osm.OsmPrimitive;
|
---|
| 24 | import org.openstreetmap.josm.data.osm.Way;
|
---|
| 25 | import org.openstreetmap.josm.data.osm.visitor.Visitor;
|
---|
[1084] | 26 | import org.openstreetmap.josm.tools.Shortcut;
|
---|
[626] | 27 |
|
---|
| 28 | public final class CopyAction extends JosmAction implements SelectionChangedListener {
|
---|
| 29 |
|
---|
| 30 | private LinkedList<JosmAction> listeners;
|
---|
[1023] | 31 |
|
---|
[626] | 32 | public CopyAction() {
|
---|
| 33 | super(tr("Copy"), "copy",
|
---|
| 34 | tr("Copy selected objects to paste buffer."),
|
---|
[1084] | 35 | Shortcut.registerShortcut("system:copy", tr("Edit: {0}", tr("Copy")), KeyEvent.VK_C, Shortcut.GROUP_MENU), true);
|
---|
[626] | 36 | setEnabled(false);
|
---|
| 37 | DataSet.selListeners.add(this);
|
---|
| 38 | listeners = new LinkedList<JosmAction>();
|
---|
| 39 | }
|
---|
| 40 |
|
---|
| 41 | @Override public void addListener(JosmAction a) {
|
---|
| 42 | listeners.add(a);
|
---|
| 43 | }
|
---|
[1023] | 44 |
|
---|
[626] | 45 | public void actionPerformed(ActionEvent e) {
|
---|
| 46 | Collection<OsmPrimitive> sel = Main.ds.getSelected();
|
---|
[1023] | 47 | if (sel.isEmpty()) {
|
---|
[626] | 48 | JOptionPane.showMessageDialog(Main.parent,
|
---|
[1023] | 49 | tr("Please select something to copy."));
|
---|
[626] | 50 | return;
|
---|
| 51 | }
|
---|
| 52 |
|
---|
| 53 | /* New pasteBuffer - will be assigned to the global one at the end */
|
---|
| 54 | final DataSet pasteBuffer = new DataSet();
|
---|
| 55 | final HashMap<OsmPrimitive,OsmPrimitive> map = new HashMap<OsmPrimitive,OsmPrimitive>();
|
---|
| 56 | /* temporarily maps old nodes to new so we can do a true deep copy */
|
---|
| 57 |
|
---|
[1023] | 58 | /* scan the selected objects, mapping them to copies; when copying a way or relation,
|
---|
[626] | 59 | * the copy references the copies of their child objects */
|
---|
| 60 | new Visitor(){
|
---|
| 61 | public void visit(Node n) {
|
---|
[1023] | 62 | /* check if already in pasteBuffer - e.g. two ways are selected which share a node;
|
---|
| 63 | * or a way and a node in that way is selected, we'll see it twice, once via the
|
---|
[626] | 64 | * way and once directly; and so on. */
|
---|
| 65 | if (map.containsKey(n)) { return; }
|
---|
| 66 | Node nnew = new Node(n);
|
---|
| 67 | map.put(n, nnew);
|
---|
| 68 | pasteBuffer.addPrimitive(nnew);
|
---|
| 69 | }
|
---|
| 70 | public void visit(Way w) {
|
---|
| 71 | /* check if already in pasteBuffer - could have come from a relation, and directly etc. */
|
---|
| 72 | if (map.containsKey(w)) { return; }
|
---|
| 73 | Way wnew = new Way();
|
---|
| 74 | wnew.cloneFrom(w);
|
---|
| 75 | wnew.nodes.clear();
|
---|
| 76 | List<Node> nodes = new ArrayList<Node>();
|
---|
| 77 | for (Node n : w.nodes) {
|
---|
| 78 | if (! map.containsKey(n)) {
|
---|
| 79 | n.visit(this);
|
---|
| 80 | }
|
---|
| 81 | nodes.add((Node)map.get(n));
|
---|
| 82 | }
|
---|
| 83 | wnew.nodes.clear();
|
---|
| 84 | wnew.nodes.addAll(nodes);
|
---|
| 85 | pasteBuffer.addPrimitive(wnew);
|
---|
| 86 | }
|
---|
| 87 | public void visit(Relation e) {
|
---|
| 88 | if (map.containsKey(e)) { return; }
|
---|
| 89 | Relation enew = new Relation(e);
|
---|
| 90 | List<RelationMember> members = new ArrayList<RelationMember>();
|
---|
| 91 | for (RelationMember m : e.members) {
|
---|
| 92 | if (! map.containsKey(m.member)) {
|
---|
| 93 | m.member.visit(this);
|
---|
| 94 | }
|
---|
| 95 | RelationMember mnew = new RelationMember(m);
|
---|
| 96 | mnew.member = map.get(m.member);
|
---|
| 97 | members.add(mnew);
|
---|
| 98 | }
|
---|
| 99 | enew.members.addAll(members);
|
---|
| 100 | pasteBuffer.addPrimitive(enew);
|
---|
| 101 | }
|
---|
| 102 | public void visitAll() {
|
---|
| 103 | for (OsmPrimitive osm : Main.ds.getSelected())
|
---|
| 104 | osm.visit(this);
|
---|
| 105 | }
|
---|
| 106 | }.visitAll();
|
---|
| 107 |
|
---|
| 108 | Main.pasteBuffer = pasteBuffer;
|
---|
| 109 | Main.main.menu.paste.setEnabled(true); /* now we have a paste buffer we can make paste available */
|
---|
[1023] | 110 |
|
---|
[626] | 111 | for(JosmAction a : listeners) {
|
---|
| 112 | a.pasteBufferChanged(Main.pasteBuffer);
|
---|
| 113 | }
|
---|
| 114 | }
|
---|
| 115 |
|
---|
| 116 | public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
|
---|
| 117 | setEnabled(! newSelection.isEmpty());
|
---|
| 118 | }
|
---|
| 119 | }
|
---|