source: josm/trunk/src/org/openstreetmap/josm/actions/CopyAction.java@ 2283

Last change on this file since 2283 was 2283, checked in by Gubaer, 15 years ago

fixed #3698: copying a relation or its keys/values impossible

  • Property svn:eol-style set to native
File size: 5.2 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2// Author: David Earl
3package org.openstreetmap.josm.actions;
4
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.event.ActionEvent;
8import java.awt.event.KeyEvent;
9import java.util.ArrayList;
10import java.util.Collection;
11import java.util.HashMap;
12import java.util.LinkedList;
13import java.util.List;
14
15import javax.swing.JOptionPane;
16
17import org.openstreetmap.josm.Main;
18import org.openstreetmap.josm.data.osm.DataSet;
19import org.openstreetmap.josm.data.osm.Node;
20import org.openstreetmap.josm.data.osm.OsmPrimitive;
21import org.openstreetmap.josm.data.osm.Relation;
22import org.openstreetmap.josm.data.osm.RelationMember;
23import org.openstreetmap.josm.data.osm.Way;
24import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
25import org.openstreetmap.josm.tools.Shortcut;
26
27public final class CopyAction extends JosmAction {
28
29 private LinkedList<JosmAction> listeners;
30
31 public CopyAction() {
32 super(tr("Copy"), "copy",
33 tr("Copy selected objects to paste buffer."),
34 Shortcut.registerShortcut("system:copy", tr("Edit: {0}", tr("Copy")), KeyEvent.VK_C, Shortcut.GROUP_MENU), true);
35 listeners = new LinkedList<JosmAction>();
36 }
37
38 @Override public void addListener(JosmAction a) {
39 listeners.add(a);
40 }
41
42 public void actionPerformed(ActionEvent e) {
43 if(isEmptySelection()) return;
44
45 Main.pasteBuffer = copyData();
46 Main.pasteSource = getEditLayer();
47 Main.main.menu.paste.setEnabled(true); /* now we have a paste buffer we can make paste available */
48
49 for(JosmAction a : listeners) {
50 a.pasteBufferChanged(Main.pasteBuffer);
51 }
52 }
53
54 public DataSet copyData() {
55 /* New pasteBuffer - will be assigned to the global one at the end */
56 final DataSet pasteBuffer = new DataSet();
57 final HashMap<OsmPrimitive,OsmPrimitive> map = new HashMap<OsmPrimitive,OsmPrimitive>();
58 /* temporarily maps old nodes to new so we can do a true deep copy */
59
60 if(isEmptySelection()) return pasteBuffer;
61
62 /* scan the selected objects, mapping them to copies; when copying a way or relation,
63 * the copy references the copies of their child objects */
64 new AbstractVisitor() {
65 public void visit(Node n) {
66 /* check if already in pasteBuffer - e.g. two ways are selected which share a node;
67 * or a way and a node in that way is selected, we'll see it twice, once via the
68 * way and once directly; and so on. */
69 if (map.containsKey(n))
70 return;
71 Node nnew = new Node(n);
72 map.put(n, nnew);
73 pasteBuffer.addPrimitive(nnew);
74 }
75 public void visit(Way w) {
76 /* check if already in pasteBuffer - could have come from a relation, and directly etc. */
77 if (map.containsKey(w))
78 return;
79 Way wnew = new Way();
80 wnew.cloneFrom(w);
81 map.put(w, wnew);
82 List<Node> nodes = new ArrayList<Node>();
83 for (Node n : w.getNodes()) {
84 if (! map.containsKey(n)) {
85 n.visit(this);
86 }
87 nodes.add((Node)map.get(n));
88 }
89 wnew.setNodes(nodes);
90 pasteBuffer.addPrimitive(wnew);
91 }
92 public void visit(Relation e) {
93 if (map.containsKey(e))
94 return;
95 Relation enew = new Relation(e);
96 map.put(e, enew);
97 List<RelationMember> members = new ArrayList<RelationMember>();
98 for (RelationMember m : e.getMembers()) {
99 if (! map.containsKey(m.getMember())) {
100 m.getMember().visit(this);
101 }
102 RelationMember mnew = new RelationMember(m.getRole(), map.get(m.getMember()));
103 members.add(mnew);
104 }
105 enew.setMembers(members);
106 pasteBuffer.addPrimitive(enew);
107 }
108 public void visitAll() {
109 for (OsmPrimitive osm : getCurrentDataSet().getSelected()) {
110 osm.visit(this);
111 }
112 }
113 }.visitAll();
114
115 return pasteBuffer;
116 }
117
118 @Override
119 protected void updateEnabledState() {
120 if (getCurrentDataSet() == null) {
121 setEnabled(false);
122 } else {
123 updateEnabledState(getCurrentDataSet().getSelected());
124 }
125 }
126
127 @Override
128 protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
129 setEnabled(selection != null && !selection.isEmpty());
130 }
131
132 private boolean isEmptySelection() {
133 Collection<OsmPrimitive> sel = getCurrentDataSet().getSelected();
134 if (sel.isEmpty()) {
135 JOptionPane.showMessageDialog(
136 Main.parent,
137 tr("Please select something to copy."),
138 tr("Information"),
139 JOptionPane.INFORMATION_MESSAGE
140 );
141 return true;
142 }
143 return false;
144 }
145}
Note: See TracBrowser for help on using the repository browser.