Changeset 1690 in josm for trunk/src/org/openstreetmap/josm/gui
- Timestamp:
- 2009-06-23T22:03:37+02:00 (15 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/gui
- Files:
-
- 1 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/conflict/ConflictResolver.java
r1654 r1690 23 23 import org.openstreetmap.josm.gui.conflict.nodes.NodeListMergeModel; 24 24 import org.openstreetmap.josm.gui.conflict.nodes.NodeListMerger; 25 import org.openstreetmap.josm.gui.conflict.properties.OperationCancelledException; 25 26 import org.openstreetmap.josm.gui.conflict.properties.PropertiesMergeModel; 26 27 import org.openstreetmap.josm.gui.conflict.properties.PropertiesMerger; … … 145 146 this.their = their; 146 147 propertiesMerger.getModel().populate(my, their); 148 if (propertiesMerger.getModel().hasVisibleStateConflict()) { 149 tabbedPane.setEnabledAt(1, false); 150 tabbedPane.setEnabledAt(2, false); 151 tabbedPane.setEnabledAt(3, false); 152 return; 153 } 147 154 tabbedPane.setEnabledAt(0, true); 148 155 tagMerger.getModel().populate(my, their); … … 165 172 tabbedPane.setEnabledAt(3, true); 166 173 } 174 167 175 } 168 176 … … 173 181 * @return the resolution command 174 182 */ 175 public Command buildResolveCommand() {183 public Command buildResolveCommand() throws OperationCancelledException { 176 184 ArrayList<Command> commands = new ArrayList<Command>(); 177 if (tagMerger.getModel().getNumResolvedConflicts() > 0) { 178 commands.add(tagMerger.getModel().buildResolveCommand(my, their)); 179 } 180 commands.addAll(propertiesMerger.getModel().buildResolveCommand(my, their)); 181 if (my instanceof Way && nodeListMerger.getModel().isFrozen()) { 182 NodeListMergeModel model =(NodeListMergeModel)nodeListMerger.getModel(); 183 commands.add(model.buildResolveCommand((Way)my, (Way)their)); 184 } else if (my instanceof Relation && relationMemberMerger.getModel().isFrozen()) { 185 RelationMemberListMergeModel model =(RelationMemberListMergeModel)relationMemberMerger.getModel(); 186 commands.add(model.buildResolveCommand((Relation)my, (Relation)their)); 187 } 188 if (isResolvedCompletely()) { 189 commands.add( 190 new VersionConflictResolveCommand(my, their) 191 ); 185 if (propertiesMerger.getModel().hasVisibleStateConflict()) { 186 if (propertiesMerger.getModel().isDecidedVisibleState()) { 187 commands.addAll(propertiesMerger.getModel().buildResolveCommand(my, their)); 188 } 189 } else { 190 if (tagMerger.getModel().getNumResolvedConflicts() > 0) { 191 commands.add(tagMerger.getModel().buildResolveCommand(my, their)); 192 } 193 commands.addAll(propertiesMerger.getModel().buildResolveCommand(my, their)); 194 if (my instanceof Way && nodeListMerger.getModel().isFrozen()) { 195 NodeListMergeModel model =(NodeListMergeModel)nodeListMerger.getModel(); 196 commands.add(model.buildResolveCommand((Way)my, (Way)their)); 197 } else if (my instanceof Relation && relationMemberMerger.getModel().isFrozen()) { 198 RelationMemberListMergeModel model =(RelationMemberListMergeModel)relationMemberMerger.getModel(); 199 commands.add(model.buildResolveCommand((Relation)my, (Relation)their)); 200 } 201 if (isResolvedCompletely()) { 202 commands.add( 203 new VersionConflictResolveCommand(my, their) 204 ); 205 } 192 206 } 193 207 return new SequenceCommand(tr("Conflict Resolution"), commands); -
trunk/src/org/openstreetmap/josm/gui/conflict/properties/PropertiesMergeModel.java
r1669 r1690 3 3 4 4 import static org.openstreetmap.josm.gui.conflict.MergeDecisionType.UNDECIDED; 5 import static org.openstreetmap.josm.tools.I18n.tr; 5 6 6 7 import java.beans.PropertyChangeListener; 7 8 import java.beans.PropertyChangeSupport; 9 import java.io.IOException; 10 import java.net.HttpURLConnection; 8 11 import java.util.ArrayList; 12 import java.util.HashMap; 9 13 import java.util.List; 10 14 import java.util.Observable; 11 15 16 import javax.swing.JOptionPane; 17 import javax.swing.text.html.HTML; 18 19 import org.openstreetmap.josm.Main; 12 20 import org.openstreetmap.josm.command.Command; 13 21 import org.openstreetmap.josm.command.CoordinateConflictResolveCommand; 14 22 import org.openstreetmap.josm.command.DeletedStateConflictResolveCommand; 23 import org.openstreetmap.josm.command.PurgePrimitivesCommand; 24 import org.openstreetmap.josm.command.UndeletePrimitivesCommand; 15 25 import org.openstreetmap.josm.data.coor.LatLon; 26 import org.openstreetmap.josm.data.osm.DataSet; 16 27 import org.openstreetmap.josm.data.osm.Node; 17 28 import org.openstreetmap.josm.data.osm.OsmPrimitive; 29 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 30 import org.openstreetmap.josm.data.osm.Relation; 31 import org.openstreetmap.josm.data.osm.RelationMember; 32 import org.openstreetmap.josm.data.osm.Way; 33 import org.openstreetmap.josm.gui.PleaseWaitRunnable; 18 34 import org.openstreetmap.josm.gui.conflict.MergeDecisionType; 35 import org.openstreetmap.josm.gui.conflict.properties.PropertiesMerger.KeepMyVisibleStateAction; 36 import org.openstreetmap.josm.io.MultiFetchServerObjectReader; 37 import org.openstreetmap.josm.io.OsmApi; 38 import org.openstreetmap.josm.io.OsmApiException; 39 import org.openstreetmap.josm.io.OsmServerObjectReader; 40 import org.openstreetmap.josm.io.OsmTransferException; 41 import org.xml.sax.SAXException; 19 42 20 43 /** 21 44 * This is the model for resolving conflicts in the properties of the 22 45 * {@see OsmPrimitive}s. In particular, it represents conflicts in the coordiates of {@see Node}s and 23 * the deleted state of {@see OsmPrimitive}s.46 * the deleted or visible state of {@see OsmPrimitive}s. 24 47 * 25 48 * This model is an {@see Observable}. It notifies registered {@see Observer}s whenever the … … 31 54 * @see Node#getCoor() 32 55 * @see OsmPrimitive#deleted 56 * @see OsmPrimitive#visible 33 57 * 34 58 */ … … 37 61 static public final String RESOLVED_COMPLETELY_PROP = PropertiesMergeModel.class.getName() + ".resolvedCompletely"; 38 62 63 private OsmPrimitive my; 64 39 65 private LatLon myCoords; 40 66 private LatLon theirCoords; … … 43 69 private boolean myDeletedState; 44 70 private boolean theirDeletedState; 71 private boolean myVisibleState; 72 private boolean theirVisibleState; 45 73 private MergeDecisionType deletedMergeDecision; 74 private MergeDecisionType visibleMergeDecision; 46 75 private final PropertyChangeSupport support; 47 76 private boolean resolvedCompletely; … … 91 120 92 121 /** 122 * replies true if there is a conflict in the visible state and if this conflict is 123 * resolved 124 * 125 * @return true if there is a conflict in the visible state and if this conflict is 126 * resolved; false, otherwise 127 */ 128 public boolean isDecidedVisibleState() { 129 return ! visibleMergeDecision.equals(UNDECIDED); 130 } 131 132 /** 93 133 * replies true if the current decision for the coordinate conflict is <code>decision</code> 94 134 * … … 111 151 112 152 /** 153 * replies true if the current decision for the visible state conflict is <code>decision</code> 154 * 155 * @return true if the current decision for the visible state conflict is <code>decision</code>; 156 * false, otherwise 157 */ 158 public boolean isVisibleStateDecision(MergeDecisionType decision) { 159 return visibleMergeDecision.equals(decision); 160 } 161 /** 113 162 * populates the model with the differences between my and their version 114 163 * … … 117 166 */ 118 167 public void populate(OsmPrimitive my, OsmPrimitive their) { 168 this.my = my; 119 169 if (my instanceof Node) { 120 170 myCoords = ((Node)my).getCoor(); … … 128 178 theirDeletedState = their.deleted; 129 179 180 myVisibleState = my.visible; 181 theirVisibleState = their.visible; 182 130 183 coordMergeDecision = UNDECIDED; 131 184 deletedMergeDecision = UNDECIDED; 185 visibleMergeDecision = UNDECIDED; 132 186 setChanged(); 133 187 notifyObservers(); … … 209 263 } 210 264 211 public void decideDeletedStateConflict(MergeDecisionType decision) { 265 266 /** 267 * replies my visible state, 268 * @return my visible state 269 */ 270 public Boolean getMyVisibleState() { 271 return myVisibleState; 272 } 273 274 /** 275 * replies their visible state, 276 * @return their visible state 277 */ 278 public Boolean getTheirVisibleState() { 279 return theirVisibleState; 280 } 281 282 /** 283 * replies the merged visible state; null, if the merge decision is 284 * {@see MergeDecisionType#UNDECIDED}. 285 * 286 * @return the merged visible state 287 */ 288 public Boolean getMergedVisibleState() { 289 switch(visibleMergeDecision) { 290 case KEEP_MINE: return myVisibleState; 291 case KEEP_THEIR: return theirVisibleState; 292 case UNDECIDED: return null; 293 } 294 // should not happen 295 return null; 296 } 297 298 /** 299 * decides the conflict between two deleted states 300 * @param decision the decision (must not be null) 301 * 302 * @throws IllegalArgumentException thrown, if decision is null 303 */ 304 public void decideDeletedStateConflict(MergeDecisionType decision) throws IllegalArgumentException{ 305 if (decision == null) 306 throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "decision")); 212 307 this.deletedMergeDecision = decision; 308 setChanged(); 309 notifyObservers(); 310 fireCompletelyResolved(); 311 } 312 313 /** 314 * decides the conflict between two visible states 315 * @param decision the decision (must not be null) 316 * 317 * @throws IllegalArgumentException thrown, if decision is null 318 */ 319 public void decideVisibleStateConflict(MergeDecisionType decision) throws IllegalArgumentException { 320 if (decision == null) 321 throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "decision")); 322 this.visibleMergeDecision = decision; 213 323 setChanged(); 214 324 notifyObservers(); … … 242 352 243 353 /** 354 * replies true if my and their primitive have a conflict between 355 * their visible states 356 * 357 * @return true if my and their primitive have a conflict between 358 * their visible states 359 */ 360 public boolean hasVisibleStateConflict() { 361 return myVisibleState != theirVisibleState; 362 } 363 364 /** 244 365 * replies true if all conflict in this model are resolved 245 366 * … … 254 375 ret = ret && ! deletedMergeDecision.equals(UNDECIDED); 255 376 } 377 if (hasVisibleStateConflict()) { 378 ret = ret && ! visibleMergeDecision.equals(UNDECIDED); 379 } 256 380 return ret; 257 381 } … … 264 388 * @return the list of commands 265 389 */ 266 public List<Command> buildResolveCommand(OsmPrimitive my, OsmPrimitive their) {390 public List<Command> buildResolveCommand(OsmPrimitive my, OsmPrimitive their) throws OperationCancelledException{ 267 391 ArrayList<Command> cmds = new ArrayList<Command>(); 392 if (hasVisibleStateConflict() && isDecidedVisibleState()) { 393 if (isVisibleStateDecision(MergeDecisionType.KEEP_MINE)) { 394 try { 395 UndeletePrimitivesCommand cmd = createUndeletePrimitiveCommand(my); 396 if (cmd == null) 397 throw new OperationCancelledException(); 398 cmds.add(cmd); 399 } catch(OsmTransferException e) { 400 handleExceptionWhileBuildingCommand(e); 401 throw new OperationCancelledException(e); 402 } 403 } else if (isVisibleStateDecision(MergeDecisionType.KEEP_THEIR)) { 404 cmds.add(new PurgePrimitivesCommand(my)); 405 } 406 } 268 407 if (hasCoordConflict() && isDecidedCoord()) { 269 408 cmds.add(new CoordinateConflictResolveCommand((Node)my, (Node)their, coordMergeDecision)); … … 274 413 return cmds; 275 414 } 415 416 public OsmPrimitive getMyPrimitive() { 417 return my; 418 } 419 420 /** 421 * 422 * @param id 423 */ 424 protected void handleExceptionWhileBuildingCommand(Exception e) { 425 e.printStackTrace(); 426 String msg = e.getMessage() != null ? e.getMessage() : e.toString(); 427 msg = msg.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">"); 428 JOptionPane.showMessageDialog( 429 Main.parent, 430 tr("<html>An error occurred while communicating with the server<br>" 431 + "Details: {0}</html>", 432 msg 433 ), 434 tr("Communication with server failed"), 435 JOptionPane.ERROR_MESSAGE 436 ); 437 } 438 439 /** 440 * User has decided to keep his local version of a primitive which had been deleted 441 * on the server 442 * 443 * @param id the primitive id 444 */ 445 protected UndeletePrimitivesCommand createUndeletePrimitiveCommand(OsmPrimitive my) throws OsmTransferException { 446 if (my instanceof Node) 447 return createUndeleteNodeCommand((Node)my); 448 else if (my instanceof Way) 449 return createUndeleteWayCommand((Way)my); 450 else if (my instanceof Relation) 451 return createUndeleteRelationCommand((Relation)my); 452 return null; 453 } 454 /** 455 * Undelete a node which is already deleted on the server. The API 456 * doesn't offer a call for "undeleting" a node. We therefore create 457 * a clone of the node which we flag as new. On the next upload the 458 * server will assign the node a new id. 459 * 460 * @param node the node to undelete 461 */ 462 protected UndeletePrimitivesCommand createUndeleteNodeCommand(Node node) { 463 return new UndeletePrimitivesCommand(node); 464 } 465 466 /** 467 * displays a confirmation message. The user has to confirm that additional dependent 468 * nodes should be undeleted too. 469 * 470 * @param way the way 471 * @param dependent a list of dependent nodes which have to be undelete too 472 * @return true, if the user confirms; false, otherwise 473 */ 474 protected boolean confirmUndeleteDependentPrimitives(Way way, ArrayList<OsmPrimitive> dependent) { 475 String [] options = { 476 tr("Yes, undelete them too"), 477 tr("No, cancel operation") 478 }; 479 int ret = JOptionPane.showOptionDialog( 480 Main.parent, 481 tr("<html>There are {0} additional nodes used by way {1}<br>" 482 + "which are deleted on the server.<br>" 483 + "<br>" 484 + "Do you want to undelete these nodes too?</html>", 485 Long.toString(dependent.size()), Long.toString(way.id)), 486 tr("Undelete additional nodes?"), 487 JOptionPane.YES_NO_OPTION, 488 JOptionPane.QUESTION_MESSAGE, 489 null, 490 options, 491 options[0] 492 ); 493 494 switch(ret) { 495 case JOptionPane.CLOSED_OPTION: return false; 496 case JOptionPane.YES_OPTION: return true; 497 case JOptionPane.NO_OPTION: return false; 498 } 499 return false; 500 501 } 502 503 protected boolean confirmUndeleteDependentPrimitives(Relation r, ArrayList<OsmPrimitive> dependent) { 504 String [] options = { 505 tr("Yes, undelete them too"), 506 tr("No, cancel operation") 507 }; 508 int ret = JOptionPane.showOptionDialog( 509 Main.parent, 510 tr("<html>There are {0} additional primitives referred to by relation {1}<br>" 511 + "which are deleted on the server.<br>" 512 + "<br>" 513 + "Do you want to undelete them too?</html>", 514 Long.toString(dependent.size()), Long.toString(r.id)), 515 tr("Undelete dependent primitives?"), 516 JOptionPane.YES_NO_OPTION, 517 JOptionPane.QUESTION_MESSAGE, 518 null, 519 options, 520 options[0] 521 ); 522 523 switch(ret) { 524 case JOptionPane.CLOSED_OPTION: return false; 525 case JOptionPane.YES_OPTION: return true; 526 case JOptionPane.NO_OPTION: return false; 527 } 528 return false; 529 530 } 531 532 /** 533 * Creates the undelete command for a way which is already deleted on the server. 534 * 535 * This method also checks whether there are additional nodes referred to by 536 * this way which are deleted on the server too. 537 * 538 * @param way the way to undelete 539 * @return the undelete command 540 * @see #createUndeleteNodeCommand(Node) 541 */ 542 protected UndeletePrimitivesCommand createUndeleteWayCommand(final Way way) throws OsmTransferException { 543 544 HashMap<Long,OsmPrimitive> candidates = new HashMap<Long,OsmPrimitive>(); 545 for (Node n : way.nodes) { 546 if (n.id > 0 && ! candidates.values().contains(n)) { 547 candidates.put(n.id, n); 548 } 549 } 550 MultiFetchServerObjectReader reader = new MultiFetchServerObjectReader(); 551 reader.append(candidates.values()); 552 DataSet ds = reader.parseOsm(); 553 554 ArrayList<OsmPrimitive> toDelete = new ArrayList<OsmPrimitive>(); 555 for (OsmPrimitive their : ds.allPrimitives()) { 556 if (candidates.keySet().contains(their.id) && ! their.visible) { 557 toDelete.add(candidates.get(their.id)); 558 } 559 } 560 if (!toDelete.isEmpty()) { 561 if (! confirmUndeleteDependentPrimitives(way, toDelete)) 562 // FIXME: throw exception ? 563 return null; 564 } 565 toDelete.add(way); 566 return new UndeletePrimitivesCommand(toDelete); 567 } 568 569 /** 570 * Creates an undelete command for a relation which is already deleted on the server. 571 * 572 * This method checks whether there are additional primitives referred to by 573 * this relation which are already deleted on the server. 574 * 575 * @param r the relation 576 * @return the undelete command 577 * @see #createUndeleteNodeCommand(Node) 578 */ 579 protected UndeletePrimitivesCommand createUndeleteRelationCommand(final Relation r) throws OsmTransferException { 580 581 HashMap<Long,OsmPrimitive> candidates = new HashMap<Long, OsmPrimitive>(); 582 for (RelationMember m : r.members) { 583 if (m.member.id > 0 && !candidates.values().contains(m.member)) { 584 candidates.put(m.member.id,m.member); 585 } 586 } 587 588 MultiFetchServerObjectReader reader = new MultiFetchServerObjectReader(); 589 reader.append(candidates.values()); 590 DataSet ds = reader.parseOsm(); 591 592 ArrayList<OsmPrimitive> toDelete = new ArrayList<OsmPrimitive>(); 593 for (OsmPrimitive their : ds.allPrimitives()) { 594 if (candidates.keySet().contains(their.id) && ! their.visible) { 595 toDelete.add(candidates.get(their.id)); 596 } 597 } 598 if (!toDelete.isEmpty()) { 599 if (! confirmUndeleteDependentPrimitives(r, toDelete)) 600 // FIXME: throw exception ? 601 return null; 602 } 603 toDelete.add(r); 604 return new UndeletePrimitivesCommand(toDelete); 605 } 606 276 607 } -
trunk/src/org/openstreetmap/josm/gui/conflict/properties/PropertiesMerger.java
r1676 r1690 18 18 import javax.swing.JButton; 19 19 import javax.swing.JLabel; 20 import javax.swing.JOptionPane; 20 21 import javax.swing.JPanel; 21 22 import javax.swing.SwingUtilities; 23 24 import org.openstreetmap.josm.Main; 22 25 import org.openstreetmap.josm.data.coor.LatLon; 26 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 23 27 import org.openstreetmap.josm.gui.conflict.MergeDecisionType; 24 28 import org.openstreetmap.josm.tools.ImageProvider; … … 48 52 private JLabel lblTheirDeletedState; 49 53 54 private JLabel lblMyVisibleState; 55 private JLabel lblMergedVisibleState; 56 private JLabel lblTheirVisibleState; 57 50 58 private final PropertiesMergeModel model; 51 59 … … 59 67 } 60 68 61 protected void build() { 62 setLayout(new GridBagLayout()); 69 protected void buildHeaderRow() { 63 70 GridBagConstraints gc = new GridBagConstraints(); 64 71 65 // ------------------66 72 gc.gridx = 1; 67 73 gc.gridy = 0; … … 88 94 lblTheirVersion.setToolTipText(tr("Properties in their dataset, i.e. the server dataset")); 89 95 add(lblTheirVersion, gc); 90 91 // -------------------------------- 96 } 97 98 protected void buildCoordinateConflictRows() { 99 GridBagConstraints gc = new GridBagConstraints(); 100 92 101 gc.gridx = 0; 93 102 gc.gridy = 1; … … 161 170 JButton btnUndecideCoordinates = new JButton(actUndecideCoordinates); 162 171 add(btnUndecideCoordinates, gc); 163 // --------------------------------------------------- 172 } 173 174 protected void buildDeletedStateConflictRows() { 175 GridBagConstraints gc = new GridBagConstraints(); 164 176 165 177 gc.gridx = 0; … … 191 203 model.addObserver(actKeepMyDeletedState); 192 204 JButton btnKeepMyDeletedState = new JButton(actKeepMyDeletedState); 193 btnKeepMy Coordinates.setName("button.keepmydeletedstate");205 btnKeepMyDeletedState.setName("button.keepmydeletedstate"); 194 206 add(btnKeepMyDeletedState, gc); 195 207 … … 212 224 model.addObserver(actKeepTheirDeletedState); 213 225 JButton btnKeepTheirDeletedState = new JButton(actKeepTheirDeletedState); 214 btnKeep MyCoordinates.setName("button.keeptheirdeletedstate");226 btnKeepTheirDeletedState.setName("button.keeptheirdeletedstate"); 215 227 add(btnKeepTheirDeletedState, gc); 216 228 … … 233 245 model.addObserver(actUndecideDeletedState); 234 246 JButton btnUndecideDeletedState = new JButton(actUndecideDeletedState); 235 btn KeepMyCoordinates.setName("button.undecidedeletedstate");247 btnUndecideDeletedState.setName("button.undecidedeletedstate"); 236 248 add(btnUndecideDeletedState, gc); 237 249 } 250 251 protected void buildVisibleStateRows() { 252 GridBagConstraints gc = new GridBagConstraints(); 253 254 gc.gridx = 0; 255 gc.gridy = 5; 256 gc.gridwidth = 1; 257 gc.gridheight = 1; 258 gc.fill = GridBagConstraints.BOTH; 259 gc.anchor = GridBagConstraints.LINE_START; 260 gc.weightx = 0.0; 261 gc.weighty = 0.0; 262 gc.insets = new Insets(0,5,0,5); 263 add(new JLabel(tr("Visible State:")), gc); 264 265 gc.gridx = 1; 266 gc.gridy = 5; 267 gc.fill = GridBagConstraints.BOTH; 268 gc.anchor = GridBagConstraints.CENTER; 269 gc.weightx = 0.33; 270 gc.weighty = 0.0; 271 add(lblMyVisibleState = buildValueLabel("label.myvisiblestate"), gc); 272 273 gc.gridx = 2; 274 gc.gridy = 5; 275 gc.fill = GridBagConstraints.NONE; 276 gc.anchor = GridBagConstraints.CENTER; 277 gc.weightx = 0.0; 278 gc.weighty = 0.0; 279 KeepMyVisibleStateAction actKeepMyVisibleState = new KeepMyVisibleStateAction(); 280 model.addObserver(actKeepMyVisibleState); 281 JButton btnKeepMyVisibleState = new JButton(actKeepMyVisibleState); 282 btnKeepMyVisibleState.setName("button.keepmyvisiblestate"); 283 add(btnKeepMyVisibleState, gc); 284 285 gc.gridx = 3; 286 gc.gridy = 5; 287 gc.fill = GridBagConstraints.BOTH; 288 gc.anchor = GridBagConstraints.CENTER; 289 gc.weightx = 0.33; 290 gc.weighty = 0.0; 291 add(lblMergedVisibleState = buildValueLabel("label.mergedvisiblestate"), gc); 292 293 gc.gridx = 4; 294 gc.gridy = 5; 295 gc.fill = GridBagConstraints.NONE; 296 gc.anchor = GridBagConstraints.CENTER; 297 gc.weightx = 0.0; 298 gc.weighty = 0.0; 299 KeepTheirVisibleStateAction actKeepTheirVisibleState = new KeepTheirVisibleStateAction(); 300 model.addObserver(actKeepTheirVisibleState); 301 JButton btnKeepTheirVisibleState = new JButton(actKeepTheirVisibleState); 302 btnKeepTheirVisibleState.setName("button.keeptheirvisiblestate"); 303 add(btnKeepTheirVisibleState, gc); 304 305 gc.gridx = 5; 306 gc.gridy = 5; 307 gc.fill = GridBagConstraints.BOTH; 308 gc.anchor = GridBagConstraints.CENTER; 309 gc.weightx = 0.33; 310 gc.weighty = 0.0; 311 add(lblTheirVisibleState = buildValueLabel("label.theirvisiblestate"), gc); 312 313 // --------------------------------------------------- 314 gc.gridx = 3; 315 gc.gridy = 6; 316 gc.fill = GridBagConstraints.NONE; 317 gc.anchor = GridBagConstraints.CENTER; 318 gc.weightx = 0.0; 319 gc.weighty = 0.0; 320 UndecideVisibleStateConflictAction actUndecideVisibleState = new UndecideVisibleStateConflictAction(); 321 model.addObserver(actUndecideVisibleState); 322 JButton btnUndecideVisibleState = new JButton(actUndecideVisibleState); 323 btnUndecideVisibleState.setName("button.undecidevisiblestate"); 324 add(btnUndecideVisibleState, gc); 325 } 326 327 protected void build() { 328 setLayout(new GridBagLayout()); 329 buildHeaderRow(); 330 buildCoordinateConflictRows(); 331 buildDeletedStateConflictRows(); 332 buildVisibleStateRows(); 238 333 } 239 334 … … 265 360 } 266 361 267 protected void updateCoordiates() { 362 public String visibleStateToString(Boolean visible) { 363 if (visible == null) 364 return tr("(none)"); 365 if (visible) 366 return tr("visible (on the server)"); 367 else 368 return tr("not visible (on the server)"); 369 } 370 371 public String visibleStateToStringMerged(Boolean visible) { 372 if (visible == null) 373 return tr("(none)"); 374 if (visible) 375 return tr("Keep a clone of the local version"); 376 else 377 return tr("Physically delete from local dataset"); 378 } 379 380 protected void updateCoordinates() { 268 381 lblMyCoordinates.setText(coordToString(model.getMyCoords())); 269 382 lblMergedCoordinates.setText(coordToString(model.getMergedCoords())); … … 320 433 } 321 434 435 protected void updateVisibleState() { 436 lblMyVisibleState.setText(visibleStateToString(model.getMyVisibleState())); 437 lblMergedVisibleState.setText(visibleStateToStringMerged(model.getMergedVisibleState())); 438 lblTheirVisibleState.setText(visibleStateToString(model.getTheirVisibleState())); 439 440 if (! model.hasVisibleStateConflict()) { 441 lblMyVisibleState.setBackground(BGCOLOR_NO_CONFLICT); 442 lblMergedVisibleState.setBackground(BGCOLOR_NO_CONFLICT); 443 lblTheirVisibleState.setBackground(BGCOLOR_NO_CONFLICT); 444 } else { 445 if (!model.isDecidedVisibleState()) { 446 lblMyVisibleState.setBackground(BGCOLOR_UNDECIDED); 447 lblMergedVisibleState.setBackground(BGCOLOR_NO_CONFLICT); 448 lblTheirVisibleState.setBackground(BGCOLOR_UNDECIDED); 449 } else { 450 lblMyVisibleState.setBackground( 451 model.isVisibleStateDecision(MergeDecisionType.KEEP_MINE) 452 ? BGCOLOR_DECIDED : BGCOLOR_NO_CONFLICT 453 ); 454 lblMergedVisibleState.setBackground(BGCOLOR_DECIDED); 455 lblTheirVisibleState.setBackground( 456 model.isVisibleStateDecision(MergeDecisionType.KEEP_THEIR) 457 ? BGCOLOR_DECIDED : BGCOLOR_NO_CONFLICT 458 ); 459 } 460 } 461 } 462 322 463 public void update(Observable o, Object arg) { 323 updateCoordi ates();464 updateCoordinates(); 324 465 updateDeletedState(); 466 updateVisibleState(); 325 467 } 326 468 … … 418 560 } 419 561 } 562 563 class KeepMyVisibleStateAction extends AbstractAction implements Observer { 564 public KeepMyVisibleStateAction() { 565 putValue(Action.SMALL_ICON, ImageProvider.get("dialogs/conflict", "tagkeepmine")); 566 putValue(Action.SHORT_DESCRIPTION, tr("Keep my visible state")); 567 } 568 569 public void actionPerformed(ActionEvent e) { 570 if (confirmKeepMine()) { 571 model.decideVisibleStateConflict(MergeDecisionType.KEEP_MINE); 572 } 573 } 574 575 public void update(Observable o, Object arg) { 576 setEnabled(model.hasVisibleStateConflict() && ! model.isDecidedVisibleState()); 577 } 578 579 protected boolean confirmKeepMine() { 580 String [] options = { 581 tr("Yes, reset the id"), 582 tr("No, abort") 583 }; 584 int ret = JOptionPane.showOptionDialog( 585 null, 586 tr("<html>To keep your local version, JOSM<br>" 587 + "has to reset the id of {0} {1} to 0.<br>" 588 + "On the next upload the server will assign<br>" 589 + "it a new id.<br>" 590 + "Do yo agree?</html>", 591 OsmPrimitiveType.from(model.getMyPrimitive()).getLocalizedDisplayNamePlural(), 592 model.getMyPrimitive().id 593 ), 594 tr("Reset id to 0"), 595 JOptionPane.YES_NO_OPTION, 596 JOptionPane.QUESTION_MESSAGE, 597 null, 598 options, 599 options[1] 600 ); 601 return ret == JOptionPane.YES_OPTION; 602 } 603 } 604 605 class KeepTheirVisibleStateAction extends AbstractAction implements Observer { 606 public KeepTheirVisibleStateAction() { 607 putValue(Action.SMALL_ICON, ImageProvider.get("dialogs/conflict", "tagkeeptheir")); 608 putValue(Action.SHORT_DESCRIPTION, tr("Keep their visible state")); 609 } 610 611 public void actionPerformed(ActionEvent e) { 612 if (confirmKeepTheir()){ 613 model.decideVisibleStateConflict(MergeDecisionType.KEEP_THEIR); 614 } 615 } 616 617 public void update(Observable o, Object arg) { 618 setEnabled(model.hasVisibleStateConflict() && ! model.isDecidedVisibleState()); 619 } 620 621 protected boolean confirmKeepTheir() { 622 String [] options = { 623 tr("Yes, purge it"), 624 tr("No, abort") 625 }; 626 int ret = JOptionPane.showOptionDialog( 627 null, 628 tr("<html>JOSM will have to remove your local primitive with id {0}<br>" 629 + "from the dataset.<br>" 630 + "Do you agree?</html>", 631 model.getMyPrimitive().id 632 ), 633 tr("Remove from dataset"), 634 JOptionPane.YES_NO_OPTION, 635 JOptionPane.QUESTION_MESSAGE, 636 null, 637 options, 638 options[1] 639 ); 640 return ret == JOptionPane.YES_OPTION; 641 } 642 } 643 644 class UndecideVisibleStateConflictAction extends AbstractAction implements Observer { 645 public UndecideVisibleStateConflictAction() { 646 putValue(Action.SMALL_ICON, ImageProvider.get("dialogs/conflict", "tagundecide")); 647 putValue(Action.SHORT_DESCRIPTION, tr("Undecide conflict between visible state")); 648 } 649 650 public void actionPerformed(ActionEvent e) { 651 model.decideVisibleStateConflict(MergeDecisionType.UNDECIDED); 652 } 653 654 public void update(Observable o, Object arg) { 655 setEnabled(model.hasVisibleStateConflict() && model.isDecidedVisibleState()); 656 } 657 } 420 658 } -
trunk/src/org/openstreetmap/josm/gui/dialogs/ConflictResolutionDialog.java
r1677 r1690 23 23 import org.openstreetmap.josm.command.Command; 24 24 import org.openstreetmap.josm.gui.conflict.ConflictResolver; 25 import org.openstreetmap.josm.gui.conflict.properties.OperationCancelledException; 25 26 import org.openstreetmap.josm.tools.ImageProvider; 26 27 … … 190 191 return; 191 192 } 192 Command cmd = resolver.buildResolveCommand(); 193 Main.main.undoRedo.add(cmd); 193 try { 194 Command cmd = resolver.buildResolveCommand(); 195 Main.main.undoRedo.add(cmd); 196 } catch(OperationCancelledException e) { 197 // do nothing. Exception already reported 198 } 194 199 setVisible(false); 195 200 } -
trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java
r1670 r1690 527 527 final MergeVisitor visitor = new MergeVisitor(Main.main 528 528 .editLayer().data, dataSet); 529 for (final OsmPrimitive osm : dataSet.allPrimitives()) { 530 osm.visit(visitor); 531 } 532 visitor.fixReferences(); 529 visitor.merge(); 533 530 534 531 // copy the merged layer's data source info … … 538 535 Main.main.editLayer().fireDataChange(); 539 536 540 if (visitor. conflicts.isEmpty())537 if (visitor.getConflicts().isEmpty()) 541 538 return; 542 539 final ConflictDialog dlg = Main.map.conflictDialog; 543 dlg.add(visitor. conflicts);540 dlg.add(visitor.getConflicts()); 544 541 JOptionPane.showMessageDialog(Main.parent, 545 542 tr("There were conflicts during import.")); -
trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
r1677 r1690 245 245 public void mergeFrom(final DataSet from) { 246 246 final MergeVisitor visitor = new MergeVisitor(data,from); 247 for (final OsmPrimitive osm : from.allPrimitives()) { 248 osm.visit(visitor); 249 } 250 visitor.fixReferences(); 247 visitor.merge(); 251 248 252 249 Area a = data.getDataSourceArea(); … … 274 271 Main.map.mapView.repaint(); 275 272 276 if (visitor. conflicts.isEmpty())273 if (visitor.getConflicts().isEmpty()) 277 274 return; 278 275 final ConflictDialog dlg = Main.map.conflictDialog; 279 dlg.add(visitor. conflicts);280 JOptionPane.showMessageDialog(Main.parent,tr("There were {0} conflicts during import.", visitor. conflicts.size()));276 dlg.add(visitor.getConflicts()); 277 JOptionPane.showMessageDialog(Main.parent,tr("There were {0} conflicts during import.", visitor.getConflicts().size())); 281 278 if (!dlg.isVisible()) { 282 279 dlg.action.actionPerformed(new ActionEvent(this, 0, ""));
Note:
See TracChangeset
for help on using the changeset viewer.