Changeset 2305 in josm for trunk/src/org/openstreetmap/josm/actions
- Timestamp:
- 2009-10-24T21:22:49+02:00 (17 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/actions
- Files:
-
- 6 edited
-
CopyAction.java (modified) (3 diffs)
-
DuplicateAction.java (modified) (2 diffs)
-
JosmAction.java (modified) (9 diffs)
-
MoveAction.java (modified) (1 diff)
-
PasteAction.java (modified) (4 diffs)
-
PasteTagsAction.java (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/CopyAction.java
r2283 r2305 7 7 import java.awt.event.ActionEvent; 8 8 import java.awt.event.KeyEvent; 9 import java.util.ArrayList;10 9 import java.util.Collection; 11 import java.util.HashMap;12 10 import java.util.LinkedList; 13 import java.util.List;14 11 15 12 import javax.swing.JOptionPane; 16 13 17 14 import org.openstreetmap.josm.Main; 18 import org.openstreetmap.josm.data.osm.DataSet;19 import org.openstreetmap.josm.data.osm.Node;20 15 import org.openstreetmap.josm.data.osm.OsmPrimitive; 21 import org.openstreetmap.josm.data.osm.Relation;22 import org.openstreetmap.josm.data.osm.RelationMember;23 import org.openstreetmap.josm.data.osm.Way;24 import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;25 16 import org.openstreetmap.josm.tools.Shortcut; 26 17 … … 43 34 if(isEmptySelection()) return; 44 35 45 Main.pasteBuffer = copyData();36 Main.pasteBuffer.makeCopy(getCurrentDataSet().getSelected()); 46 37 Main.pasteSource = getEditLayer(); 47 38 Main.main.menu.paste.setEnabled(true); /* now we have a paste buffer we can make paste available */ … … 50 41 a.pasteBufferChanged(Main.pasteBuffer); 51 42 } 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 the68 * 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 43 } 117 44 -
trunk/src/org/openstreetmap/josm/actions/DuplicateAction.java
r2256 r2305 10 10 11 11 import org.openstreetmap.josm.data.osm.OsmPrimitive; 12 import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy; 12 13 import org.openstreetmap.josm.tools.Shortcut; 13 14 … … 21 22 22 23 public void actionPerformed(ActionEvent e) { 23 new PasteAction().pasteData(new CopyAction().copyData(), getEditLayer(), e);24 new PasteAction().pasteData(new PrimitiveDeepCopy(getCurrentDataSet().getSelected()), getEditLayer(), e); 24 25 } 25 26 -
trunk/src/org/openstreetmap/josm/actions/JosmAction.java
r2260 r2305 13 13 import org.openstreetmap.josm.data.osm.DataSet; 14 14 import org.openstreetmap.josm.data.osm.OsmPrimitive; 15 import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy; 15 16 import org.openstreetmap.josm.gui.layer.Layer; 16 17 import org.openstreetmap.josm.gui.layer.OsmDataLayer; … … 22 23 /** 23 24 * Base class helper for all Actions in JOSM. Just to make the life easier. 24 * 25 * 25 26 * A JosmAction is a {@see LayerChangeListener} and a {@see SelectionChangedListener}. Upon 26 27 * a layer change event or a selection change event it invokes {@see #updateEnabled()}. … … 28 29 * of a JosmAction depending on the {@see #getCurrentDataSet()} and the current layers 29 30 * (see also {@see #getEditLayer()}). 30 * 31 * 31 32 * destroy() from interface Destroyable is called e.g. for MapModes, when the last layer has 32 33 * been removed and so the mapframe will be destroyed. For other JosmActions, destroy() may never … … 105 106 * needs to be overridden to be useful 106 107 */ 107 public void pasteBufferChanged( DataSetnewPasteBuffer) {108 public void pasteBufferChanged(PrimitiveDeepCopy newPasteBuffer) { 108 109 return; 109 110 } … … 126 127 /** 127 128 * Replies the current edit layer 128 * 129 * 129 130 * @return the current edit layer. null, if no edit layer exists 130 131 */ … … 135 136 /** 136 137 * Replies the current dataset 137 * 138 * 138 139 * @return the current dataset. null, if no current dataset exists 139 140 */ … … 155 156 * Override in subclasses to init the enabled state of an action when it is 156 157 * created. Default behaviour is to call {@see #updateEnabledState()} 157 * 158 * 158 159 * @see #updateEnabledState() 159 160 * @see #updateEnabledState(Collection) … … 166 167 * Override in subclasses to update the enabled state of the action when 167 168 * something in the JOSM state changes, i.e. when a layer is removed or added. 168 * 169 * 169 170 * See {@see #updateEnabledState(Collection)} to respond to changes in the collection 170 171 * of selected primitives. 171 * 172 * 172 173 * Default behavior is empty. 173 * 174 * 174 175 * @see #updateEnabledState(Collection) 175 176 * @see #initEnabledState() … … 183 184 * new selection. Avoid calling getCurrentDataSet().getSelected() because this 184 185 * loops over the complete data set. 185 * 186 * 186 187 * @param selection the collection of selected primitives 187 * 188 * 188 189 * @see #updateEnabledState() 189 190 * @see #initEnabledState() -
trunk/src/org/openstreetmap/josm/actions/MoveAction.java
r2256 r2305 81 81 disty = 0; 82 82 distx = -distx; 83 break; 83 84 default: 84 85 disty = 0; -
trunk/src/org/openstreetmap/josm/actions/PasteAction.java
r2070 r2305 8 8 import java.awt.event.KeyEvent; 9 9 import java.util.ArrayList; 10 import java.util.Collection;11 10 import java.util.HashMap; 12 import java.util.LinkedList;13 11 import java.util.List; 12 import java.util.ListIterator; 13 import java.util.Map; 14 14 15 15 import org.openstreetmap.josm.Main; 16 import org.openstreetmap.josm.command.AddCommand; 17 import org.openstreetmap.josm.command.Command; 18 import org.openstreetmap.josm.command.SequenceCommand; 16 import org.openstreetmap.josm.command.AddPrimitivesCommand; 19 17 import org.openstreetmap.josm.data.coor.EastNorth; 20 import org.openstreetmap.josm.data.osm. DataSet;21 import org.openstreetmap.josm.data.osm. Node;22 import org.openstreetmap.josm.data.osm. OsmPrimitive;23 import org.openstreetmap.josm.data.osm.Relation; 24 import org.openstreetmap.josm.data.osm.RelationMember; 25 import org.openstreetmap.josm.data.osm.Way; 18 import org.openstreetmap.josm.data.osm.NodeData; 19 import org.openstreetmap.josm.data.osm.PrimitiveData; 20 import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy; 21 import org.openstreetmap.josm.data.osm.RelationData; 22 import org.openstreetmap.josm.data.osm.RelationMemberData; 23 import org.openstreetmap.josm.data.osm.WayData; 26 24 import org.openstreetmap.josm.gui.layer.Layer; 27 25 import org.openstreetmap.josm.tools.Shortcut; … … 40 38 } 41 39 42 public void pasteData( DataSetpasteBuffer, Layer source, ActionEvent e) {40 public void pasteData(PrimitiveDeepCopy pasteBuffer, Layer source, ActionEvent e) { 43 41 /* Find the middle of the pasteBuffer area */ 44 42 double maxEast = -1E100, minEast = 1E100, maxNorth = -1E100, minNorth = 1E100; 45 for (Node n : pasteBuffer.nodes) { 46 double east = n.getEastNorth().east(); 47 double north = n.getEastNorth().north(); 48 if (east > maxEast) { maxEast = east; } 49 if (east < minEast) { minEast = east; } 50 if (north > maxNorth) { maxNorth = north; } 51 if (north < minNorth) { minNorth = north; } 43 for (PrimitiveData data : pasteBuffer.getAll()) { 44 if (data instanceof NodeData) { 45 NodeData n = (NodeData)data; 46 double east = n.getEastNorth().east(); 47 double north = n.getEastNorth().north(); 48 if (east > maxEast) { maxEast = east; } 49 if (east < minEast) { minEast = east; } 50 if (north > maxNorth) { maxNorth = north; } 51 if (north < minNorth) { minNorth = north; } 52 } 52 53 } 53 54 … … 63 64 double offsetNorth = mPosition.north() - (maxNorth + minNorth)/2.0; 64 65 65 HashMap<OsmPrimitive,OsmPrimitive> map = new HashMap<OsmPrimitive,OsmPrimitive>();66 /* temporarily maps old nodes to new so we can do a true deep copy */67 66 68 /* do the deep copy of the paste buffer contents, leaving the pasteBuffer unchanged */ 69 for (Node n : pasteBuffer.nodes) { 70 Node nnew = new Node(n); 71 nnew.clearOsmId(); 72 if (Main.map.mapView.getEditLayer() == source) { 73 nnew.setEastNorth(nnew.getEastNorth().add(offsetEast, offsetNorth)); 74 } 75 map.put(n, nnew); 67 68 // Make a copy of pasteBuffer and map from old id to copied data id 69 List<PrimitiveData> bufferCopy = new ArrayList<PrimitiveData>(); 70 Map<Long, Long> newIds = new HashMap<Long, Long>(); 71 for (PrimitiveData data:pasteBuffer.getAll()) { 72 PrimitiveData copy = data.makeCopy(); 73 copy.clearOsmId(); 74 newIds.put(data.getId(), copy.getId()); 75 bufferCopy.add(copy); 76 76 } 77 for (Way w : pasteBuffer.ways) { 78 Way wnew = new Way(); 79 wnew.cloneFrom(w); 80 wnew.clearOsmId(); 81 /* make sure we reference the new nodes corresponding to the old ones */ 82 List<Node> nodes = new ArrayList<Node>(); 83 for (Node n : w.getNodes()) { 84 nodes.add((Node)map.get(n)); 85 } 86 wnew.setNodes(nodes); 87 map.put(w, wnew); 88 } 89 for (Relation r : pasteBuffer.relations) { 90 Relation rnew = new Relation(r); 91 r.clearOsmId(); 92 List<RelationMember> members = new ArrayList<RelationMember>(); 93 for (RelationMember m : r.getMembers()) { 94 OsmPrimitive mo = map.get(m.getMember()); 95 if(mo != null) /* FIXME - This only prevents illegal data, but kills the relation */ 96 { 97 RelationMember mnew = new RelationMember(m.getRole(), map.get(m.getMember())); 98 members.add(mnew); 77 78 // Update references in copied buffer 79 for (PrimitiveData data:bufferCopy) { 80 if (data instanceof NodeData) { 81 NodeData nodeData = (NodeData)data; 82 if (Main.map.mapView.getEditLayer() == source) { 83 nodeData.setEastNorth(nodeData.getEastNorth().add(offsetEast, offsetNorth)); 84 } 85 } else if (data instanceof WayData) { 86 ListIterator<Long> it = ((WayData)data).getNodes().listIterator(); 87 while (it.hasNext()) { 88 it.set(newIds.get(it.next())); 89 } 90 } else if (data instanceof RelationData) { 91 ListIterator<RelationMemberData> it = ((RelationData)data).getMembers().listIterator(); 92 while (it.hasNext()) { 93 RelationMemberData member = it.next(); 94 it.set(new RelationMemberData(member.getRole(), member.getMemberType(), newIds.get(member.getMemberId()))); 99 95 } 100 96 } 101 rnew.setMembers(members);102 map.put(r, rnew);103 97 } 104 98 105 /* Now execute the commands to add the dupicated contents of the paste buffer to the map */ 106 Collection<OsmPrimitive> osms = map.values(); 107 Collection<Command> clist = new LinkedList<Command>(); 108 for (OsmPrimitive osm : osms) { 109 clist.add(new AddCommand(osm)); 110 } 99 /* Now execute the commands to add the duplicated contents of the paste buffer to the map */ 111 100 112 Main.main.undoRedo.add(new SequenceCommand(tr("Paste"), clist));113 getCurrentDataSet().setSelected(osms); 101 Main.main.undoRedo.add(new AddPrimitivesCommand(bufferCopy)); 102 //getCurrentDataSet().setSelected(osms); 114 103 Main.map.mapView.repaint(); 115 104 } … … 121 110 return; 122 111 } 123 setEnabled( 124 !Main.pasteBuffer.nodes.isEmpty() 125 || !Main.pasteBuffer.ways.isEmpty() 126 || !Main.pasteBuffer.relations.isEmpty() 127 ); 112 setEnabled(!Main.pasteBuffer.isEmpty()); 128 113 } 129 114 } -
trunk/src/org/openstreetmap/josm/actions/PasteTagsAction.java
r2256 r2305 18 18 import org.openstreetmap.josm.command.Command; 19 19 import org.openstreetmap.josm.command.SequenceCommand; 20 import org.openstreetmap.josm.data.osm.DataSet;21 import org.openstreetmap.josm.data.osm.Node;22 20 import org.openstreetmap.josm.data.osm.OsmPrimitive; 23 21 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 24 import org.openstreetmap.josm.data.osm.Relation; 22 import org.openstreetmap.josm.data.osm.PrimitiveData; 23 import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy; 25 24 import org.openstreetmap.josm.data.osm.TagCollection; 26 import org.openstreetmap.josm.data.osm.Way;27 25 import org.openstreetmap.josm.gui.conflict.tags.PasteTagsConflictResolverDialog; 28 26 import org.openstreetmap.josm.tools.Shortcut; … … 37 35 } 38 36 39 static private List<Class<? extends OsmPrimitive>> osmPrimitiveClasses; 40 static { 41 osmPrimitiveClasses = new ArrayList<Class<? extends OsmPrimitive>>(); 42 osmPrimitiveClasses.add(Node.class); 43 osmPrimitiveClasses.add(Way.class); 44 osmPrimitiveClasses.add(Relation.class); 45 } 46 47 /** 48 * Replies true if the source for tag pasting is heterogeneous, i.e. if it doesn't consist of 49 * {@see OsmPrimitive}s of exactly one type 50 * 51 * @return 52 */ 53 protected boolean isHeteogeneousSource() { 54 int count = 0; 55 count = !getSourcePrimitivesByType(Node.class).isEmpty() ? count + 1 : count; 56 count = !getSourcePrimitivesByType(Way.class).isEmpty() ? count + 1 : count; 57 count = !getSourcePrimitivesByType(Relation.class).isEmpty() ? count + 1 : count; 58 return count > 1; 59 } 60 61 /** 62 * Replies all primitives of type <code>type</code> in the current selection. 63 * 64 * @param <T> 65 * @param type the type 66 * @return all primitives of type <code>type</code> in the current selection. 67 */ 68 protected <T extends OsmPrimitive> Collection<? extends OsmPrimitive> getSourcePrimitivesByType(Class<T> type) { 69 return OsmPrimitive.getFilteredList(Main.pasteBuffer.getSelected(), type); 70 } 71 72 /** 73 * Replies the collection of tags for all primitives of type <code>type</code> in the current 74 * selection 75 * 76 * @param <T> 77 * @param type the type 78 * @return the collection of tags for all primitives of type <code>type</code> in the current 79 * selection 80 */ 81 protected <T extends OsmPrimitive> TagCollection getSourceTagsByType(Class<T> type) { 82 return TagCollection.unionOfAllPrimitives(getSourcePrimitivesByType(type)); 83 } 84 85 /** 86 * Replies true if there is at least one tag in the current selection for primitives of 87 * type <code>type</code> 88 * 89 * @param <T> 90 * @param type the type 91 * @return true if there is at least one tag in the current selection for primitives of 92 * type <code>type</code> 93 */ 94 protected <T extends OsmPrimitive> boolean hasSourceTagsByType(Class<T> type) { 95 return ! getSourceTagsByType(type).isEmpty(); 96 } 97 98 protected Command buildChangeCommand(Collection<? extends OsmPrimitive> selection, TagCollection tc) { 99 List<Command> commands = new ArrayList<Command>(); 100 for (String key : tc.getKeys()) { 101 String value = tc.getValues(key).iterator().next(); 102 value = value.equals("") ? null : value; 103 commands.add(new ChangePropertyCommand(selection,key,value)); 104 } 105 if (!commands.isEmpty()) { 106 String title1 = trn("Pasting {0} tag", "Pasting {0} tags", tc.getKeys().size(), tc.getKeys().size()); 107 String title2 = trn("to {0} primitive", "to {0} primtives", selection.size(), selection.size()); 108 return new SequenceCommand( 109 title1 + " " + title2, 110 commands 111 ); 112 } 113 return null; 114 } 115 116 protected Map<OsmPrimitiveType, Integer> getSourceStatistics() { 117 HashMap<OsmPrimitiveType, Integer> ret = new HashMap<OsmPrimitiveType, Integer>(); 118 for (Class<? extends OsmPrimitive> type: osmPrimitiveClasses) { 119 if (!getSourceTagsByType(type).isEmpty()) { 120 ret.put(OsmPrimitiveType.from(type), getSourcePrimitivesByType(type).size()); 121 } 122 } 123 return ret; 124 } 125 126 protected Map<OsmPrimitiveType, Integer> getTargetStatistics() { 127 HashMap<OsmPrimitiveType, Integer> ret = new HashMap<OsmPrimitiveType, Integer>(); 128 for (Class<? extends OsmPrimitive> type: osmPrimitiveClasses) { 129 int count = OsmPrimitive.getFilteredList(getEditLayer().data.getSelected(), type).size(); 130 if (count > 0) { 131 ret.put(OsmPrimitiveType.from(type), count); 132 } 133 } 134 return ret; 135 } 136 137 /** 138 * Pastes the tags from a homogeneous source (i.e. the {@see Main#pasteBuffer}s selection consisting 139 * of one type of {@see OsmPrimitive}s only. 140 * 141 * Tags from a homogeneous source can be pasted to a heterogeneous target. All target primitives, 142 * regardless of their type, receive the same tags. 143 * 144 * @param targets the collection of target primitives 145 */ 146 protected void pasteFromHomogeneousSource(Collection<? extends OsmPrimitive> targets) { 147 TagCollection tc = null; 148 for (Class<? extends OsmPrimitive> type : osmPrimitiveClasses) { 149 TagCollection tc1 = getSourceTagsByType(type); 150 if (!tc1.isEmpty()) { 151 tc = tc1; 152 } 153 } 154 if (tc == null) 155 // no tags found to paste. Abort. 156 return; 157 158 if (!tc.isApplicableToPrimitive()) { 159 PasteTagsConflictResolverDialog dialog = new PasteTagsConflictResolverDialog(Main.parent); 160 dialog.populate(tc, getSourceStatistics(), getTargetStatistics()); 161 dialog.setVisible(true); 162 if (dialog.isCanceled()) 37 public static class TagPaster { 38 39 private final Collection<PrimitiveData> source; 40 private final Collection<OsmPrimitive> target; 41 private final List<Command> commands = new ArrayList<Command>(); 42 43 public TagPaster(Collection<PrimitiveData> source, Collection<OsmPrimitive> target) { 44 this.source = source; 45 this.target = target; 46 } 47 48 /** 49 * Replies true if the source for tag pasting is heterogeneous, i.e. if it doesn't consist of 50 * {@see OsmPrimitive}s of exactly one type 51 * 52 * @return 53 */ 54 protected boolean isHeteogeneousSource() { 55 int count = 0; 56 count = !getSourcePrimitivesByType(OsmPrimitiveType.NODE).isEmpty() ? count + 1 : count; 57 count = !getSourcePrimitivesByType(OsmPrimitiveType.WAY).isEmpty() ? count + 1 : count; 58 count = !getSourcePrimitivesByType(OsmPrimitiveType.RELATION).isEmpty() ? count + 1 : count; 59 return count > 1; 60 } 61 62 /** 63 * Replies all primitives of type <code>type</code> in the current selection. 64 * 65 * @param <T> 66 * @param type the type 67 * @return all primitives of type <code>type</code> in the current selection. 68 */ 69 protected <T extends PrimitiveData> Collection<? extends PrimitiveData> getSourcePrimitivesByType(OsmPrimitiveType type) { 70 return PrimitiveData.getFilteredList(source, type); 71 } 72 73 /** 74 * Replies the collection of tags for all primitives of type <code>type</code> in the current 75 * selection 76 * 77 * @param <T> 78 * @param type the type 79 * @return the collection of tags for all primitives of type <code>type</code> in the current 80 * selection 81 */ 82 protected <T extends OsmPrimitive> TagCollection getSourceTagsByType(OsmPrimitiveType type) { 83 return TagCollection.unionOfAllPrimitives(getSourcePrimitivesByType(type)); 84 } 85 86 /** 87 * Replies true if there is at least one tag in the current selection for primitives of 88 * type <code>type</code> 89 * 90 * @param <T> 91 * @param type the type 92 * @return true if there is at least one tag in the current selection for primitives of 93 * type <code>type</code> 94 */ 95 protected <T extends OsmPrimitive> boolean hasSourceTagsByType(OsmPrimitiveType type) { 96 return ! getSourceTagsByType(type).isEmpty(); 97 } 98 99 protected Command buildChangeCommand(Collection<? extends OsmPrimitive> selection, TagCollection tc) { 100 List<Command> commands = new ArrayList<Command>(); 101 for (String key : tc.getKeys()) { 102 String value = tc.getValues(key).iterator().next(); 103 value = value.equals("") ? null : value; 104 commands.add(new ChangePropertyCommand(selection,key,value)); 105 } 106 if (!commands.isEmpty()) { 107 String title1 = trn("Pasting {0} tag", "Pasting {0} tags", tc.getKeys().size(), tc.getKeys().size()); 108 String title2 = trn("to {0} primitive", "to {0} primtives", selection.size(), selection.size()); 109 return new SequenceCommand( 110 title1 + " " + title2, 111 commands 112 ); 113 } 114 return null; 115 } 116 117 protected Map<OsmPrimitiveType, Integer> getSourceStatistics() { 118 HashMap<OsmPrimitiveType, Integer> ret = new HashMap<OsmPrimitiveType, Integer>(); 119 for (OsmPrimitiveType type: OsmPrimitiveType.values()) { 120 if (!getSourceTagsByType(type).isEmpty()) { 121 ret.put(type, getSourcePrimitivesByType(type).size()); 122 } 123 } 124 return ret; 125 } 126 127 protected Map<OsmPrimitiveType, Integer> getTargetStatistics() { 128 HashMap<OsmPrimitiveType, Integer> ret = new HashMap<OsmPrimitiveType, Integer>(); 129 for (OsmPrimitiveType type: OsmPrimitiveType.values()) { 130 int count = OsmPrimitive.getFilteredList(target, type.getOsmClass()).size(); 131 if (count > 0) { 132 ret.put(type, count); 133 } 134 } 135 return ret; 136 } 137 138 /** 139 * Pastes the tags from a homogeneous source (i.e. the {@see Main#pasteBuffer}s selection consisting 140 * of one type of {@see OsmPrimitive}s only. 141 * 142 * Tags from a homogeneous source can be pasted to a heterogeneous target. All target primitives, 143 * regardless of their type, receive the same tags. 144 * 145 * @param targets the collection of target primitives 146 */ 147 protected void pasteFromHomogeneousSource() { 148 TagCollection tc = null; 149 for (OsmPrimitiveType type : OsmPrimitiveType.values()) { 150 TagCollection tc1 = getSourceTagsByType(type); 151 if (!tc1.isEmpty()) { 152 tc = tc1; 153 } 154 } 155 if (tc == null) 156 // no tags found to paste. Abort. 163 157 return; 164 Command cmd = buildChangeCommand(targets, dialog.getResolution()); 165 Main.main.undoRedo.add(cmd);166 } else {167 // no conflicts in the source tags to resolve. Just apply the tags168 // to the target primitives169 //170 Command cmd = buildChangeCommand(targets, tc);171 Main.main.undoRedo.add(cmd);172 }173 }174 175 /**176 * Replies true if there is at least one primitive of type <code>type</code> in the collection177 * <code>selection</code>178 *179 * @param <T>180 * @param selection the collection of primitives181 * @param type the type to look for 182 * @return true if there is at least one primitive of type <code>type</code> in the collection183 *<code>selection</code>184 */185 protected <T extends OsmPrimitive> boolean hasTargetPrimitives(Collection<OsmPrimitive> selection, Class<T> type) {186 return !OsmPrimitive.getFilteredList(selection, type).isEmpty();187 }188 189 /**190 * Replies true if this a heterogeneous source can be pasted without conflict to targets191 *192 * @param targets the collection of target primitives193 * @returntrue if this a heterogeneous source can be pasted without conflicts to targets194 */195 protected boolean canPasteFromHeterogeneousSourceWithoutConflict(Collection<OsmPrimitive> targets) { 196 if (hasTargetPrimitives(targets, Node.class)) {197 TagCollection tc = TagCollection.unionOfAllPrimitives(getSourcePrimitivesByType(Node.class));198 if (!tc.isEmpty() && ! tc.isApplicableToPrimitive())199 return false;200 }201 if (hasTargetPrimitives(targets, Way.class)) {202 TagCollectiontc = TagCollection.unionOfAllPrimitives(getSourcePrimitivesByType(Way.class));203 if (!tc.isEmpty() && ! tc.isApplicableToPrimitive())204 return false;205 }206 if (hasTargetPrimitives(targets, Relation.class)) {207 TagCollection tc = TagCollection.unionOfAllPrimitives(getSourcePrimitivesByType(Relation.class));208 if (!tc.isEmpty() && ! tc.isApplicableToPrimitive())209 return false;210 }211 return true;212 } 213 214 /**215 * Pastes the tags in the current selection of the paste buffer to a set of target216 * primitives.217 *218 * @param targets the collection of target primitives219 */220 protected void pasteFromHeterogeneousSource(Collection<OsmPrimitive> targets) {221 if (canPasteFromHeterogeneousSourceWithoutConflict(targets)) {222 if (hasSourceTagsByType( Node.class) && hasTargetPrimitives(targets, Node.class)) {223 Command cmd = buildChangeCommand(target s, getSourceTagsByType(Node.class));224 Main.main.undoRedo.add(cmd);225 } 226 if (hasSourceTagsByType(Way.class) && hasTargetPrimitives(targets, Way.class)) {227 Command cmd = buildChangeCommand(targets, getSourceTagsByType(Way.class));228 Main.main.undoRedo.add(cmd);229 }230 if (hasSourceTagsByType(Relation.class) && hasTargetPrimitives(targets, Relation.class)) {231 Command cmd = buildChangeCommand(targets,getSourceTagsByType(Relation.class));232 Main.main.undoRedo.add(cmd);233 }234 } else {235 PasteTagsConflictResolverDialog dialog = new PasteTagsConflictResolverDialog(Main.parent);236 dialog. populate(237 getSourceTagsByType(Node.class),238 getSourceTagsByType(Way.class),239 getSourceTagsByType(Relation.class),240 getSourceStatistics(),241 getTargetStatistics()242 ); 243 dialog.setVisible(true);244 if (dialog.isCanceled())245 return;246 if (hasSourceTagsByType(Node.class) && hasTargetPrimitives(targets, Node.class)) {247 Command cmd = buildChangeCommand(OsmPrimitive.getFilteredList(targets, Node.class), dialog.getResolution(OsmPrimitiveType.NODE)); 248 Main.main.undoRedo.add(cmd);249 }250 if ( hasSourceTagsByType(Way.class) && hasTargetPrimitives(targets, Way.class)) {251 Command cmd = buildChangeCommand(OsmPrimitive.getFilteredList(targets, Way.class), dialog.getResolution(OsmPrimitiveType.WAY));252 Main.main.undoRedo.add(cmd);253 }254 if (hasSourceTagsByType(Relation.class) && hasTargetPrimitives(targets, Relation.class)) {255 Command cmd = buildChangeCommand(OsmPrimitive.getFilteredList(targets, Relation.class), dialog.getResolution(OsmPrimitiveType.RELATION));256 Main.main.undoRedo.add(cmd);257 } 258 }259 } 158 159 if (!tc.isApplicableToPrimitive()) { 160 PasteTagsConflictResolverDialog dialog = new PasteTagsConflictResolverDialog(Main.parent); 161 dialog.populate(tc, getSourceStatistics(), getTargetStatistics()); 162 dialog.setVisible(true); 163 if (dialog.isCanceled()) 164 return; 165 Command cmd = buildChangeCommand(target, dialog.getResolution()); 166 commands.add(cmd); 167 } else { 168 // no conflicts in the source tags to resolve. Just apply the tags 169 // to the target primitives 170 // 171 Command cmd = buildChangeCommand(target, tc); 172 commands.add(cmd); 173 } 174 } 175 176 /** 177 * Replies true if there is at least one primitive of type <code>type</code> in the collection 178 * <code>selection</code> 179 * 180 * @param <T> 181 * @param selection the collection of primitives 182 * @param type the type to look for 183 * @return true if there is at least one primitive of type <code>type</code> in the collection 184 * <code>selection</code> 185 */ 186 protected <T extends OsmPrimitive> boolean hasTargetPrimitives(Class<T> type) { 187 return !OsmPrimitive.getFilteredList(target, type).isEmpty(); 188 } 189 190 /** 191 * Replies true if this a heterogeneous source can be pasted without conflict to targets 192 * 193 * @param targets the collection of target primitives 194 * @return true if this a heterogeneous source can be pasted without conflicts to targets 195 */ 196 protected boolean canPasteFromHeterogeneousSourceWithoutConflict(Collection<OsmPrimitive> targets) { 197 for (OsmPrimitiveType type:OsmPrimitiveType.values()) { 198 if (hasTargetPrimitives(type.getOsmClass())) { 199 TagCollection tc = TagCollection.unionOfAllPrimitives(getSourcePrimitivesByType(type)); 200 if (!tc.isEmpty() && ! tc.isApplicableToPrimitive()) 201 return false; 202 } 203 } 204 return true; 205 } 206 207 /** 208 * Pastes the tags in the current selection of the paste buffer to a set of target 209 * primitives. 210 * 211 * @param targets the collection of target primitives 212 */ 213 protected void pasteFromHeterogeneousSource() { 214 if (canPasteFromHeterogeneousSourceWithoutConflict(target)) { 215 for (OsmPrimitiveType type:OsmPrimitiveType.values()) { 216 if (hasSourceTagsByType(type) && hasTargetPrimitives(type.getOsmClass())) { 217 Command cmd = buildChangeCommand(target, getSourceTagsByType(type)); 218 commands.add(cmd); 219 } 220 } 221 } else { 222 PasteTagsConflictResolverDialog dialog = new PasteTagsConflictResolverDialog(Main.parent); 223 dialog.populate( 224 getSourceTagsByType(OsmPrimitiveType.NODE), 225 getSourceTagsByType(OsmPrimitiveType.WAY), 226 getSourceTagsByType(OsmPrimitiveType.RELATION), 227 getSourceStatistics(), 228 getTargetStatistics() 229 ); 230 dialog.setVisible(true); 231 if (dialog.isCanceled()) 232 return; 233 for (OsmPrimitiveType type:OsmPrimitiveType.values()) { 234 if (hasSourceTagsByType(type) && hasTargetPrimitives(type.getOsmClass())) { 235 Command cmd = buildChangeCommand(OsmPrimitive.getFilteredList(target, type.getOsmClass()), dialog.getResolution(type)); 236 commands.add(cmd); 237 } 238 } 239 } 240 } 241 242 public List<Command> execute() { 243 commands.clear(); 244 if (isHeteogeneousSource()) { 245 pasteFromHeterogeneousSource(); 246 } else { 247 pasteFromHomogeneousSource(); 248 } 249 return commands; 250 } 251 252 } 253 260 254 261 255 public void actionPerformed(ActionEvent e) { 262 256 if (getCurrentDataSet().getSelected().isEmpty()) 263 257 return; 264 if (isHeteogeneousSource()) { 265 pasteFromHeterogeneousSource(getCurrentDataSet().getSelected()); 266 } else { 267 pasteFromHomogeneousSource(getCurrentDataSet().getSelected()); 268 } 269 } 270 271 @Override public void pasteBufferChanged(DataSet newPasteBuffer) { 258 TagPaster tagPaster = new TagPaster(Main.pasteBuffer.getDirectlyAdded(), getCurrentDataSet().getSelected()); 259 for (Command c:tagPaster.execute()) { 260 Main.main.undoRedo.add(c); 261 } 262 } 263 264 @Override public void pasteBufferChanged(PrimitiveDeepCopy newPasteBuffer) { 272 265 updateEnabledState(); 273 266 } … … 281 274 setEnabled( 282 275 !getCurrentDataSet().getSelected().isEmpty() 283 && !TagCollection.unionOfAllPrimitives(Main.pasteBuffer.get Selected()).isEmpty()276 && !TagCollection.unionOfAllPrimitives(Main.pasteBuffer.getDirectlyAdded()).isEmpty() 284 277 ); 285 278 } … … 289 282 setEnabled( 290 283 selection!= null && !selection.isEmpty() 291 && !TagCollection.unionOfAllPrimitives(Main.pasteBuffer.get Selected()).isEmpty()284 && !TagCollection.unionOfAllPrimitives(Main.pasteBuffer.getDirectlyAdded()).isEmpty() 292 285 ); 293 286 }
Note:
See TracChangeset
for help on using the changeset viewer.
