Changeset 2308 in josm for trunk/src/org/openstreetmap
- Timestamp:
- 2009-10-25T12:05:31+01:00 (15 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 5 added
- 23 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/AboutAction.java
r2081 r2308 93 93 static public void setUserAgent() { 94 94 Properties sysProp = System.getProperties(); 95 sysProp.put("http.agent", "JOSM/1.5 ("+(version.equals(tr("UNKNOWN"))?"UNKNOWN":version)+" "+LanguageInfo.get LanguageCode()+")");95 sysProp.put("http.agent", "JOSM/1.5 ("+(version.equals(tr("UNKNOWN"))?"UNKNOWN":version)+" "+LanguageInfo.getJOSMLocaleCode()+")"); 96 96 System.setProperties(sysProp); 97 97 } -
trunk/src/org/openstreetmap/josm/actions/CombineWayAction.java
r2273 r2308 107 107 TagCollection wayTags = TagCollection.unionOfAllPrimitives(ways); 108 108 109 110 109 // try to build a new way which includes all the combined 111 110 // ways -
trunk/src/org/openstreetmap/josm/actions/HelpAction.java
r2274 r2308 9 9 10 10 import javax.swing.AbstractAction; 11 import javax.swing.AbstractButton;12 import javax.swing.Action;13 import javax.swing.JComponent;14 import javax.swing.JMenu;15 11 import javax.swing.SwingUtilities; 16 12 17 13 import org.openstreetmap.josm.Main; 18 14 import org.openstreetmap.josm.gui.help.HelpBrowserProxy; 19 import org.openstreetmap.josm.gui.help.Help ful;15 import org.openstreetmap.josm.gui.help.HelpUtil; 20 16 import org.openstreetmap.josm.tools.ImageProvider; 21 17 … … 23 19 * Open a help browser and displays lightweight online help. 24 20 * 25 * @author imi26 21 */ 27 22 public class HelpAction extends AbstractAction { 28 29 30 private String pathhelp = Main.pref.get("help.pathhelp", "Help/");31 private String pathmenu = Main.pref.get("help.pathmenu", "Menu/");32 23 33 24 public HelpAction() { … … 43 34 if (mouse != null) { 44 35 c = SwingUtilities.getDeepestComponentAt(c, mouse.x, mouse.y); 45 topic = contextSensitiveHelp(c);36 topic = HelpUtil.getContextSpecificHelpTopic(c); 46 37 } else { 47 38 topic = null; … … 49 40 } else { 50 41 Point mouse = Main.parent.getMousePosition(); 51 topic = contextSensitiveHelp(SwingUtilities.getDeepestComponentAt(Main.parent, mouse.x, mouse.y));42 topic = HelpUtil.getContextSpecificHelpTopic(SwingUtilities.getDeepestComponentAt(Main.parent, mouse.x, mouse.y)); 52 43 } 53 44 if (topic == null) { 54 HelpBrowserProxy.getInstance().setUrlForHelpTopic(" Help");45 HelpBrowserProxy.getInstance().setUrlForHelpTopic("/"); 55 46 } else { 56 help(topic);47 HelpBrowserProxy.getInstance().setUrlForHelpTopic(topic); 57 48 } 58 49 } else { 59 HelpBrowserProxy.getInstance().setUrlForHelpTopic(" Help");50 HelpBrowserProxy.getInstance().setUrlForHelpTopic("/"); 60 51 } 61 52 } 62 63 /**64 * @return The topic of the help. <code>null</code> for "don't know"65 */66 private String contextSensitiveHelp(Object c) {67 if (c == null)68 return null;69 if (c instanceof Helpful)70 return ((Helpful)c).helpTopic();71 if (c instanceof JMenu) {72 JMenu b = (JMenu)c;73 if (b.getClientProperty("help") != null)74 return (String)b.getClientProperty("help");75 return pathmenu+b.getText();76 }77 if (c instanceof AbstractButton) {78 AbstractButton b = (AbstractButton)c;79 if (b.getClientProperty("help") != null)80 return (String)b.getClientProperty("help");81 return contextSensitiveHelp(((AbstractButton)c).getAction());82 }83 if (c instanceof Action)84 return (String)((Action)c).getValue("help");85 if (c instanceof JComponent && ((JComponent)c).getClientProperty("help") != null)86 return (String)((JComponent)c).getClientProperty("help");87 if (c instanceof Component)88 return contextSensitiveHelp(((Component)c).getParent());89 return null;90 }91 92 /**93 * Displays the help (or browse on the already open help) on the online page94 * with the given help topic. Use this for larger help descriptions.95 */96 public void help(String topic) {97 HelpBrowserProxy.getInstance().setUrlForHelpTopic(pathhelp + topic);98 }99 53 } -
trunk/src/org/openstreetmap/josm/actions/OpenLocationAction.java
r2285 r2308 91 91 tr("Close dialog and cancel downloading") 92 92 }); 93 dialog.configureContextsensitiveHelp(" Help/Action/OpenLocation", true /* show help button */);93 dialog.configureContextsensitiveHelp("/Action/OpenLocation", true /* show help button */); 94 94 dialog.showDialog(); 95 95 if (dialog.getValue() != 1) return; -
trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java
r2181 r2308 142 142 c = DeleteCommand.deleteWithReferences(getEditLayer(),getCurrentDataSet().getSelected()); 143 143 } else { 144 c = DeleteCommand.delete(getEditLayer(),getCurrentDataSet().getSelected(), !alt );144 c = DeleteCommand.delete(getEditLayer(),getCurrentDataSet().getSelected(), !alt /* also delete nodes in way */); 145 145 } 146 146 if (c != null) { … … 309 309 * @param e MouseEvent from which modifiers and position are taken 310 310 * @param int modifiers For explanation: @see updateCursor 311 * @param Simulate Set to true if the user shouldbe bugged with additional311 * @param silet Set to true if the user should not be bugged with additional 312 312 * dialogs 313 313 * @return 314 314 */ 315 private Command buildDeleteCommands(MouseEvent e, int modifiers, boolean si mulate) {315 private Command buildDeleteCommands(MouseEvent e, int modifiers, boolean silent) { 316 316 // Note: CTRL is the only modifier that is checked in MouseMove, don't 317 317 // forget updating it there … … 330 330 c = DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton((OsmPrimitive)ws.way),true); 331 331 } else { 332 c = DeleteCommand.delete(getEditLayer(),Collections.singleton((OsmPrimitive)ws.way), !alt, si mulate);332 c = DeleteCommand.delete(getEditLayer(),Collections.singleton((OsmPrimitive)ws.way), !alt, silent); 333 333 } 334 334 } … … 336 336 c = DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton(sel)); 337 337 } else { 338 c = DeleteCommand.delete(getEditLayer(),Collections.singleton(sel), !alt, si mulate);338 c = DeleteCommand.delete(getEditLayer(),Collections.singleton(sel), !alt, silent); 339 339 } 340 340 -
trunk/src/org/openstreetmap/josm/command/Command.java
r2284 r2308 3 3 4 4 import java.util.Collection; 5 import static org.openstreetmap.josm.tools.I18n.tr; 5 6 import java.util.HashMap; 6 7 import java.util.HashSet; … … 58 59 * Creates a new command in the context of a specific data layer 59 60 * 60 * @param layer the data layer 61 * @param layer the data layer. Must not be null. 62 * @throws IllegalArgumentException thrown if layer is null 61 63 */ 62 public Command(OsmDataLayer layer) { 64 public Command(OsmDataLayer layer) throws IllegalArgumentException { 65 if (layer == null) 66 throw new IllegalArgumentException(tr("Parameter ''{0}'' must not be null", "layer")); 63 67 this.layer = layer; 64 68 } -
trunk/src/org/openstreetmap/josm/command/DeleteCommand.java
r2296 r2308 10 10 import java.util.Collection; 11 11 import java.util.Collections; 12 import java.util.HashMap;13 12 import java.util.HashSet; 14 13 import java.util.Iterator; … … 24 23 25 24 import org.openstreetmap.josm.Main; 25 import org.openstreetmap.josm.data.osm.BackreferencedDataSet; 26 26 import org.openstreetmap.josm.data.osm.Node; 27 27 import org.openstreetmap.josm.data.osm.OsmPrimitive; … … 31 31 import org.openstreetmap.josm.data.osm.Way; 32 32 import org.openstreetmap.josm.data.osm.WaySegment; 33 import org.openstreetmap.josm.data.osm.BackreferencedDataSet.RelationToChildReference; 33 34 import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor; 34 35 import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil; 35 36 import org.openstreetmap.josm.gui.DefaultNameFormatter; 36 37 import org.openstreetmap.josm.gui.ExtendedDialog; 38 import org.openstreetmap.josm.gui.actionsupport.DeleteFromRelationConfirmationDialog; 37 39 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 38 40 import org.openstreetmap.josm.tools.ImageProvider; 39 41 42 import sun.swing.BakedArrayList; 43 40 44 /** 41 45 * A command to delete a number of primitives from the dataset. 42 * @author imi 46 43 47 */ 44 48 public class DeleteCommand extends Command { … … 49 53 50 54 /** 51 * Constructor for a collection of data 55 * Constructor. Deletes a collection of primitives in the current edit layer. 56 * 57 * @param data the primitives to delete 52 58 */ 53 59 public DeleteCommand(Collection<? extends OsmPrimitive> data) { 54 super(); 60 if (data == null) { 61 data = Collections.emptyList(); 62 } 55 63 this.toDelete = data; 64 } 65 66 /** 67 * Constructor. Deletes a single primitive in the current edit layer. 68 * 69 * @param data the primitive to delete. Must not be null. 70 * @throws IllegalArgumentException thrown if data is null 71 */ 72 public DeleteCommand(OsmPrimitive data) throws IllegalArgumentException { 73 if (data == null) 74 throw new IllegalArgumentException(tr("Parameter ''{0}'' must not be null", "data")); 75 this.toDelete = Collections.singleton(data); 56 76 } 57 77 … … 59 79 * Constructor for a single data item. Use the collection constructor to delete multiple 60 80 * objects. 61 */ 62 public DeleteCommand(OsmPrimitive data) { 63 this.toDelete = Collections.singleton(data); 64 } 65 66 /** 67 * Constructor for a single data item. Use the collection constructor to delete multiple 68 * objects. 69 * 70 * @param layer the layer context for deleting this primitive 71 * @param data the primitive to delete 72 */ 73 public DeleteCommand(OsmDataLayer layer, OsmPrimitive data) { 81 * 82 * @param layer the layer context for deleting this primitive. Must not be null. 83 * @param data the primitive to delete. Must not be null. 84 * @throws IllegalArgumentException thrown if data is null 85 * @throws IllegalArgumentException thrown if layer is null 86 */ 87 public DeleteCommand(OsmDataLayer layer, OsmPrimitive data) throws IllegalArgumentException { 74 88 super(layer); 89 if (data == null) 90 throw new IllegalArgumentException(tr("Parameter ''{0}'' must not be null", "data")); 75 91 this.toDelete = Collections.singleton(data); 76 92 } … … 80 96 * a specific layer 81 97 * 82 * @param layer the layer context for deleting these primitives 98 * @param layer the layer context for deleting these primitives. Must not be null. 83 99 * @param data the primitives to delete 84 */ 85 public DeleteCommand(OsmDataLayer layer, Collection<? extends OsmPrimitive> data) { 100 * @throws IllegalArgumentException thrown if layer is null 101 */ 102 public DeleteCommand(OsmDataLayer layer, Collection<? extends OsmPrimitive> data) throws IllegalArgumentException{ 86 103 super(layer); 104 if (data == null) { 105 data = Collections.emptyList(); 106 } 87 107 this.toDelete = data; 108 } 109 110 protected void removeNewNodesFromDeletedWay(Way w) { 111 // #2707: ways to be deleted can include new nodes (with node.id == 0). 112 // Remove them from the way before the way is deleted. Otherwise the 113 // deleted way is saved (or sent to the API) with a dangling reference to a node 114 // Example: 115 // <node id='2' action='delete' visible='true' version='1' ... /> 116 // <node id='1' action='delete' visible='true' version='1' ... /> 117 // <!-- missing node with id -1 because new deleted nodes are not persisted --> 118 // <way id='3' action='delete' visible='true' version='1'> 119 // <nd ref='1' /> 120 // <nd ref='-1' /> <!-- here's the problem --> 121 // <nd ref='2' /> 122 // </way> 123 if (w.isNew()) 124 return; // process existing ways only 125 List<Node> nodesToKeep = new ArrayList<Node>(); 126 // lookup new nodes which have been added to the set of deleted 127 // nodes ... 128 Iterator<Node> it = nodesToKeep.iterator(); 129 while(it.hasNext()) { 130 Node n = it.next(); 131 if (n.isNew()) { 132 it.remove(); 133 } 134 } 135 w.setNodes(nodesToKeep); 88 136 } 89 137 … … 93 141 for (OsmPrimitive osm : toDelete) { 94 142 osm.setDeleted(true); 143 if (osm instanceof Way) { 144 removeNewNodesFromDeletedWay((Way)osm); 145 } 95 146 } 96 147 return true; … … 109 160 String msg = ""; 110 161 switch(OsmPrimitiveType.from(primitive)) { 111 case NODE: msg = "Delete node {0}"; break;112 case WAY: msg = "Delete way {0}"; break;113 case RELATION:msg = "Delete relation {0}"; break;162 case NODE: msg = "Delete node {0}"; break; 163 case WAY: msg = "Delete way {0}"; break; 164 case RELATION:msg = "Delete relation {0}"; break; 114 165 } 115 166 … … 130 181 apiname = t.getAPIName(); 131 182 switch(t) { 132 case NODE: msg = trn("Delete {0} node", "Delete {0} nodes", toDelete.size(), toDelete.size()); break;133 case WAY: msg = trn("Delete {0} way", "Delete {0} ways", toDelete.size(), toDelete.size()); break;134 case RELATION: msg = trn("Delete {0} relation", "Delete {0} relations", toDelete.size(), toDelete.size()); break;183 case NODE: msg = trn("Delete {0} node", "Delete {0} nodes", toDelete.size(), toDelete.size()); break; 184 case WAY: msg = trn("Delete {0} way", "Delete {0} ways", toDelete.size(), toDelete.size()); break; 185 case RELATION: msg = trn("Delete {0} relation", "Delete {0} relations", toDelete.size(), toDelete.size()); break; 135 186 } 136 187 } … … 156 207 * If a way is deleted, only the way and no nodes are deleted. 157 208 * 158 * @param layer 209 * @param layer the {@see OsmDataLayer} in whose context primitives are deleted. Must not be null. 159 210 * @param selection The list of all object to be deleted. 160 * @param si mulateSet to true if the user should not be bugged with additional dialogs211 * @param silent Set to true if the user should not be bugged with additional dialogs 161 212 * @return command A command to perform the deletions, or null of there is nothing to delete. 162 */ 163 public static Command deleteWithReferences(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection, boolean simulate) { 213 * @throws IllegalArgumentException thrown if layer is null 214 */ 215 public static Command deleteWithReferences(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection, boolean silent) throws IllegalArgumentException { 216 if (layer == null) 217 throw new IllegalArgumentException(tr("Parameter ''{0}'' must not be null", "layer")); 218 if (selection == null || selection.isEmpty()) return null; 164 219 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data); 165 220 v.initialize(); … … 170 225 if (v.getData().isEmpty()) 171 226 return null; 172 if (!checkAndConfirmOutlyingDeletes(layer,v.getData()) && !si mulate)227 if (!checkAndConfirmOutlyingDeletes(layer,v.getData()) && !silent) 173 228 return null; 174 229 return new DeleteCommand(layer,v.getData()); … … 233 288 * <li>it is not referred to by other non-deleted primitives outside of <code>primitivesToDelete</code></li> 234 289 * <ul> 290 * @param backreferences backreference data structure 235 291 * @param layer the layer in whose context primitives are deleted 236 292 * @param primitivesToDelete the primitives to delete … … 238 294 * can be deleted too 239 295 */ 240 protected static Collection<Node> computeNodesToDelete( OsmDataLayer layer, Collection<OsmPrimitive> primitivesToDelete) {296 protected static Collection<Node> computeNodesToDelete(BackreferencedDataSet backreferences, OsmDataLayer layer, Collection<OsmPrimitive> primitivesToDelete) { 241 297 Collection<Node> nodesToDelete = new HashSet<Node>(); 242 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data, false); 243 for (OsmPrimitive osm : primitivesToDelete) { 244 if (! (osm instanceof Way) ) { 245 continue; 246 } 247 for (Node n : ((Way) osm).getNodes()) { 298 //CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data, false); 299 for (Way way : OsmPrimitive.getFilteredList(primitivesToDelete, Way.class)) { 300 for (Node n : way.getNodes()) { 248 301 if (n.isTagged()) { 249 302 continue; 250 303 } 251 v.initialize();252 n.visit(v);253 Collection<OsmPrimitive> referringPrimitives = v.getData();304 //v.initialize(); 305 //n.visit(v); 306 Collection<OsmPrimitive> referringPrimitives = backreferences.getParents(n); 254 307 referringPrimitives.removeAll(primitivesToDelete); 255 308 int count = 0; … … 276 329 * they are part of a relation, inform the user and do not delete. 277 330 * 278 * @param layer the {@see OsmDataLayer} in whose context a primitivethe primitives are deleted279 * @param selection The objects to delete.331 * @param layer the {@see OsmDataLayer} in whose context the primitives are deleted 332 * @param selection the objects to delete. 280 333 * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well 281 * @param simulate Set to true if the user should not be bugged with additional questions282 334 * @return command a command to perform the deletions, or null if there is nothing to delete. 283 335 */ 284 336 public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection, 285 337 boolean alsoDeleteNodesInWay) { 286 return delete(layer, selection, alsoDeleteNodesInWay, false); 287 } 288 338 return delete(layer, selection, alsoDeleteNodesInWay, false /* not silent */); 339 } 340 341 /** 342 * Try to delete all given primitives. 343 * 344 * If a node is used by a way, it's removed from that way. If a node or a way is used by a 345 * relation, inform the user and do not delete. 346 * 347 * If this would cause ways with less than 2 nodes to be created, delete these ways instead. If 348 * they are part of a relation, inform the user and do not delete. 349 * 350 * @param layer the {@see OsmDataLayer} in whose context the primitives are deleted 351 * @param selection the objects to delete. 352 * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well 353 * @param silent set to true if the user should not be bugged with additional questions 354 * @return command a command to perform the deletions, or null if there is nothing to delete. 355 */ 289 356 public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection, 290 boolean alsoDeleteNodesInWay, boolean si mulate) {291 if (selection .isEmpty())357 boolean alsoDeleteNodesInWay, boolean silent) { 358 if (selection == null || selection.isEmpty()) 292 359 return null; 293 360 294 Collection<OsmPrimitive> primitivesToDelete = new HashSet<OsmPrimitive>(selection); 361 BackreferencedDataSet backreferences = new BackreferencedDataSet(layer.data); 362 backreferences.build(); 363 364 Set<OsmPrimitive> primitivesToDelete = new HashSet<OsmPrimitive>(selection); 295 365 Collection<Way> waysToBeChanged = new HashSet<Way>(); 296 HashMap<OsmPrimitive, Collection<OsmPrimitive>> relationsToBeChanged = new HashMap<OsmPrimitive, Collection<OsmPrimitive>>();297 366 298 367 if (alsoDeleteNodesInWay) { 299 368 // delete untagged nodes only referenced by primitives in primitivesToDelete, 300 369 // too 301 Collection<Node> nodesToDelete = computeNodesToDelete( layer, primitivesToDelete);370 Collection<Node> nodesToDelete = computeNodesToDelete(backreferences, layer, primitivesToDelete); 302 371 primitivesToDelete.addAll(nodesToDelete); 303 372 } 304 373 305 if (!si mulate&& !checkAndConfirmOutlyingDeletes(layer,primitivesToDelete))374 if (!silent && !checkAndConfirmOutlyingDeletes(layer,primitivesToDelete)) 306 375 return null; 307 376 308 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data, false); 309 for (OsmPrimitive osm : primitivesToDelete) { 310 v.initialize(); 311 osm.visit(v); 312 for (OsmPrimitive ref : v.getData()) { 313 if (primitivesToDelete.contains(ref)) { 314 continue; 315 } 316 if (ref instanceof Way) { 317 waysToBeChanged.add((Way) ref); 318 } else if (ref instanceof Relation) { 319 if (testRelation((Relation) ref, osm, simulate) == 1) { 320 Collection<OsmPrimitive> relset = relationsToBeChanged.get(ref); 321 if (relset == null) { 322 relset = new HashSet<OsmPrimitive>(); 323 } 324 relset.add(osm); 325 relationsToBeChanged.put(ref, relset); 326 } else 327 return null; 328 } else 329 return null; 330 } 331 } 377 waysToBeChanged.addAll(OsmPrimitive.getFilteredSet(backreferences.getParents(primitivesToDelete), Way.class)); 332 378 333 379 Collection<Command> cmds = new LinkedList<Command>(); … … 337 383 if (wnew.getNodesCount() < 2) { 338 384 primitivesToDelete.add(w); 339 340 v.initialize();341 w.visit(v);342 for (OsmPrimitive ref : v.getData()) {343 if (primitivesToDelete.contains(ref)) {344 continue;345 }346 if (ref instanceof Relation) {347 Boolean found = false;348 Collection<OsmPrimitive> relset = relationsToBeChanged.get(ref);349 if (relset == null) {350 relset = new HashSet<OsmPrimitive>();351 } else {352 for (OsmPrimitive m : relset) {353 if (m == w) {354 found = true;355 break;356 }357 }358 }359 if (!found) {360 if (testRelation((Relation) ref, w, simulate) == 1) {361 relset.add(w);362 relationsToBeChanged.put(ref, relset);363 } else364 return null;365 }366 } else367 return null;368 }369 385 } else { 370 386 cmds.add(new ChangeCommand(w, wnew)); … … 372 388 } 373 389 374 Iterator<OsmPrimitive> iterator = relationsToBeChanged.keySet().iterator(); 390 // get a confirmation that the objects to delete can be removed from their parent 391 // relations 392 // 393 if (!silent) { 394 Set<RelationToChildReference> references = backreferences.getRelationToChildReferences(primitivesToDelete); 395 Iterator<RelationToChildReference> it = references.iterator(); 396 while(it.hasNext()) { 397 RelationToChildReference ref = it.next(); 398 if (ref.getParent().isDeleted()) { 399 it.remove(); 400 } 401 } 402 if (!references.isEmpty()) { 403 DeleteFromRelationConfirmationDialog dialog = DeleteFromRelationConfirmationDialog.getInstance(); 404 dialog.getModel().populate(references); 405 dialog.setVisible(true); 406 if (dialog.isCanceled()) 407 return null; 408 } 409 } 410 411 // remove the objects from their parent relations 412 // 413 Iterator<Relation> iterator = OsmPrimitive.getFilteredSet(backreferences.getParents(primitivesToDelete), Relation.class).iterator(); 375 414 while (iterator.hasNext()) { 376 Relation cur = (Relation)iterator.next();415 Relation cur = iterator.next(); 377 416 Relation rel = new Relation(cur); 378 for (OsmPrimitive osm : relationsToBeChanged.get(cur)) { 379 rel.removeMembersFor(osm); 380 } 417 rel.removeMembersFor(primitivesToDelete); 381 418 cmds.add(new ChangeCommand(cur, rel)); 382 419 } 383 420 384 // #2707: ways to be deleted can include new nodes (with node.id == 0). 385 // Remove them from the way before the way is deleted. Otherwise the 386 // deleted way is saved (or sent to the API) with a dangling reference to a node 387 // Example: 388 // <node id='2' action='delete' visible='true' version='1' ... /> 389 // <node id='1' action='delete' visible='true' version='1' ... /> 390 // <!-- missing node with id -1 because new deleted nodes are not persisted --> 391 // <way id='3' action='delete' visible='true' version='1'> 392 // <nd ref='1' /> 393 // <nd ref='-1' /> <!-- heres the problem --> 394 // <nd ref='2' /> 395 // </way> 396 for (OsmPrimitive primitive : primitivesToDelete) { 397 if (!(primitive instanceof Way)) { 398 continue; 399 } 400 Way w = (Way) primitive; 401 if (w.isNew()) { // new ways with id == 0 are fine, 402 continue; // process existing ways only 403 } 404 Way wnew = new Way(w); 405 List<Node> nodesToKeep = new ArrayList<Node>(); 406 // lookup new nodes which have been added to the set of deleted 407 // nodes ... 408 for (Node n : wnew.getNodes()) { 409 if (!n.isNew() || !primitivesToDelete.contains(n)) { 410 nodesToKeep.add(n); 411 } 412 } 413 // .. and remove them from the way 414 // 415 wnew.setNodes(nodesToKeep); 416 if (nodesToKeep.size() < w.getNodesCount()) { 417 cmds.add(new ChangeCommand(w, wnew)); 418 } 419 } 420 421 // build the delete command 422 // 421 423 if (!primitivesToDelete.isEmpty()) { 422 424 cmds.add(new DeleteCommand(layer,primitivesToDelete)); … … 427 429 428 430 public static Command deleteWaySegment(OsmDataLayer layer, WaySegment ws) { 429 if (ws.way.getNodesCount() < 3) { 430 // If the way contains less than three nodes, it can't have more 431 // than one segment, so the way should be deleted. 432 431 if (ws.way.getNodesCount() < 3) 433 432 return new DeleteCommand(layer, Collections.singleton(ws.way)); 434 }435 433 436 434 if (ws.way.firstNode() == ws.way.lastNode()) { -
trunk/src/org/openstreetmap/josm/data/osm/Relation.java
r2305 r2308 2 2 3 3 import java.util.ArrayList; 4 import java.util.Collection; 4 5 import java.util.HashMap; 5 6 import java.util.HashSet; … … 170 171 for (RelationMemberData member:relationData.getMembers()) { 171 172 switch (member.getMemberType()) { 172 case NODE:173 nodes.put(member.getMemberId(), nodeMarker);174 break;175 case WAY:176 ways.put(member.getMemberId(), wayMarker);177 break;178 case RELATION:179 relations.put(member.getMemberId(), relationMarker);180 break;173 case NODE: 174 nodes.put(member.getMemberId(), nodeMarker); 175 break; 176 case WAY: 177 ways.put(member.getMemberId(), wayMarker); 178 break; 179 case RELATION: 180 relations.put(member.getMemberId(), relationMarker); 181 break; 181 182 } 182 183 } … … 202 203 OsmPrimitive foundMember = null; 203 204 switch (member.getMemberType()) { 204 case NODE: 205 foundMember = nodes.get(member.getMemberId()); 206 if (foundMember == nodeMarker) { 207 throw new AssertionError("Data consistency problem - relation with missing member detected"); 208 } 209 break; 210 case WAY: 211 foundMember = ways.get(member.getMemberId()); 212 if (foundMember == wayMarker) { 213 throw new AssertionError("Data consistency problem - relation with missing member detected"); 214 } 215 break; 216 case RELATION: 217 foundMember = relations.get(member.getMemberId()); 218 if (foundMember == relationMarker) { 219 throw new AssertionError("Data consistency problem - relation with missing member detected"); 220 } 221 break; 205 case NODE: 206 foundMember = nodes.get(member.getMemberId()); 207 if (foundMember == nodeMarker) 208 throw new AssertionError("Data consistency problem - relation with missing member detected"); 209 break; 210 case WAY: 211 foundMember = ways.get(member.getMemberId()); 212 if (foundMember == wayMarker) 213 throw new AssertionError("Data consistency problem - relation with missing member detected"); 214 break; 215 case RELATION: 216 foundMember = relations.get(member.getMemberId()); 217 if (foundMember == relationMarker) 218 throw new AssertionError("Data consistency problem - relation with missing member detected"); 219 break; 222 220 } 223 221 newMembers.add(new RelationMember(member.getRole(), foundMember)); … … 290 288 } 291 289 290 /** 291 * removes all members with member.member == primitive 292 * 293 * @param primitives the primitives to check for 294 */ 295 public void removeMembersFor(Collection<OsmPrimitive> primitives) { 296 if (primitives == null || primitives.isEmpty()) 297 return; 298 299 ArrayList<RelationMember> todelete = new ArrayList<RelationMember>(); 300 for (RelationMember member: members) { 301 if (primitives.contains(member.getMember())) { 302 todelete.add(member); 303 } 304 } 305 members.removeAll(todelete); 306 } 307 292 308 @Override 293 309 public String getDisplayName(NameFormatter formatter) { -
trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java
r2282 r2308 1370 1370 leftHandTraffic = Main.pref.getBoolean("mappaint.lefthandtraffic",false); 1371 1371 orderFont = new Font(Main.pref.get("mappaint.font","Helvetica"), Font.PLAIN, Main.pref.getInteger("mappaint.fontsize", 8)); 1372 String[] names = {"name:"+LanguageInfo.get LanguageCode(), "name", "int_name", "ref", "operator", "brand","addr:housenumber"};1372 String[] names = {"name:"+LanguageInfo.getJOSMLocaleCode(), "name", "int_name", "ref", "operator", "brand","addr:housenumber"}; 1373 1373 regionalNameOrder = Main.pref.getCollection("mappaint.nameOrder", Arrays.asList(names)); 1374 1374 minEN = nc.getEastNorth(0,nc.getHeight()-1); -
trunk/src/org/openstreetmap/josm/gui/GettingStarted.java
r2120 r2308 52 52 53 53 final private int myVersion = AboutAction.getVersionNumber(); 54 final private String myLang = LanguageInfo.get LanguageCodeWiki();54 final private String myLang = LanguageInfo.getWikiLanguagePrefix(); 55 55 56 56 /** -
trunk/src/org/openstreetmap/josm/gui/dialogs/ConflictResolutionDialog.java
r2301 r2308 192 192 193 193 public void actionPerformed(ActionEvent arg0) { 194 HelpBrowserProxy.getInstance().setUrlForHelpTopic("/ Help/Dialog/ConflictDialog");194 HelpBrowserProxy.getInstance().setUrlForHelpTopic("/Dialog/ConflictDialog"); 195 195 } 196 196 } -
trunk/src/org/openstreetmap/josm/gui/help/ContextSensitiveHelpAction.java
r2289 r2308 19 19 private String helpTopic; 20 20 21 /** 22 * 23 * @param helpTopic 24 */ 21 25 public ContextSensitiveHelpAction(String helpTopic) { 22 26 putValue(SHORT_DESCRIPTION, tr("Show help information")); -
trunk/src/org/openstreetmap/josm/gui/help/HelpApplication.java
r2274 r2308 6 6 import java.awt.Rectangle; 7 7 import java.awt.Toolkit; 8 import java.io.IOException; 9 import java.io.PrintWriter; 10 import java.io.StringWriter; 11 import java.lang.Thread.UncaughtExceptionHandler; 8 12 import java.util.Arrays; 9 13 import java.util.Collection; … … 12 16 import java.util.List; 13 17 import java.util.Map; 18 import java.util.logging.FileHandler; 19 import java.util.logging.Level; 20 import java.util.logging.LogManager; 21 import java.util.logging.Logger; 22 import java.util.logging.SimpleFormatter; 23 24 import javax.swing.JOptionPane; 14 25 15 26 import org.openstreetmap.josm.Main; … … 23 34 */ 24 35 public class HelpApplication { 36 static private final Logger logger = Logger.getLogger(HelpApplication.class.getName()); 25 37 private HelpBrowser browser; 26 38 private HelpBrowserCommandProcessor commandProcessor; … … 82 94 83 95 MainApplication.preConstructorInit(args); 96 Thread.setDefaultUncaughtExceptionHandler( 97 new UncaughtExceptionHandler() { 98 public void uncaughtException(Thread t, Throwable e) { 99 StringWriter sw = new StringWriter(); 100 e.printStackTrace(new PrintWriter(sw)); 101 logger.log(Level.SEVERE, sw.getBuffer().toString()); 102 } 103 } 104 ); 84 105 85 106 new HelpApplication().start(); -
trunk/src/org/openstreetmap/josm/gui/help/HelpBrowser.java
r2276 r2308 2 2 package org.openstreetmap.josm.gui.help; 3 3 4 import static org.openstreetmap.josm.gui.help.HelpUtil.buildAbsoluteHelpTopic; 5 import static org.openstreetmap.josm.gui.help.HelpUtil.getHelpTopicEditUrl; 4 6 import static org.openstreetmap.josm.tools.I18n.tr; 5 7 6 8 import java.awt.BorderLayout; 9 import java.awt.Rectangle; 7 10 import java.awt.event.ActionEvent; 8 11 import java.awt.event.KeyEvent; … … 12 15 import java.io.IOException; 13 16 import java.io.InputStreamReader; 17 import java.util.Locale; 14 18 import java.util.Observable; 15 19 import java.util.Observer; 20 import java.util.logging.Logger; 16 21 17 22 import javax.swing.AbstractAction; … … 22 27 import javax.swing.JOptionPane; 23 28 import javax.swing.JPanel; 29 import javax.swing.JScrollBar; 24 30 import javax.swing.JScrollPane; 25 31 import javax.swing.JSeparator; … … 28 34 import javax.swing.event.HyperlinkEvent; 29 35 import javax.swing.event.HyperlinkListener; 36 import javax.swing.text.AttributeSet; 37 import javax.swing.text.BadLocationException; 38 import javax.swing.text.Document; 39 import javax.swing.text.Element; 40 import javax.swing.text.SimpleAttributeSet; 41 import javax.swing.text.html.HTMLDocument; 30 42 import javax.swing.text.html.HTMLEditorKit; 31 43 import javax.swing.text.html.StyleSheet; 44 import javax.swing.text.html.HTML.Tag; 32 45 33 46 import org.openstreetmap.josm.Main; 47 import org.openstreetmap.josm.gui.HelpAwareOptionPane; 34 48 import org.openstreetmap.josm.tools.ImageProvider; 35 import org.openstreetmap.josm.tools.LanguageInfo;36 49 import org.openstreetmap.josm.tools.OpenBrowser; 37 import org.openstreetmap.josm.tools.WikiReader;38 50 39 51 public class HelpBrowser extends JFrame { 40 52 static private final Logger logger = Logger.getLogger(HelpBrowser.class.getName()); 53 54 /** the unique instance */ 41 55 private static HelpBrowser instance; 42 56 … … 61 75 static public void launchBrowser(String helpTopic) { 62 76 HelpBrowser browser = getInstance(); 63 browser. setUrlForHelpTopic(helpTopic);77 browser.openHelpTopic(helpTopic); 64 78 browser.setVisible(true); 65 79 browser.toFront(); … … 68 82 /** the help browser */ 69 83 private JEditorPane help; 84 private JScrollPane spHelp; 85 70 86 /** the help browser history */ 71 87 private HelpBrowserHistory history; … … 74 90 private String url; 75 91 76 private String languageCode = LanguageInfo.getLanguageCodeWiki(); 77 private String baseurl = Main.pref.get("help.baseurl", "http://josm.openstreetmap.de"); 78 private String pathbase = Main.pref.get("help.pathbase", "/wiki/"); 79 private WikiReader reader = new WikiReader(baseurl); 92 private HelpContentReader reader; 80 93 81 94 /** … … 126 139 help.setEditorKit(kit); 127 140 help.setEditable(false); 128 help.addHyperlinkListener(new HyperlinkListener(){ 129 public void hyperlinkUpdate(HyperlinkEvent e) { 130 if (e.getEventType() != HyperlinkEvent.EventType.ACTIVATED) 131 return; 132 if (e.getURL() == null) { 133 help.setText("<html>404 not found</html>"); 134 } else if (e.getURL().toString().endsWith("action=edit")) { 135 OpenBrowser.displayUrl(e.getURL().toString()); 136 } else { 137 url = e.getURL().toString(); 138 setUrl(e.getURL().toString()); 139 } 140 } 141 }); 141 help.addHyperlinkListener(new HyperlinkHandler()); 142 142 help.setContentType("text/html"); 143 144 145 143 history = new HelpBrowserHistory(this); 146 144 … … 148 146 setContentPane(p); 149 147 150 p.add( new JScrollPane(help), BorderLayout.CENTER);148 p.add(spHelp = new JScrollPane(help), BorderLayout.CENTER); 151 149 152 150 addWindowListener(new WindowAdapter(){ … … 168 166 169 167 public HelpBrowser() { 168 reader = new HelpContentReader(HelpUtil.getWikiBaseUrl()); 170 169 build(); 171 170 } 172 171 172 /** 173 * Replies the current URL 174 * 175 * @return the current URL 176 */ 173 177 public String getUrl() { 174 178 return url; 175 179 } 176 180 177 protected void loadUrl(String url) { 178 String langurl = url; 179 if(url.startsWith(baseurl+pathbase)){ 180 int i = pathbase.length()+baseurl.length(); 181 String title = url.substring(i); 182 if(languageCode.length() != 0 && !title.startsWith(languageCode)) { 183 title = languageCode + title; 184 } 185 langurl = url.substring(0, i) + title; 186 } 187 boolean loaded = false; 188 if(!langurl.equals(this.url) && !langurl.equals(url)){ 189 loaded = loadHelpUrl(url, langurl, true); 190 } 191 if(!loaded) { 192 loaded = loadHelpUrl(url, langurl, false); 193 } 194 if(!loaded) { 195 help.setText(tr("Error while loading page {0}",url)); 196 } 197 } 198 199 public void setUrl(String url) { 200 loadUrl(url); 181 /** 182 * Displays a warning page when a help topic doesn't exist yet. 183 * 184 * @param relativeHelpTopic the help topic 185 */ 186 protected void handleMissingHelpContent(String relativeHelpTopic) { 187 String message = tr("<html><p class=\"warning-header\">Help content for help topic missing</p>" 188 + "<p class=\"warning-body\">Help content for the help topic <strong>{0}</strong> is " 189 + "not available yet. It is missing both in your local language ({1}) and in english.<br><br>" 190 + "Please help to improve the JOSM help system and fill in the missing information." 191 + "You can both edit the <a href=\"{2}\">help topic in your local language ({1})</a> and " 192 + "the <a href=\"{3}\">help topic in english</a>." 193 + "</p></html>", 194 relativeHelpTopic, 195 Locale.getDefault().getDisplayName(), 196 getHelpTopicEditUrl(buildAbsoluteHelpTopic(relativeHelpTopic)), 197 getHelpTopicEditUrl(buildAbsoluteHelpTopic(relativeHelpTopic, Locale.ENGLISH)) 198 ); 199 help.setText(message); 200 } 201 202 /** 203 * Displays a error page if a help topic couldn't be loaded because of network or IO error. 204 * 205 * @param relativeHelpTopic the help topic 206 * @param e the exception 207 */ 208 protected void handleHelpContentReaderException(String relativeHelpTopic, HelpContentReaderException e) { 209 String message = tr("<html><p class=\"error-header\">Error when retrieving help information</p>" 210 + "<p class=\"error-body\">The content for the help topic <strong>{0}</strong> could " 211 + "not be loaded. The error message is (untranslated):<br>" 212 + "<tt>{1}</tt>" 213 + "</p></html>", 214 relativeHelpTopic, 215 e.toString() 216 ); 217 help.setText(message); 218 } 219 220 protected void scrollToTop() { 221 JScrollBar sb = spHelp.getVerticalScrollBar(); 222 sb.setValue(sb.getMinimum()); 223 } 224 225 /** 226 * Loads a help topic given by a relative help topic name (i.e. "/Action/New") 227 * 228 * First tries to load the language specific help topic. If it is missing, tries to 229 * load the topic in english. 230 * 231 * @param relativeHelpTopic the relative help topic 232 */ 233 protected void loadRelativeHelpTopic(String relativeHelpTopic) { 234 String url = HelpUtil.getHelpTopicUrl(HelpUtil.buildAbsoluteHelpTopic(relativeHelpTopic)); 235 String content = null; 236 try { 237 content = reader.fetchHelpTopicContent(url); 238 } catch(MissingHelpContentException e) { 239 url = HelpUtil.getHelpTopicUrl(HelpUtil.buildAbsoluteHelpTopic(relativeHelpTopic, Locale.ENGLISH)); 240 try { 241 logger.info("fetching url: " + url); 242 content = reader.fetchHelpTopicContent(url); 243 } catch(MissingHelpContentException e1) { 244 handleMissingHelpContent(relativeHelpTopic); 245 return; 246 } catch(HelpContentReaderException e1) { 247 e1.printStackTrace(); 248 handleHelpContentReaderException(relativeHelpTopic,e1); 249 return; 250 } 251 } catch(HelpContentReaderException e) { 252 e.printStackTrace(); 253 handleHelpContentReaderException(relativeHelpTopic, e); 254 return; 255 } 256 help.setText(content); 257 history.setCurrentUrl(url); 258 this.url = url; 259 scrollToTop(); 260 } 261 262 /** 263 * Loads a help topic given by an absolute help topic name, i.e. 264 * "/De:Help/Action/New" 265 * 266 * @param absoluteHelpTopic the absolute help topic name 267 */ 268 protected void loadAbsoluteHelpTopic(String absoluteHelpTopic) { 269 String url = HelpUtil.getHelpTopicUrl(absoluteHelpTopic); 270 String content = null; 271 try { 272 content = reader.fetchHelpTopicContent(url); 273 } catch(MissingHelpContentException e) { 274 handleMissingHelpContent(absoluteHelpTopic); 275 return; 276 } catch(HelpContentReaderException e) { 277 e.printStackTrace(); 278 handleHelpContentReaderException(absoluteHelpTopic, e); 279 return; 280 } 281 help.setText(content); 282 history.setCurrentUrl(url); 283 this.url = url; 284 scrollToTop(); 285 } 286 287 /** 288 * Opens an URL and displays the content. 289 * 290 * If the URL is the locator of an absolute help topic, help content is loaded from 291 * the JOSM wiki. Otherwise, the help browser loads the page from the given URL 292 * 293 * @param url the url 294 */ 295 public void openUrl(String url) { 201 296 if (!isVisible()) { 202 297 setVisible(true); … … 205 300 toFront(); 206 301 } 207 history.setCurrentUrl(url); 208 } 209 210 public void setUrlForHelpTopic(String topic) { 211 setUrl(baseurl+pathbase+ topic); 212 } 213 214 protected boolean loadHelpUrl(String url, String localizedUrl, boolean useLocalizedUrl){ 215 this.url = useLocalizedUrl ? localizedUrl : url; 216 boolean loaded = false; 217 try { 218 String txt = reader.read(this.url); 219 if(txt.length() == 0){ 220 if(useLocalizedUrl) 221 throw new IOException(); 222 if(url.equals(localizedUrl)){ 223 txt = ("<HTML>"+tr("Help page missing. Create it in <A HREF=\"{0}\">English</A>.", 224 url+"?action=edit")+"</HTML>"); 225 } else{ 226 txt = ("<HTML>"+tr("Help page missing. Create it in <A HREF=\"{0}\">English</A> or <A HREF=\"{1}\">your language</A>.", 227 url+"?action=edit", localizedUrl+"?action=edit")+"</HTML>"); 228 } 229 } 230 help.setText(txt); 231 help.setCaretPosition(0); 232 loaded = true; 233 } catch (IOException ex) { 234 } 235 return loaded; 302 String helpTopic = HelpUtil.extractAbsoluteHelpTopic(url); 303 if (helpTopic == null) { 304 try { 305 this.url = url; 306 help.setPage(url); 307 } catch(IOException e) { 308 HelpAwareOptionPane.showOptionDialog( 309 Main.parent, 310 tr( 311 "<html>Failed to open help page for url {0}.<br>" 312 + "This is most likely due to a network problem, please check your<br>" 313 + "your internet connection</html>", 314 url.toString() 315 ), 316 tr("Failed to open URL"), 317 JOptionPane.ERROR_MESSAGE, 318 null, /* no icon */ 319 null, /* standard options, just OK button */ 320 null, /* default is standard */ 321 null /* no help context */ 322 ); 323 } 324 history.setCurrentUrl(url); 325 } else { 326 loadAbsoluteHelpTopic(helpTopic); 327 } 328 } 329 330 /** 331 * Loads and displays the help information for a help topic given 332 * by a relative help topic name, i.e. "/Action/New" 333 * 334 * @param relativeHelpTopic the relative help topic 335 */ 336 public void openHelpTopic(String relativeHelpTopic) { 337 if (!isVisible()) { 338 setVisible(true); 339 toFront(); 340 } else { 341 toFront(); 342 } 343 loadRelativeHelpTopic(relativeHelpTopic); 236 344 } 237 345 … … 256 364 257 365 public void actionPerformed(ActionEvent e) { 258 if (!getUrl().startsWith(baseurl)) { 366 if (!getUrl().startsWith(HelpUtil.getWikiBaseHelpUrl())) { 367 String message = tr( 368 "<html>The current URL <tt>{0}</tt><br>" 369 + "is an external URL. Editing is only possible for help topics<br>" 370 + "on the help server <tt>{1}</tt>.</html>", 371 getUrl(), 372 HelpUtil.getWikiBaseUrl() 373 ); 259 374 JOptionPane.showMessageDialog( 260 375 Main.parent, 261 tr("Can only edit help pages from JOSM Online Help"),376 message, 262 377 tr("Warning"), 263 378 JOptionPane.WARNING_MESSAGE … … 265 380 return; 266 381 } 382 String url = getUrl(); 383 url = url.replaceAll("#[^#]*$", ""); 267 384 OpenBrowser.displayUrl(url+"?action=edit"); 268 385 } … … 277 394 278 395 public void actionPerformed(ActionEvent e) { 279 setUrl(url);396 openUrl(getUrl()); 280 397 } 281 398 } … … 328 445 329 446 public void actionPerformed(ActionEvent e) { 330 setUrlForHelpTopic("Help"); 447 openHelpTopic("/"); 448 } 449 } 450 451 class HyperlinkHandler implements HyperlinkListener { 452 453 /** 454 * Scrolls the help browser to the element with id <code>id</code> 455 * 456 * @param id the id 457 * @return true, if an element with this id was found and scrolling was successful; false, otherwise 458 */ 459 protected boolean scrollToElementWithId(String id) { 460 Document d = help.getDocument(); 461 if (d instanceof HTMLDocument) { 462 HTMLDocument doc = (HTMLDocument) d; 463 Element element = doc.getElement(id); 464 try { 465 Rectangle r = help.modelToView(element.getStartOffset()); 466 if (r != null) { 467 Rectangle vis = help.getVisibleRect(); 468 r.height = vis.height; 469 help.scrollRectToVisible(r); 470 return true; 471 } 472 } catch(BadLocationException e) { 473 System.err.println(tr("Warning: bad location in HTML document. Exception was: " + e.toString())); 474 e.printStackTrace(); 475 } 476 } 477 return false; 478 } 479 480 /** 481 * Checks whether the hyperlink event originated on a <a ...> element with 482 * a relative href consisting of a URL fragment only, i.e. 483 * <a href="#thisIsALocalFragment">. If so, replies the fragment, i.e. 484 * "thisIsALocalFragment". 485 * 486 * Otherwise, replies null 487 * 488 * @param e the hyperlink event 489 * @return the local fragment 490 */ 491 protected String getUrlFragment(HyperlinkEvent e) { 492 AttributeSet set = e.getSourceElement().getAttributes(); 493 Object value = set.getAttribute(Tag.A); 494 if (value == null || ! (value instanceof SimpleAttributeSet)) return null; 495 SimpleAttributeSet atts = (SimpleAttributeSet)value; 496 value = atts.getAttribute(javax.swing.text.html.HTML.Attribute.HREF); 497 if (value == null) return null; 498 String s = (String)value; 499 if (s.matches("#.*")) 500 return s.substring(1); 501 return null; 502 } 503 504 public void hyperlinkUpdate(HyperlinkEvent e) { 505 if (e.getEventType() != HyperlinkEvent.EventType.ACTIVATED) 506 return; 507 if (e.getURL() == null) { 508 // Probably hyperlink event on a an A-element with a href consisting of 509 // a fragment only, i.e. "#ALocalFragment". 510 // 511 String fragment = getUrlFragment(e); 512 if (fragment != null) { 513 // first try to scroll to an element with id==fragment. This is the way 514 // table of contents are built in the JOSM wiki. If this fails, try to 515 // scroll to a <A name="..."> element. 516 // 517 if (!scrollToElementWithId(fragment)) { 518 help.scrollToReference(fragment); 519 } 520 } else { 521 HelpAwareOptionPane.showOptionDialog( 522 Main.parent, 523 tr("Failed to open help page. The target URL is empty."), 524 tr("Failed to open help page"), 525 JOptionPane.ERROR_MESSAGE, 526 null, /* no icon */ 527 null, /* standard options, just OK button */ 528 null, /* default is standard */ 529 null /* no help context */ 530 ); 531 } 532 } else if (e.getURL().toString().endsWith("action=edit")) { 533 OpenBrowser.displayUrl(e.getURL().toString()); 534 } else { 535 url = e.getURL().toString(); 536 openUrl(e.getURL().toString()); 537 } 331 538 } 332 539 } -
trunk/src/org/openstreetmap/josm/gui/help/HelpBrowserCommandProcessor.java
r2274 r2308 5 5 import java.io.IOException; 6 6 import java.io.InputStreamReader; 7 import java.util.logging.Level; 8 import java.util.logging.Logger; 7 9 8 10 import javax.swing.SwingUtilities; … … 16 18 */ 17 19 public class HelpBrowserCommandProcessor implements Runnable { 20 private static final Logger logger = Logger.getLogger(HelpBrowserCommandProcessor.class.getName()); 18 21 19 22 /** the controlled help browser*/ … … 31 34 * Show the help page for help topic <code>helpTopic</code>. 32 35 * 33 * @param helpTopic sthe help topic36 * @param helpTopic the help topic 34 37 */ 35 protected void setUrlForHelpTopic s(final String helpTopics) {38 protected void setUrlForHelpTopic(final String helpTopic) { 36 39 Runnable r = new Runnable() { 37 40 public void run() { 38 browser. setUrlForHelpTopic(helpTopics);41 browser.openHelpTopic(helpTopic); 39 42 browser.setVisible(true); 40 43 browser.toFront(); … … 65 68 while(true) { 66 69 String cmd = null; 70 67 71 try { 68 72 cmd = reader.readLine(); 73 logger.info("got command: " + cmd); 69 74 } catch(IOException e) { 75 logger.log(Level.SEVERE,e.toString()); 70 76 System.out.println(tr("Failed to read command. Exiting help browser. Exception was:" + e.toString())); 71 77 System.exit(1); … … 73 79 if (cmd.startsWith("exit")) { 74 80 exit(); 75 } else if (cmd.startsWith("setUrlForHelpTopic s")) {76 String helpTopic s = cmd.substring("setUrlForHelpTopics".length());77 setUrlForHelpTopic s(helpTopics);81 } else if (cmd.startsWith("setUrlForHelpTopic ")) { 82 String helpTopic = cmd.substring("setUrlForHelpTopic ".length()); 83 setUrlForHelpTopic(helpTopic); 78 84 } 79 85 } -
trunk/src/org/openstreetmap/josm/gui/help/HelpBrowserHistory.java
r2274 r2308 35 35 if (historyPos < 0) return; 36 36 String url = history.get(historyPos); 37 browser. loadUrl(url);37 browser.openUrl(url); 38 38 setChanged(); 39 39 notifyObservers(); … … 44 44 if (historyPos >= history.size()) return; 45 45 String url = history.get(historyPos); 46 browser. loadUrl(url);46 browser.openUrl(url); 47 47 setChanged(); 48 48 notifyObservers(); -
trunk/src/org/openstreetmap/josm/gui/help/HelpBrowserProxy.java
r2276 r2308 77 77 /** 78 78 * Direct the help browser to the help page for help topic 79 * <code> helpTopic</code>79 * <code>relativeHelpTopic</code> 80 80 * 81 * @param helpTopic the help topic81 * @param relativeHelpTopic the help topic 82 82 */ 83 public void setUrlForHelpTopic(String helpTopic) {83 public void setUrlForHelpTopic(String relativeHelpTopic) { 84 84 if (helpBrowserProcess == null) { 85 85 launch(); … … 95 95 return; 96 96 } 97 pw.println("setUrlForHelpTopic s " + helpTopic);97 pw.println("setUrlForHelpTopic " + relativeHelpTopic); 98 98 pw.flush(); 99 99 } -
trunk/src/org/openstreetmap/josm/gui/help/HelpUtil.java
r2301 r2308 2 2 package org.openstreetmap.josm.gui.help; 3 3 4 import java.awt.Component; 4 5 import java.awt.event.KeyEvent; 5 6 import java.util.Locale; 7 8 import javax.swing.AbstractButton; 9 import javax.swing.Action; 6 10 import javax.swing.JComponent; 11 import javax.swing.JMenu; 7 12 import javax.swing.KeyStroke; 8 13 9 14 import org.openstreetmap.josm.Main; 15 import org.openstreetmap.josm.tools.LanguageInfo; 10 16 11 17 public class HelpUtil { 12 18 13 19 /** 20 * Replies the base wiki URL. 21 * 22 * @return the base wiki URL 23 */ 24 static public String getWikiBaseUrl() { 25 return Main.pref.get("help.baseurl", "http://josm.openstreetmap.de"); 26 } 27 28 /** 29 * Replies the base wiki URL for help pages 30 * 31 * @return the base wiki URL for help pages 32 */ 33 static public String getWikiBaseHelpUrl() { 34 return getWikiBaseUrl() + "/wiki"; 35 } 36 37 /** 38 * Replies the URL on the wiki for an absolute help topic. The URL is encoded in UTF-8. 39 * 40 * @param absoluteHelpTopic the absolute help topic 41 * @return the url 42 * @see #buildAbsoluteHelpTopic(String) 43 * @see #buildAbsoluteHelpTopic(String, Locale) 44 */ 45 static public String getHelpTopicUrl(String absoluteHelpTopic) { 46 String ret = getWikiBaseHelpUrl(); 47 ret = ret.replaceAll("\\/+$", ""); 48 absoluteHelpTopic =absoluteHelpTopic.replace(" ", "%20"); 49 absoluteHelpTopic = absoluteHelpTopic.replaceAll("^\\/+", "/"); 50 return ret + absoluteHelpTopic; 51 } 52 53 /** 54 * Replies the URL to the edit page for the absolute help topic. 55 * 56 * @param absoluteHelpTopic the absolute help topic 57 * @return the URL to the edit page 58 */ 59 static public String getHelpTopicEditUrl(String absoluteHelpTopic) { 60 String topicUrl = getHelpTopicUrl(absoluteHelpTopic); 61 topicUrl = topicUrl.replaceAll("#[^#]*$", ""); // remove optional fragment 62 return topicUrl + "?action=edit"; 63 } 64 65 /** 66 * Extracts the relative help topic from an URL. Replies null, if 67 * no relative help topic is found. 68 * 69 * @param url the url 70 * @return the relative help topic in the URL, i.e. "/Action/New" 71 */ 72 static public String extractRelativeHelpTopic(String url) { 73 String topic = extractAbsoluteHelpTopic(url); 74 if (topic == null) return null; 75 String pattern = "/[A-Z][a-z]:" + getHelpTopicPrefix(Locale.ENGLISH).replaceAll("^\\/+", ""); 76 if (url.matches(pattern)) 77 return topic.substring(pattern.length()); 78 return null; 79 } 80 81 /** 82 * Extracts the absolute help topic from an URL. Replies null, if 83 * no absolute help topic is found. 84 * 85 * @param url the url 86 * @return the absolute help topic in the URL, i.e. "/De:Help/Action/New" 87 */ 88 static public String extractAbsoluteHelpTopic(String url) { 89 if (!url.startsWith(getWikiBaseHelpUrl())) return null; 90 url = url.substring(getWikiBaseHelpUrl().length()); 91 String prefix = getHelpTopicPrefix(Locale.ENGLISH); 92 if (url.startsWith(prefix)) 93 return url; 94 95 String pattern = "/[A-Z][a-z]:" + prefix.replaceAll("^\\/+", ""); 96 if (url.matches(pattern)) 97 return url; 98 99 return null; 100 } 101 102 /** 103 * Replies the help topic prefix for the current locale. Examples: 104 * <ul> 105 * <li>/Help if the current locale is a locale with language "en"</li> 106 * <li>/De:Help if the current locale is a locale with language "de"</li> 107 * </ul> 108 * 109 * @return the help topic prefix 110 * @see #getHelpTopicPrefix(Locale) 111 */ 112 static public String getHelpTopicPrefix() { 113 return getHelpTopicPrefix(Locale.getDefault()); 114 } 115 116 /** 117 * Replies the help topic prefix for the given locale. Examples: 118 * <ul> 119 * <li>/Help if the locale is a locale with language "en"</li> 120 * <li>/De:Help if the locale is a locale with language "de"</li> 121 * </ul> 122 * 123 * @param locale the locale. {@see Locale#ENGLISH} assumed, if null. 124 * @return the help topic prefix 125 * @see #getHelpTopicPrefix(Locale) 126 */ 127 static public String getHelpTopicPrefix(Locale locale) { 128 if (locale == null) { 129 locale = Locale.ENGLISH; 130 } 131 String ret = Main.pref.get("help.pathhelp", "/Help"); 132 ret = ret.replaceAll("^\\/+", ""); // remove leading / 133 ret = "/" + LanguageInfo.getWikiLanguagePrefix(locale) + ret; 134 return ret; 135 } 136 137 /** 138 * Replies the absolute, localized help topic for the given topic. 139 * 140 * Example: for a topic "/Dialog/RelationEditor" and the locale "de", this method 141 * replies "/De:Help/Dialog/RelationEditor" 142 * 143 * @param topic the relative help topic. Home help topic assumed, if null. 144 * @param locale the locale. {@see Locale#ENGLISH} assumed, if null. 145 * @return the absolute, localized help topic 146 */ 147 static public String buildAbsoluteHelpTopic(String topic, Locale locale) { 148 if (locale == null) { 149 locale = Locale.ENGLISH; 150 } 151 if (topic == null || topic.trim().length() == 0 || topic.trim().equals("/")) 152 return getHelpTopicPrefix(locale); 153 String ret = getHelpTopicPrefix(locale); 154 if (topic.startsWith("/")) { 155 ret += topic; 156 } else { 157 ret += "/" + topic; 158 } 159 ret.replaceAll("\\/+", "\\/"); // just in case, collapse sequences of // 160 return ret; 161 } 162 163 /** 164 * Replies the absolute, localized help topic for the given topic and the 165 * current locale. 166 * 167 * @param topic the relative help topic. Home help topic assumed, if null. 168 * @return the absolute, localized help topic 169 * @see Locale#getDefault() 170 * @see #buildAbsoluteHelpTopic(String, Locale) 171 */ 172 static public String buildAbsoluteHelpTopic(String topic) { 173 return buildAbsoluteHelpTopic(topic, Locale.getDefault()); 174 } 175 176 /** 177 * Replies the context specific help topic configured for <code>context</code>. 178 * 179 * @return the help topic. null, if no context specific help topic is found 180 */ 181 static public String getContextSpecificHelpTopic(Object context) { 182 if (context == null) 183 return null; 184 if (context instanceof Helpful) 185 return ((Helpful)context).helpTopic(); 186 if (context instanceof JMenu) { 187 JMenu b = (JMenu)context; 188 if (b.getClientProperty("help") != null) 189 return (String)b.getClientProperty("help"); 190 return null; 191 } 192 if (context instanceof AbstractButton) { 193 AbstractButton b = (AbstractButton)context; 194 if (b.getClientProperty("help") != null) 195 return (String)b.getClientProperty("help"); 196 return getContextSpecificHelpTopic(b.getAction()); 197 } 198 if (context instanceof Action) 199 return (String)((Action)context).getValue("help"); 200 if (context instanceof JComponent && ((JComponent)context).getClientProperty("help") != null) 201 return (String)((JComponent)context).getClientProperty("help"); 202 if (context instanceof Component) 203 return getContextSpecificHelpTopic(((Component)context).getParent()); 204 return null; 205 } 206 207 /** 14 208 * Makes a component aware of context sensitive help. 15 209 * 16 * @param component the component 17 * @param topic the help topic 18 */ 19 static public void setHelpContext(JComponent component, String topic) { 210 * A relative help topic doesn't start with /Help and doesn't include a locale 211 * code. Example: /Dialog/RelationEditor is a relative help topic, /De:Help/Dialog/RelationEditor 212 * is not. 213 * 214 * 215 * @param component the component the component 216 * @param topic the help topic. Set to the default help topic if null. 217 */ 218 static public void setHelpContext(JComponent component, String relativeHelpTopic) { 219 if (relativeHelpTopic == null) { 220 relativeHelpTopic = ""; 221 } 20 222 component.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F1,0), "help"); 21 223 component.getActionMap().put("help", Main.main.menu.help); 22 component.putClientProperty("help", topic); 23 } 24 224 component.putClientProperty("help", relativeHelpTopic); 225 } 226 227 /** 228 * This is a simple marker method for help topic literals. If you declare a help 229 * topic literal in the source you should enclose it in ht(...). 230 * 231 * <strong>Example</strong> 232 * <pre> 233 * String helpTopic = ht("/Dialog/RelationEditor"); 234 * or 235 * putValue("help", ht("/Dialog/RelationEditor")); 236 * </pre> 237 * 238 * 239 * @param helpTopic 240 */ 241 static public String ht(String helpTopic) { 242 // this is just a marker method 243 return helpTopic; 244 } 25 245 } -
trunk/src/org/openstreetmap/josm/gui/help/help-browser.css
r2274 r2308 19 19 tt {font-family: Courier New} 20 20 pre {font-family: Courier New} 21 .warning-header { 22 font-family: Arial, sans-serif; 23 font-size:24pt; 24 font-weight:bold 25 } 26 .warning-body { 27 background-color:rgb(253,255,221); 28 padding: 10pt; 29 border-color:rgb(128,128,128); 30 border-style: solid; 31 border-width: 1px; 32 } 33 34 .error-header { 35 font-family: Arial, sans-serif; 36 font-size:24pt; 37 font-weight:bold 38 } 39 .error-body { 40 background-color:rgb(254,195,190); 41 padding: 10pt; 42 border-color:rgb(128,128,128); 43 border-style: solid; 44 border-width: 1px; 45 } -
trunk/src/org/openstreetmap/josm/gui/io/UploadDialog.java
r2301 r2308 192 192 JComponent.WHEN_IN_FOCUSED_WINDOW 193 193 ); 194 195 pnl.add(new SideButton(new ContextSensitiveHelpAction("/Help/Dialogs/UploadDialog"))); 196 HelpUtil.setHelpContext(getRootPane(),"/Help/Dialogs/UploadDialog"); 194 pnl.add(new SideButton(new ContextSensitiveHelpAction("/Dialogs/UploadDialog"))); 195 HelpUtil.setHelpContext(getRootPane(),"/Dialogs/UploadDialog"); 197 196 return pnl; 198 197 } -
trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
r2301 r2308 376 376 public void actionPerformed(ActionEvent e) { 377 377 HelpBrowser b = new HelpBrowser(); 378 b. setUrlForHelpTopic("Help/Concepts/Conflict");378 b.openHelpTopic("Help/Concepts/Conflict"); 379 379 b.setVisible(true); 380 380 } … … 383 383 dialog.setContentPane(pane); 384 384 dialog.pack(); 385 HelpUtil.setHelpContext(dialog.getRootPane(), " Concepts/Conflict");385 HelpUtil.setHelpContext(dialog.getRootPane(), "/Concepts/Conflict"); 386 386 WindowGeometry.centerOnScreen(dialog.getSize()).applySafe(dialog); 387 387 dialog.setVisible(true); -
trunk/src/org/openstreetmap/josm/tools/LanguageInfo.java
r1755 r2308 3 3 4 4 import java.util.Locale; 5 import static org.openstreetmap.josm.tools.I18n.tr; 5 6 6 7 public class LanguageInfo { 7 static public String getLanguageCodeWiki() 8 { 9 String languageCode = getLanguageCode(); 10 if(languageCode.equals("en")) 8 9 /** 10 * Replies the wiki language prefix for the given locale. The wiki language 11 * prefix has the form 'Xy:' where 'Xy' is a ISO 639 language code in title 12 * case. 13 * 14 * @param locale the locale 15 * @return the wiki language prefix 16 */ 17 static public String getWikiLanguagePrefix(Locale locale) { 18 String code = getJOSMLocaleCode(locale); 19 if (code.length() == 2) { 20 if (code.equals("en")) return ""; 21 } else if (code.matches("[^_]+_[^_]+")) { 22 code = code.substring(0,2); 23 } else { 24 System.err.println(tr("Warning: failed to derive wiki language prefix from JOSM locale code ''{0}''. Using default code ''en''.", code)); 11 25 return ""; 12 else if(languageCode.equals("pt_BR")) 13 return "Pt:"; 14 return languageCode.substring(0,1).toUpperCase() + languageCode.substring(1) + ":"; 26 } 27 return code.substring(0,1).toUpperCase() + code.substring(1) + ":"; 15 28 } 16 static public String getLanguageCode() 17 { 18 String full = Locale.getDefault().toString(); 29 30 /** 31 * Replies the wiki language prefix for the current locale. 32 * 33 * @return the wiki language prefix 34 * @see Locale#getDefault() 35 * @see #getWikiLanguagePrefix(Locale) 36 */ 37 static public String getWikiLanguagePrefix() { 38 return getWikiLanguagePrefix(Locale.getDefault()); 39 } 40 41 /** 42 * Replies the JOSM locale code for the default locale. 43 * 44 * @return the JOSM locale code for the default locale 45 * @see #getJOSMLocaleCode(Locale) 46 */ 47 static public String getJOSMLocaleCode() { 48 return getJOSMLocaleCode(Locale.getDefault()); 49 } 50 51 /** 52 * Replies the local code used by JOSM for a given locale. 53 * 54 * In most cases JOSM uses the 2-character ISO 639 language code ({@see Locale#getLanguage()} 55 * to identify the locale of a localized resource, but in some cases it may use the 56 * programmatic name for locales, as replied by {@see Locale#toString()}. 57 * 58 * @param locale the locale. Replies "en" if null. 59 * @return the JOSM code for the given locale 60 */ 61 static public String getJOSMLocaleCode(Locale locale) { 62 if (locale == null) return "en"; 63 String full = locale.toString(); 19 64 if (full.equals("iw_IL")) 20 65 return "he"; … … 22 67 else if (full.equals("en_GB")) 23 68 return full; 24 return Locale.getDefault().getLanguage(); 69 70 return locale.getLanguage(); 25 71 } 72 73 26 74 static public String getLanguageCodeXML() 27 75 { 28 return get LanguageCode()+".";76 return getJOSMLocaleCode()+"."; 29 77 } 30 78 static public String getLanguageCodeManifest() 31 79 { 32 return get LanguageCode()+"_";80 return getJOSMLocaleCode()+"_"; 33 81 } 34 82 } -
trunk/src/org/openstreetmap/josm/tools/WikiReader.java
r2274 r2308 35 35 * pathes etc.. 36 36 * 37 * @return Either the string of the content of the wiki page.37 * @return 38 38 * @throws IOException Throws, if the page could not be loaded. 39 39 */ … … 46 46 47 47 public String readLang(String text) { 48 String languageCode = LanguageInfo.get LanguageCodeWiki();48 String languageCode = LanguageInfo.getWikiLanguagePrefix(); 49 49 String url = baseurl + "/wiki/" + languageCode + text; 50 50 String res = "";
Note:
See TracChangeset
for help on using the changeset viewer.