Changeset 2008 in josm
- Timestamp:
- 2009-08-30T15:41:28+02:00 (15 years ago)
- Location:
- trunk
- Files:
-
- 17 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/AboutAction.java
r1986 r2008 67 67 } 68 68 revision = loadFile(u, manifest); 69 System.out.println("Revision: " + revision.getText()); 69 70 70 71 Pattern versionPattern = Pattern.compile(".*?(?:Revision|Main-Version): ([0-9]*(?: SVN)?).*", Pattern.CASE_INSENSITIVE|Pattern.DOTALL); -
trunk/src/org/openstreetmap/josm/actions/CopyAction.java
r1937 r2008 17 17 import org.openstreetmap.josm.Main; 18 18 import org.openstreetmap.josm.data.osm.DataSet; 19 import org.openstreetmap.josm.data.osm.DataSource;20 19 import org.openstreetmap.josm.data.osm.Node; 21 20 import org.openstreetmap.josm.data.osm.OsmPrimitive; … … 24 23 import org.openstreetmap.josm.data.osm.Way; 25 24 import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor; 26 import org.openstreetmap.josm.gui.OptionPaneUtil;27 25 import org.openstreetmap.josm.tools.Shortcut; 28 26 … … 110 108 osm.visit(this); 111 109 } 112 113 // Used internally only (in PasteTagsAction), therefore no need to translate these114 if(getCurrentDataSet().getSelectedNodes().size() > 0) {115 pasteBuffer.dataSources.add(new DataSource(null, "Copied Nodes"));116 }117 if(getCurrentDataSet().getSelectedWays().size() > 0) {118 pasteBuffer.dataSources.add(new DataSource(null, "Copied Ways"));119 }120 if(getCurrentDataSet().getSelectedRelations().size() > 0) {121 pasteBuffer.dataSources.add(new DataSource(null, "Copied Relations"));122 }123 110 } 124 111 }.visitAll(); … … 135 122 Collection<OsmPrimitive> sel = getCurrentDataSet().getSelected(); 136 123 if (sel.isEmpty()) { 137 OptionPane Util.showMessageDialog(124 JOptionPane.showMessageDialog( 138 125 Main.parent, 139 126 tr("Please select something to copy."), -
trunk/src/org/openstreetmap/josm/actions/PasteTagsAction.java
r1924 r2008 4 4 5 5 import static org.openstreetmap.josm.tools.I18n.tr; 6 import static org.openstreetmap.josm.tools.I18n.trn; 6 7 7 8 import java.awt.event.ActionEvent; 8 9 import java.awt.event.KeyEvent; 10 import java.util.ArrayList; 9 11 import java.util.Collection; 10 12 import java.util.HashMap; 11 import java.util.Iterator; 12 import java.util.LinkedList; 13 import java.util.List; 13 14 import java.util.Map; 14 15 … … 18 19 import org.openstreetmap.josm.command.SequenceCommand; 19 20 import org.openstreetmap.josm.data.osm.DataSet; 20 import org.openstreetmap.josm.data.osm. DataSource;21 import org.openstreetmap.josm.data.osm.Node; 21 22 import org.openstreetmap.josm.data.osm.OsmPrimitive; 23 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 24 import org.openstreetmap.josm.data.osm.Relation; 25 import org.openstreetmap.josm.data.osm.TagCollection; 26 import org.openstreetmap.josm.data.osm.Way; 27 import org.openstreetmap.josm.gui.conflict.tags.PasteTagsConflictResolverDialog; 22 28 import org.openstreetmap.josm.tools.Shortcut; 23 29 … … 31 37 } 32 38 33 private void pasteKeys(Collection<Command> clist, Collection<? extends OsmPrimitive> pasteBufferSubset, Collection<OsmPrimitive> selectionSubset) { 34 /* scan the paste buffer, and add tags to each of the selected objects. 35 * If a tag already exists, it is overwritten */ 36 if (selectionSubset == null || selectionSubset.isEmpty()) 39 /** 40 * Replies true if the source for tag pasting is heterogeneous, i.e. if it doesn't consist of 41 * {@see OsmPrimitive}s of exactly one type 42 * 43 * @return 44 */ 45 protected boolean isHeteogeneousSource() { 46 int count = 0; 47 count = !getSourcePrimitivesByType(Node.class).isEmpty() ? count + 1 : count; 48 count = !getSourcePrimitivesByType(Way.class).isEmpty() ? count + 1 : count; 49 count = !getSourcePrimitivesByType(Relation.class).isEmpty() ? count + 1 : count; 50 return count > 1; 51 } 52 53 /** 54 * Replies the subset of {@see OsmPrimitive}s of <code>type</code> from <code>superSet</code>. 55 * 56 * @param <T> 57 * @param superSet the super set of primitives 58 * @param type the type 59 * @return 60 */ 61 protected <T extends OsmPrimitive> Collection<? extends OsmPrimitive> getSubcollectionByType(Collection<? extends OsmPrimitive> superSet, Class<T> type) { 62 Collection<OsmPrimitive> ret = new ArrayList<OsmPrimitive>(); 63 for (OsmPrimitive p : superSet) { 64 if (type.isInstance(p)) { 65 ret.add(p); 66 } 67 } 68 return ret; 69 } 70 71 /** 72 * Replies all primitives of type <code>type</code> in the current selection. 73 * 74 * @param <T> 75 * @param type the type 76 * @return all primitives of type <code>type</code> in the current selection. 77 */ 78 protected <T extends OsmPrimitive> Collection<? extends OsmPrimitive> getSourcePrimitivesByType(Class<T> type) { 79 return getSubcollectionByType(Main.pasteBuffer.getSelected(), type); 80 } 81 82 /** 83 * Replies the collection of tags for all primitives of type <code>type</code> in the current 84 * selection 85 * 86 * @param <T> 87 * @param type the type 88 * @return the collection of tags for all primitives of type <code>type</code> in the current 89 * selection 90 */ 91 protected <T extends OsmPrimitive> TagCollection getSourceTagsByType(Class<T> type) { 92 return TagCollection.unionOfAllPrimitives(getSourcePrimitivesByType(type)); 93 } 94 95 /** 96 * Replies true if there is at least one tag in the current selection for primitives of 97 * type <code>type</code> 98 * 99 * @param <T> 100 * @param type the type 101 * @return true if there is at least one tag in the current selection for primitives of 102 * type <code>type</code> 103 */ 104 protected <T extends OsmPrimitive> boolean hasSourceTagsByType(Class<T> type) { 105 return ! getSourceTagsByType(type).isEmpty(); 106 } 107 108 protected Command buildChangeCommand(Collection<? extends OsmPrimitive> selection, TagCollection tc) { 109 List<Command> commands = new ArrayList<Command>(); 110 for (String key : tc.getKeys()) { 111 String value = tc.getValues(key).iterator().next(); 112 value = value.equals("") ? null : value; 113 commands.add(new ChangePropertyCommand(selection,key,value)); 114 } 115 if (!commands.isEmpty()) { 116 String title1 = trn("Pasting {0} tag", "Pasting {0} tags", tc.getKeys().size(), tc.getKeys().size()); 117 String title2 = trn("to {0} primitive", "to {0} primtives", selection.size(), selection.size()); 118 return new SequenceCommand( 119 title1 + " " + title2, 120 commands 121 ); 122 } 123 return null; 124 } 125 126 protected Map<OsmPrimitiveType, Integer> getSourceStatistics() { 127 HashMap<OsmPrimitiveType, Integer> ret = new HashMap<OsmPrimitiveType, Integer>(); 128 for (Class type: new Class[] {Node.class, Way.class, Relation.class}) { 129 if (!getSourceTagsByType(type).isEmpty()) { 130 ret.put(OsmPrimitiveType.from(type), getSourcePrimitivesByType(type).size()); 131 } 132 } 133 return ret; 134 } 135 136 protected Map<OsmPrimitiveType, Integer> getTargetStatistics() { 137 HashMap<OsmPrimitiveType, Integer> ret = new HashMap<OsmPrimitiveType, Integer>(); 138 for (Class type: new Class[] {Node.class, Way.class, Relation.class}) { 139 int count = getSubcollectionByType(getEditLayer().data.getSelected(), type).size(); 140 if (count > 0) { 141 ret.put(OsmPrimitiveType.from(type), count); 142 } 143 } 144 return ret; 145 } 146 147 /** 148 * Pastes the tags from a homogeneous source (i.e. the {@see Main#pasteBuffer}s selection consisting 149 * of one type of {@see OsmPrimitive}s only. 150 * 151 * Tags from a homogeneous source can be pasted to a heterogeneous target. All target primitives, 152 * regardless of their type, receive the same tags. 153 * 154 * @param targets the collection of target primitives 155 */ 156 protected void pasteFromHomogeneousSource(Collection<? extends OsmPrimitive> targets) { 157 TagCollection tc = null; 158 Class sourceType = null; 159 for (Class type : new Class[] {Node.class, Way.class, Relation.class}) { 160 TagCollection tc1 = getSourceTagsByType(type); 161 if (!tc1.isEmpty()) { 162 tc = tc1; 163 sourceType = type; 164 } 165 } 166 if (tc == null) 167 // no tags found to paste. Abort. 37 168 return; 38 169 39 for (Iterator<? extends OsmPrimitive> it = pasteBufferSubset.iterator(); it.hasNext();) { 40 OsmPrimitive osm = it.next(); 41 42 for (String key : osm.keySet()) { 43 clist.add(new ChangePropertyCommand(selectionSubset, key, osm.get(key))); 170 171 if (!tc.isApplicableToPrimitive()) { 172 PasteTagsConflictResolverDialog dialog = new PasteTagsConflictResolverDialog(Main.parent); 173 dialog.populate(tc, getSourceStatistics(), getTargetStatistics()); 174 dialog.setVisible(true); 175 if (dialog.isCanceled()) 176 return; 177 Command cmd = buildChangeCommand(targets, dialog.getResolution()); 178 Main.main.undoRedo.add(cmd); 179 } else { 180 // no conflicts in the source tags to resolve. Just apply the tags 181 // to the target primitives 182 // 183 Command cmd = buildChangeCommand(targets, tc); 184 Main.main.undoRedo.add(cmd); 185 } 186 } 187 188 /** 189 * Replies true if there is at least one primitive of type <code>type</code> in the collection 190 * <code>selection</code> 191 * 192 * @param <T> 193 * @param selection the collection of primitives 194 * @param type the type to look for 195 * @return true if there is at least one primitive of type <code>type</code> in the collection 196 * <code>selection</code> 197 */ 198 protected <T extends OsmPrimitive> boolean hasTargetPrimitives(Collection<? extends OsmPrimitive> selection, Class<T> type) { 199 return !getSubcollectionByType(selection, type).isEmpty(); 200 } 201 202 /** 203 * Replies true if this a heterogeneous source can be pasted without conflict to targets 204 * 205 * @param targets the collection of target primitives 206 * @return true if this a heterogeneous source can be pasted without conflicts to targets 207 */ 208 protected boolean canPasteFromHeterogeneousSourceWithoutConflict(Collection<? extends OsmPrimitive> targets) { 209 if (hasTargetPrimitives(targets, Node.class)) { 210 TagCollection tc = TagCollection.unionOfAllPrimitives(getSourcePrimitivesByType(Node.class)); 211 if (!tc.isEmpty() && ! tc.isApplicableToPrimitive()) 212 return false; 213 } 214 if (hasTargetPrimitives(targets, Way.class)) { 215 TagCollection tc = TagCollection.unionOfAllPrimitives(getSourcePrimitivesByType(Way.class)); 216 if (!tc.isEmpty() && ! tc.isApplicableToPrimitive()) 217 return false; 218 } 219 if (hasTargetPrimitives(targets, Relation.class)) { 220 TagCollection tc = TagCollection.unionOfAllPrimitives(getSourcePrimitivesByType(Relation.class)); 221 if (!tc.isEmpty() && ! tc.isApplicableToPrimitive()) 222 return false; 223 } 224 return true; 225 } 226 227 /** 228 * Pastes the tags in the current selection of the paste buffer to a set of target 229 * primitives. 230 * 231 * @param targets the collection of target primitives 232 */ 233 protected void pasteFromHeterogeneousSource(Collection<? extends OsmPrimitive> targets) { 234 if (canPasteFromHeterogeneousSourceWithoutConflict(targets)) { 235 if (hasSourceTagsByType(Node.class) && hasTargetPrimitives(targets, Node.class)) { 236 Command cmd = buildChangeCommand(targets, getSourceTagsByType(Node.class)); 237 Main.main.undoRedo.add(cmd); 238 } 239 if (hasSourceTagsByType(Way.class) && hasTargetPrimitives(targets, Way.class)) { 240 Command cmd = buildChangeCommand(targets, getSourceTagsByType(Way.class)); 241 Main.main.undoRedo.add(cmd); 242 } 243 if (hasSourceTagsByType(Relation.class) && hasTargetPrimitives(targets, Relation.class)) { 244 Command cmd = buildChangeCommand(targets,getSourceTagsByType(Relation.class)); 245 Main.main.undoRedo.add(cmd); 246 } 247 } else { 248 PasteTagsConflictResolverDialog dialog = new PasteTagsConflictResolverDialog(Main.parent); 249 dialog.populate( 250 getSourceTagsByType(Node.class), 251 getSourceTagsByType(Way.class), 252 getSourceTagsByType(Relation.class), 253 getSourceStatistics(), 254 getTargetStatistics() 255 ); 256 dialog.setVisible(true); 257 if (dialog.isCanceled()) 258 return; 259 if (hasSourceTagsByType(Node.class) && hasTargetPrimitives(targets, Node.class)) { 260 Command cmd = buildChangeCommand(getSubcollectionByType(targets, Node.class), dialog.getResolution(OsmPrimitiveType.NODE)); 261 Main.main.undoRedo.add(cmd); 262 } 263 if (hasSourceTagsByType(Way.class) && hasTargetPrimitives(targets, Way.class)) { 264 Command cmd = buildChangeCommand(getSubcollectionByType(targets, Way.class), dialog.getResolution(OsmPrimitiveType.WAY)); 265 Main.main.undoRedo.add(cmd); 266 } 267 if (hasSourceTagsByType(Relation.class) && hasTargetPrimitives(targets, Relation.class)) { 268 Command cmd = buildChangeCommand(getSubcollectionByType(targets, Relation.class), dialog.getResolution(OsmPrimitiveType.RELATION)); 269 Main.main.undoRedo.add(cmd); 44 270 } 45 271 } … … 47 273 48 274 public void actionPerformed(ActionEvent e) { 49 Collection<Command> clist = new LinkedList<Command>(); 50 String pbSource = "Multiple Sources"; 51 if(Main.pasteBuffer.dataSources.size() == 1) { 52 pbSource = ((DataSource) Main.pasteBuffer.dataSources.toArray()[0]).origin; 53 } 54 55 boolean pbNodes = Main.pasteBuffer.nodes.size() > 0; 56 boolean pbWays = Main.pasteBuffer.ways.size() > 0; 57 58 boolean seNodes = getCurrentDataSet().getSelectedNodes().size() > 0; 59 boolean seWays = getCurrentDataSet().getSelectedWays().size() > 0; 60 boolean seRels = getCurrentDataSet().getSelectedRelations().size() > 0; 61 62 if(!seNodes && seWays && !seRels && pbNodes && pbSource.equals("Copied Nodes")) { 63 // Copy from nodes to ways 64 pasteKeys(clist, Main.pasteBuffer.nodes, getCurrentDataSet().getSelectedWays()); 65 } else if(seNodes && !seWays && !seRels && pbWays && pbSource.equals("Copied Ways")) { 66 // Copy from ways to nodes 67 pasteKeys(clist, Main.pasteBuffer.ways, getCurrentDataSet().getSelectedNodes()); 275 if (getCurrentDataSet().getSelected().isEmpty()) 276 return; 277 if (isHeteogeneousSource()) { 278 pasteFromHeterogeneousSource(getCurrentDataSet().getSelected()); 68 279 } else { 69 // Copy from equal to equal 70 pasteKeys(clist, Main.pasteBuffer.nodes, getCurrentDataSet().getSelectedNodes()); 71 pasteKeys(clist, Main.pasteBuffer.ways, getCurrentDataSet().getSelectedWays()); 72 pasteKeys(clist, Main.pasteBuffer.relations, getCurrentDataSet().getSelectedRelations()); 73 } 74 Main.main.undoRedo.add(new SequenceCommand(tr("Paste Tags"), clist)); 75 getCurrentDataSet().setSelected(getCurrentDataSet().getSelected()); // to force selection listeners, in particular the tag panel, to update 76 Main.map.mapView.repaint(); 77 } 78 79 private boolean containsSameKeysWithDifferentValues(Collection<? extends OsmPrimitive> osms) { 80 Map<String,String> kvSeen = new HashMap<String,String>(); 81 for (OsmPrimitive osm:osms) { 82 for (String key : osm.keySet()) { 83 String value = osm.get(key); 84 if (! kvSeen.containsKey(key)) { 85 kvSeen.put(key, value); 86 } else if (! kvSeen.get(key).equals(value)) 87 return true; 88 } 89 } 90 return false; 91 } 92 93 /** 94 * Determines whether to enable the widget depending on the contents of the paste 95 * buffer and current selection 96 * @param pasteBuffer 97 */ 98 private void possiblyEnable(Collection<? extends OsmPrimitive> selection, DataSet pasteBuffer) { 99 /* only enable if there is something selected to paste into and 100 if we don't have conflicting keys in the pastebuffer */ 101 DataSet ds = getCurrentDataSet(); 102 if (ds == null || ds.getSelected().isEmpty() || pasteBuffer == null || pasteBuffer.allPrimitives().isEmpty()) { 103 setEnabled(false); 104 return; 105 } 106 setEnabled((!ds.getSelectedNodes().isEmpty() && ! containsSameKeysWithDifferentValues(pasteBuffer.nodes)) || 107 (!ds.getSelectedWays().isEmpty() && ! containsSameKeysWithDifferentValues(pasteBuffer.ways)) || 108 (! ds.getSelectedRelations().isEmpty() && ! containsSameKeysWithDifferentValues(pasteBuffer.relations))); 280 pasteFromHomogeneousSource(getCurrentDataSet().getSelected()); 281 } 109 282 } 110 283 … … 119 292 return; 120 293 } 121 possiblyEnable(getCurrentDataSet().getSelected(), Main.pasteBuffer); 294 setEnabled( 295 !getCurrentDataSet().getSelected().isEmpty() 296 && !TagCollection.unionOfAllPrimitives(Main.pasteBuffer.getSelected()).isEmpty() 297 ); 122 298 } 123 299 } -
trunk/src/org/openstreetmap/josm/command/ChangePropertyCommand.java
r1990 r2008 100 100 if (value == null) { 101 101 switch(OsmPrimitiveType.from(primitive)) { 102 case NODE: msg = marktr("Remove \"{0}\" for node ''{1}''"); break; 103 case WAY: msg = marktr("Remove \"{0}\" for way ''{1}''"); break; 104 case RELATION: msg = marktr("Remove \"{0}\" for relation ''{1}''"); break; 102 case NODE: msg = marktr("Remove \"{0}\" for node ''{1}''"); break; 103 case WAY: msg = marktr("Remove \"{0}\" for way ''{1}''"); break; 104 case RELATION: msg = marktr("Remove \"{0}\" for relation ''{1}''"); break; 105 105 } 106 106 text = tr(msg, key, primitive.getDisplayName(DefaultNameFormatter.getInstance())); 107 107 } else { 108 108 switch(OsmPrimitiveType.from(primitive)) { 109 case NODE: msg = marktr("Set {0}={1} for node ''{2}''"); break; 110 case WAY: msg = marktr("Set {0}={1} for way ''{2}''"); break; 111 case RELATION: msg = marktr("Set {0}={1} for relation ''{2}''"); break; 109 case NODE: msg = marktr("Set {0}={1} for node ''{2}''"); break; 110 case WAY: msg = marktr("Set {0}={1} for way ''{2}''"); break; 111 case RELATION: msg = marktr("Set {0}={1} for relation ''{2}''"); break; 112 112 } 113 113 text = tr(msg, key, value, primitive.getDisplayName(DefaultNameFormatter.getInstance())); 114 114 } 115 } 116 else 117 { 115 } else { 118 116 text = value == null 119 117 ? tr("Remove \"{0}\" for {1} {2}", key, objects.size(), trn("object","objects",objects.size()))
Note:
See TracChangeset
for help on using the changeset viewer.