Changeset 3362 in josm for trunk/src/org/openstreetmap


Ignore:
Timestamp:
2010-07-03T22:08:57+02:00 (10 years ago)
Author:
stoecker
Message:

fix #5182 - Conflict system simplification - patch by Upliner

Location:
trunk/src/org/openstreetmap/josm
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/command/PurgePrimitivesCommand.java

    r3335 r3362  
    4040 *
    4141 */
     42@Deprecated
    4243public class PurgePrimitivesCommand extends ConflictResolveCommand{
    4344
  • trunk/src/org/openstreetmap/josm/command/UndeletePrimitivesCommand.java

    r3262 r3362  
    2626 *
    2727 */
     28@Deprecated
    2829public class UndeletePrimitivesCommand extends ConflictResolveCommand {
    2930    //static private final Logger logger = Logger.getLogger(UndeletePrimitivesCommand.class.getName());
  • trunk/src/org/openstreetmap/josm/command/VersionConflictResolveCommand.java

    r3262 r3362  
    5151        super.executeCommand();
    5252        if (!conflict.getMy().isNew()) {
     53            long myVersion = conflict.getMy().getVersion();
     54            long theirVersion = conflict.getTheir().getVersion();
    5355            conflict.getMy().setOsmId(
    5456                    conflict.getMy().getId(),
    55                     (int)Math.max(conflict.getMy().getVersion(), conflict.getTheir().getVersion())
     57                    (int)Math.max(myVersion, theirVersion)
    5658            );
     59            // update visiblity state
     60            if (theirVersion >= myVersion) {
     61                conflict.getMy().setVisible(conflict.getTheir().isVisible());
     62            }
    5763        }
    5864        getLayer().getConflicts().remove(conflict);
  • trunk/src/org/openstreetmap/josm/data/osm/DataSet.java

    r3348 r3362  
    997997        }
    998998    }
     999
     1000    /**
     1001     * Marks all "invisible" objects as deleted. These objects should be always marked as
     1002     * deleted when downloaded from the server. They can be undeleted later if necessary.
     1003     *
     1004     */
     1005    public void deleteInvisible() {
     1006        for (OsmPrimitive primitive:allPrimitives) {
     1007            if (!primitive.isVisible()) {
     1008                primitive.setDeleted(true);
     1009            }
     1010        }
     1011    }
    9991012}
  • trunk/src/org/openstreetmap/josm/data/osm/DataSetMerger.java

    r3336 r3362  
    1111import java.util.Map;
    1212import java.util.Set;
    13 import java.util.logging.Logger;
    1413
    1514import org.openstreetmap.josm.data.conflict.Conflict;
     
    2322 */
    2423public class DataSetMerger {
    25     private static Logger logger = Logger.getLogger(DataSetMerger.class.getName());
    2624
    2725    /** the collection of conflicts created during merging */
     
    244242            // target.version > source.version => keep target version
    245243            return true;
    246         if (! target.isVisible() && source.isVisible() && target.getVersion() == source.getVersion()) {
    247             // should not happen
    248             conflicts.add(target,source);
    249         } else if (target.isVisible() && ! source.isVisible()) {
    250             // this is always a conflict because the user has to decide whether
    251             // he wants to create a clone of its target primitive or whether he
    252             // wants to purge the target from the local dataset. He can't keep it unchanged
    253             // because it was deleted on the server.
    254             //
    255             conflicts.add(target,source);
    256         } else if (target.isIncomplete() && !source.isIncomplete()) {
     244
     245        if (target.isIncomplete() && !source.isIncomplete()) {
    257246            // target is incomplete, source completes it
    258247            // => merge source into target
  • trunk/src/org/openstreetmap/josm/gui/conflict/pair/ConflictResolver.java

    r3083 r3362  
    2626import org.openstreetmap.josm.gui.conflict.pair.nodes.NodeListMergeModel;
    2727import org.openstreetmap.josm.gui.conflict.pair.nodes.NodeListMerger;
    28 import org.openstreetmap.josm.gui.conflict.pair.properties.OperationCancelledException;
    2928import org.openstreetmap.josm.gui.conflict.pair.properties.PropertiesMergeModel;
    3029import org.openstreetmap.josm.gui.conflict.pair.properties.PropertiesMerger;
     
    235234        this.conflict = conflict;
    236235        propertiesMerger.populate(conflict);
    237         if (propertiesMerger.getModel().hasVisibleStateConflict()) {
    238             tabbedPane.setEnabledAt(1, false);
    239             tabbedPane.setEnabledAt(2, false);
    240             tabbedPane.setEnabledAt(3, false);
    241             return;
    242         }
     236
    243237        tabbedPane.setEnabledAt(0, true);
    244238        tagMerger.populate(conflict);
     
    270264     * @return the resolution command
    271265     */
    272     public Command buildResolveCommand() throws OperationCancelledException {
     266    public Command buildResolveCommand() {
    273267        ArrayList<Command> commands = new ArrayList<Command>();
    274         if (propertiesMerger.getModel().hasVisibleStateConflict()) {
    275             if (propertiesMerger.getModel().isDecidedVisibleState()) {
    276                 commands.addAll(propertiesMerger.getModel().buildResolveCommand(conflict));
    277             }
    278         } else {
    279             if (tagMerger.getModel().getNumResolvedConflicts() > 0) {
    280                 commands.add(tagMerger.getModel().buildResolveCommand(conflict));
    281             }
    282             commands.addAll(propertiesMerger.getModel().buildResolveCommand(conflict));
    283             if (my instanceof Way && nodeListMerger.getModel().isFrozen()) {
    284                 NodeListMergeModel model  =(NodeListMergeModel)nodeListMerger.getModel();
    285                 commands.add(model.buildResolveCommand(conflict));
    286             } else if (my instanceof Relation && relationMemberMerger.getModel().isFrozen()) {
    287                 RelationMemberListMergeModel model  =(RelationMemberListMergeModel)relationMemberMerger.getModel();
    288                 commands.add(model.buildResolveCommand((Relation)my, (Relation)their));
    289             }
    290             if (isResolvedCompletely()) {
    291                 commands.add(new VersionConflictResolveCommand(conflict));
    292                 commands.add(new ModifiedConflictResolveCommand(conflict));
    293             }
     268
     269        if (tagMerger.getModel().getNumResolvedConflicts() > 0) {
     270            commands.add(tagMerger.getModel().buildResolveCommand(conflict));
     271        }
     272        commands.addAll(propertiesMerger.getModel().buildResolveCommand(conflict));
     273        if (my instanceof Way && nodeListMerger.getModel().isFrozen()) {
     274            NodeListMergeModel model = (NodeListMergeModel) nodeListMerger.getModel();
     275            commands.add(model.buildResolveCommand(conflict));
     276        } else if (my instanceof Relation && relationMemberMerger.getModel().isFrozen()) {
     277            RelationMemberListMergeModel model = (RelationMemberListMergeModel) relationMemberMerger.getModel();
     278            commands.add(model.buildResolveCommand((Relation) my, (Relation) their));
     279        }
     280        if (isResolvedCompletely()) {
     281            commands.add(new VersionConflictResolveCommand(conflict));
     282            commands.add(new ModifiedConflictResolveCommand(conflict));
    294283        }
    295284        return new SequenceCommand(tr("Conflict Resolution"), commands);
  • trunk/src/org/openstreetmap/josm/gui/conflict/pair/properties/PropertiesMergeModel.java

    r3083 r3362  
    33
    44import static org.openstreetmap.josm.gui.conflict.pair.MergeDecisionType.UNDECIDED;
    5 import static org.openstreetmap.josm.tools.I18n.tr;
    6 import static org.openstreetmap.josm.tools.I18n.trn;
    75
    86import java.beans.PropertyChangeListener;
     
    108import java.util.ArrayList;
    119import java.util.Collections;
    12 import java.util.HashMap;
    1310import java.util.List;
    1411import java.util.Observable;
    1512
    16 import javax.swing.JOptionPane;
    17 
    18 import org.openstreetmap.josm.Main;
    1913import org.openstreetmap.josm.command.Command;
    2014import org.openstreetmap.josm.command.CoordinateConflictResolveCommand;
    2115import org.openstreetmap.josm.command.DeletedStateConflictResolveCommand;
    22 import org.openstreetmap.josm.command.PurgePrimitivesCommand;
    23 import org.openstreetmap.josm.command.UndeletePrimitivesCommand;
    2416import org.openstreetmap.josm.data.conflict.Conflict;
    2517import org.openstreetmap.josm.data.coor.LatLon;
    26 import org.openstreetmap.josm.data.osm.DataSet;
    2718import org.openstreetmap.josm.data.osm.Node;
    2819import org.openstreetmap.josm.data.osm.OsmPrimitive;
    29 import org.openstreetmap.josm.data.osm.Relation;
    30 import org.openstreetmap.josm.data.osm.RelationMember;
    31 import org.openstreetmap.josm.data.osm.Way;
    3220import org.openstreetmap.josm.gui.conflict.pair.MergeDecisionType;
    33 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    34 import org.openstreetmap.josm.io.MultiFetchServerObjectReader;
    35 import org.openstreetmap.josm.io.OsmTransferException;
    3621import org.openstreetmap.josm.tools.CheckParameterUtil;
    3722
     
    6550    private boolean myDeletedState;
    6651    private boolean theirDeletedState;
    67     private boolean myVisibleState;
    68     private boolean theirVisibleState;
    6952    private List<OsmPrimitive> myReferrers;
    7053    private List<OsmPrimitive> theirReferrers;
    7154    private MergeDecisionType deletedMergeDecision;
    72     private MergeDecisionType visibleMergeDecision;
    7355    private final PropertyChangeSupport support;
    7456    private boolean resolvedCompletely;
     
    118100
    119101    /**
    120      * replies true if there is a  conflict in the visible state and if this conflict is
    121      * resolved
    122      *
    123      * @return true if there is a conflict in the visible state and if this conflict is
    124      * resolved; false, otherwise
    125      */
    126     public boolean isDecidedVisibleState() {
    127         return ! visibleMergeDecision.equals(UNDECIDED);
    128     }
    129 
    130     /**
    131102     * replies true if the current decision for the coordinate conflict is <code>decision</code>
    132103     *
     
    148119    }
    149120
    150     /**
    151      * replies true if the current decision for the visible state conflict is <code>decision</code>
    152      *
    153      * @return true if the current decision for the visible state conflict is <code>decision</code>;
    154      *  false, otherwise
    155      */
    156     public boolean isVisibleStateDecision(MergeDecisionType decision) {
    157         return visibleMergeDecision.equals(decision);
    158     }
    159121    /**
    160122     * populates the model with the differences between my and their version
     
    177139        theirDeletedState = their.isDeleted();
    178140
    179         myVisibleState = my.isVisible();
    180         theirVisibleState = their.isVisible();
    181 
    182141        myReferrers = my.getDataSet() == null?Collections.<OsmPrimitive>emptyList():my.getReferrers();
    183142        theirReferrers = their.getDataSet() == null?Collections.<OsmPrimitive>emptyList():their.getReferrers();
     
    185144        coordMergeDecision = UNDECIDED;
    186145        deletedMergeDecision = UNDECIDED;
    187         visibleMergeDecision = UNDECIDED;
    188146        setChanged();
    189147        notifyObservers();
     
    265223
    266224    /**
    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     /**
    283225     * returns my referrers,
    284226     * @return my referrers
     
    294236    public List<OsmPrimitive> getTheirReferrers() {
    295237        return theirReferrers;
    296     }
    297 
    298     /**
    299      * replies the merged visible state; null, if the merge decision is
    300      * {@see MergeDecisionType#UNDECIDED}.
    301      *
    302      * @return the merged visible state
    303      */
    304     public Boolean getMergedVisibleState() {
    305         switch(visibleMergeDecision) {
    306         case KEEP_MINE: return myVisibleState;
    307         case KEEP_THEIR: return theirVisibleState;
    308         case UNDECIDED: return null;
    309         }
    310         // should not happen
    311         return null;
    312238    }
    313239
     
    346272
    347273    /**
    348      * decides the conflict between two visible states
    349      * @param decision the decision (must not be null)
    350      *
    351      * @throws IllegalArgumentException thrown, if decision is null
    352      */
    353     public void decideVisibleStateConflict(MergeDecisionType decision) throws IllegalArgumentException {
    354         CheckParameterUtil.ensureParameterNotNull(decision, "decision");
    355         this.visibleMergeDecision = decision;
    356         setChanged();
    357         notifyObservers();
    358         fireCompletelyResolved();
    359     }
    360 
    361     /**
    362274     * replies true if my and their primitive have a conflict between
    363275     * their coordinate values
     
    385297
    386298    /**
    387      * replies true if my and their primitive have a conflict between
    388      * their visible states
    389      *
    390      * @return true if my and their primitive have a conflict between
    391      * their visible states
    392      */
    393     public boolean hasVisibleStateConflict() {
    394         return myVisibleState != theirVisibleState;
    395     }
    396 
    397     /**
    398299     * replies true if all conflict in this model are resolved
    399300     *
     
    408309            ret = ret && ! deletedMergeDecision.equals(UNDECIDED);
    409310        }
    410         if (hasVisibleStateConflict()) {
    411             ret = ret && ! visibleMergeDecision.equals(UNDECIDED);
    412         }
    413311        return ret;
    414312    }
     
    421319     * @return the list of commands
    422320     */
    423     public List<Command> buildResolveCommand(Conflict<? extends OsmPrimitive> conflict) throws OperationCancelledException{
    424         OsmPrimitive my = conflict.getMy();
     321    public List<Command> buildResolveCommand(Conflict<? extends OsmPrimitive> conflict) {
    425322        List<Command> cmds = new ArrayList<Command>();
    426         if (hasVisibleStateConflict() && isDecidedVisibleState()) {
    427             if (isVisibleStateDecision(MergeDecisionType.KEEP_MINE)) {
    428                 try {
    429                     UndeletePrimitivesCommand cmd = createUndeletePrimitiveCommand(my);
    430                     if (cmd == null)
    431                         throw new OperationCancelledException();
    432                     cmds.add(cmd);
    433                 } catch(OsmTransferException e) {
    434                     handleExceptionWhileBuildingCommand(e);
    435                     throw new OperationCancelledException(e);
    436                 }
    437             } else if (isVisibleStateDecision(MergeDecisionType.KEEP_THEIR)) {
    438                 cmds.add(new PurgePrimitivesCommand(my));
    439             }
    440         }
    441323        if (hasCoordConflict() && isDecidedCoord()) {
    442324            cmds.add(new CoordinateConflictResolveCommand(conflict, coordMergeDecision));
     
    452334    }
    453335
    454     /**
    455      *
    456      * @param id
    457      */
    458     protected void handleExceptionWhileBuildingCommand(Exception e) {
    459         e.printStackTrace();
    460         String msg = e.getMessage() != null ? e.getMessage() : e.toString();
    461         msg = msg.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
    462         JOptionPane.showMessageDialog(
    463                 Main.parent,
    464                 tr("<html>An error occurred while communicating with the server<br>"
    465                         + "Details: {0}</html>",
    466                         msg
    467                 ),
    468                 tr("Communication with server failed"),
    469                 JOptionPane.ERROR_MESSAGE
    470         );
    471     }
    472 
    473     /**
    474      * User has decided to keep his local version of a primitive which had been deleted
    475      * on the server
    476      *
    477      * @param id the primitive id
    478      */
    479     protected UndeletePrimitivesCommand createUndeletePrimitiveCommand(OsmPrimitive my) throws OsmTransferException {
    480         if (my instanceof Node)
    481             return createUndeleteNodeCommand((Node)my);
    482         else if (my instanceof Way)
    483             return createUndeleteWayCommand((Way)my);
    484         else if (my instanceof Relation)
    485             return createUndeleteRelationCommand((Relation)my);
    486         return null;
    487     }
    488     /**
    489      * Undelete a node which is already deleted on the server. The API
    490      * doesn't offer a call for "undeleting" a node. We therefore create
    491      * a clone of the node which we flag as new. On the next upload the
    492      * server will assign the node a new id.
    493      *
    494      * @param node the node to undelete
    495      */
    496     protected UndeletePrimitivesCommand  createUndeleteNodeCommand(Node node) {
    497         return new UndeletePrimitivesCommand(node);
    498     }
    499 
    500     /**
    501      * displays a confirmation message. The user has to confirm that additional dependent
    502      * nodes should be undeleted too.
    503      *
    504      * @param way  the way
    505      * @param dependent a list of dependent nodes which have to be undelete too
    506      * @return true, if the user confirms; false, otherwise
    507      */
    508     protected boolean confirmUndeleteDependentPrimitives(Way way, ArrayList<OsmPrimitive> dependent) {
    509         String [] options = {
    510                 tr("Yes, undelete them too"),
    511                 tr("No, cancel operation")
    512         };
    513         int ret = JOptionPane.showOptionDialog(
    514                 Main.parent,
    515                 "<html>" + trn("There is {0} additional node used by way {1}<br>"
    516                         + "which is deleted on the server."
    517                         + "<br><br>"
    518                         + "Do you want to undelete this node too?",
    519                         "There are {0} additional nodes used by way {1}<br>"
    520                         + "which are deleted on the server."
    521                         + "<br><br>"
    522                         + "Do you want to undelete these nodes too?",
    523                         dependent.size(), dependent.size(), way.getId())
    524                         + "</html>",
    525                         tr("Undelete additional nodes?"),
    526                         JOptionPane.YES_NO_OPTION,
    527                         JOptionPane.QUESTION_MESSAGE,
    528                         null,
    529                         options,
    530                         options[0]
    531         );
    532 
    533         switch(ret) {
    534         case JOptionPane.CLOSED_OPTION: return false;
    535         case JOptionPane.YES_OPTION: return true;
    536         case JOptionPane.NO_OPTION: return false;
    537         }
    538         return false;
    539 
    540     }
    541 
    542     protected boolean confirmUndeleteDependentPrimitives(Relation r, ArrayList<OsmPrimitive> dependent) {
    543         String [] options = {
    544                 tr("Yes, undelete them too"),
    545                 tr("No, cancel operation")
    546         };
    547         int ret = JOptionPane.showOptionDialog(
    548                 Main.parent,
    549                 "<html>" + trn("There is {0} additional primitive referred to by relation {1}<br>"
    550                         + "which is deleted on the server."
    551                         + "<br><br>"
    552                         + "Do you want to undelete this too?",
    553                         "There are {0} additional primitives referred to by relation {1}<br>"
    554                         + "which are deleted on the server."
    555                         + "<br><br>"
    556                         + "Do you want to undelete these too?",
    557                         dependent.size(), dependent.size(), r.getId())
    558                         + "</html>",
    559                         tr("Undelete dependent primitives?"),
    560                         JOptionPane.YES_NO_OPTION,
    561                         JOptionPane.QUESTION_MESSAGE,
    562                         null,
    563                         options,
    564                         options[0]
    565         );
    566 
    567         switch(ret) {
    568         case JOptionPane.CLOSED_OPTION: return false;
    569         case JOptionPane.YES_OPTION: return true;
    570         case JOptionPane.NO_OPTION: return false;
    571         }
    572         return false;
    573 
    574     }
    575 
    576     /**
    577      * Creates the undelete command for a way which is already deleted on the server.
    578      *
    579      * This method also checks whether there are additional nodes referred to by
    580      * this way which are deleted on the server too.
    581      *
    582      * @param way the way to undelete
    583      * @return the undelete command
    584      * @see #createUndeleteNodeCommand(Node)
    585      */
    586     protected UndeletePrimitivesCommand createUndeleteWayCommand(final Way way) throws OsmTransferException {
    587 
    588         HashMap<Long,OsmPrimitive> candidates = new HashMap<Long,OsmPrimitive>();
    589         for (Node n : way.getNodes()) {
    590             if (!n.isNew() && !candidates.values().contains(n)) {
    591                 candidates.put(n.getId(), n);
    592             }
    593         }
    594         MultiFetchServerObjectReader reader = new MultiFetchServerObjectReader();
    595         reader.append(candidates.values());
    596         DataSet ds = reader.parseOsm(NullProgressMonitor.INSTANCE);
    597 
    598         ArrayList<OsmPrimitive> toDelete = new ArrayList<OsmPrimitive>();
    599         for (OsmPrimitive their : ds.allPrimitives()) {
    600             if (candidates.keySet().contains(their.getId()) && ! their.isVisible()) {
    601                 toDelete.add(candidates.get(their.getId()));
    602             }
    603         }
    604         if (!toDelete.isEmpty()) {
    605             if (! confirmUndeleteDependentPrimitives(way, toDelete))
    606                 // FIXME: throw exception ?
    607                 return null;
    608         }
    609         toDelete.add(way);
    610         return new UndeletePrimitivesCommand(toDelete);
    611     }
    612 
    613     /**
    614      * Creates an undelete command for a relation which is already deleted on the server.
    615      *
    616      * This method  checks whether there are additional primitives referred to by
    617      * this relation which are already deleted on the server.
    618      *
    619      * @param r the relation
    620      * @return the undelete command
    621      * @see #createUndeleteNodeCommand(Node)
    622      */
    623     protected UndeletePrimitivesCommand createUndeleteRelationCommand(final Relation r) throws OsmTransferException {
    624 
    625         HashMap<Long,OsmPrimitive> candidates = new HashMap<Long, OsmPrimitive>();
    626         for (RelationMember m : r.getMembers()) {
    627             if (!m.getMember().isNew() && !candidates.values().contains(m.getMember())) {
    628                 candidates.put(m.getMember().getId(), m.getMember());
    629             }
    630         }
    631 
    632         MultiFetchServerObjectReader reader = new MultiFetchServerObjectReader();
    633         reader.append(candidates.values());
    634         DataSet ds = reader.parseOsm(NullProgressMonitor.INSTANCE);
    635 
    636         ArrayList<OsmPrimitive> toDelete = new ArrayList<OsmPrimitive>();
    637         for (OsmPrimitive their : ds.allPrimitives()) {
    638             if (candidates.keySet().contains(their.getId()) && ! their.isVisible()) {
    639                 toDelete.add(candidates.get(their.getId()));
    640             }
    641         }
    642         if (!toDelete.isEmpty()) {
    643             if (! confirmUndeleteDependentPrimitives(r, toDelete))
    644                 // FIXME: throw exception ?
    645                 return null;
    646         }
    647         toDelete.add(r);
    648         return new UndeletePrimitivesCommand(toDelete);
    649     }
    650 
    651336}
  • trunk/src/org/openstreetmap/josm/gui/conflict/pair/properties/PropertiesMerger.java

    r3218 r3362  
    1919import javax.swing.JButton;
    2020import javax.swing.JLabel;
    21 import javax.swing.JOptionPane;
    2221import javax.swing.JPanel;
    2322
     
    5453    private JLabel lblTheirDeletedState;
    5554
    56     private JLabel lblMyVisibleState;
    57     private JLabel lblMergedVisibleState;
    58     private JLabel lblTheirVisibleState;
    59 
    6055    private JLabel lblMyReferrers;
    6156    private JLabel lblTheirReferrers;
     
    251246    }
    252247
    253     protected void buildVisibleStateRows() {
    254         GridBagConstraints gc = new GridBagConstraints();
    255 
    256         gc.gridx = 0;
    257         gc.gridy = 5;
    258         gc.gridwidth = 1;
    259         gc.gridheight = 1;
    260         gc.fill = GridBagConstraints.BOTH;
    261         gc.anchor = GridBagConstraints.LINE_START;
    262         gc.weightx = 0.0;
    263         gc.weighty = 0.0;
    264         gc.insets = new Insets(0,5,0,5);
    265         add(new JLabel(tr("Visible State:")), gc);
    266 
    267         gc.gridx = 1;
    268         gc.gridy = 5;
    269         gc.fill = GridBagConstraints.BOTH;
    270         gc.anchor = GridBagConstraints.CENTER;
    271         gc.weightx = 0.33;
    272         gc.weighty = 0.0;
    273         add(lblMyVisibleState = buildValueLabel("label.myvisiblestate"), gc);
    274 
    275         gc.gridx = 2;
    276         gc.gridy = 5;
    277         gc.fill = GridBagConstraints.NONE;
    278         gc.anchor = GridBagConstraints.CENTER;
    279         gc.weightx = 0.0;
    280         gc.weighty = 0.0;
    281         KeepMyVisibleStateAction actKeepMyVisibleState = new KeepMyVisibleStateAction();
    282         model.addObserver(actKeepMyVisibleState);
    283         JButton btnKeepMyVisibleState = new JButton(actKeepMyVisibleState);
    284         btnKeepMyVisibleState.setName("button.keepmyvisiblestate");
    285         add(btnKeepMyVisibleState, gc);
    286 
    287         gc.gridx = 3;
    288         gc.gridy = 5;
    289         gc.fill = GridBagConstraints.BOTH;
    290         gc.anchor = GridBagConstraints.CENTER;
    291         gc.weightx = 0.33;
    292         gc.weighty = 0.0;
    293         add(lblMergedVisibleState = buildValueLabel("label.mergedvisiblestate"), gc);
    294 
    295         gc.gridx = 4;
    296         gc.gridy = 5;
    297         gc.fill = GridBagConstraints.NONE;
    298         gc.anchor = GridBagConstraints.CENTER;
    299         gc.weightx = 0.0;
    300         gc.weighty = 0.0;
    301         KeepTheirVisibleStateAction actKeepTheirVisibleState = new KeepTheirVisibleStateAction();
    302         model.addObserver(actKeepTheirVisibleState);
    303         JButton btnKeepTheirVisibleState = new JButton(actKeepTheirVisibleState);
    304         btnKeepTheirVisibleState.setName("button.keeptheirvisiblestate");
    305         add(btnKeepTheirVisibleState, gc);
    306 
    307         gc.gridx = 5;
    308         gc.gridy = 5;
    309         gc.fill = GridBagConstraints.BOTH;
    310         gc.anchor = GridBagConstraints.CENTER;
    311         gc.weightx = 0.33;
    312         gc.weighty = 0.0;
    313         add(lblTheirVisibleState = buildValueLabel("label.theirvisiblestate"), gc);
    314 
    315         // ---------------------------------------------------
    316         gc.gridx = 3;
    317         gc.gridy = 6;
    318         gc.fill = GridBagConstraints.NONE;
    319         gc.anchor = GridBagConstraints.CENTER;
    320         gc.weightx = 0.0;
    321         gc.weighty = 0.0;
    322         UndecideVisibleStateConflictAction actUndecideVisibleState = new UndecideVisibleStateConflictAction();
    323         model.addObserver(actUndecideVisibleState);
    324         JButton btnUndecideVisibleState = new JButton(actUndecideVisibleState);
    325         btnUndecideVisibleState.setName("button.undecidevisiblestate");
    326         add(btnUndecideVisibleState, gc);
    327     }
    328 
    329248    protected void buildReferrersRow() {
    330249        GridBagConstraints gc = new GridBagConstraints();
     
    363282        buildCoordinateConflictRows();
    364283        buildDeletedStateConflictRows();
    365         buildVisibleStateRows();
    366284        buildReferrersRow();
    367285    }
     
    392310        else
    393311            return tr("not deleted");
    394     }
    395 
    396     public String visibleStateToString(Boolean visible) {
    397         if (visible == null)
    398             return tr("(none)");
    399         if (visible)
    400             return tr("visible (on the server)");
    401         else
    402             return tr("not visible (on the server)");
    403     }
    404 
    405     public String visibleStateToStringMerged(Boolean visible) {
    406         if (visible == null)
    407             return tr("(none)");
    408         if (visible)
    409             return tr("Keep a clone of the local version");
    410         else
    411             return tr("Physically delete from local dataset");
    412312    }
    413313
     
    478378    }
    479379
    480     protected void updateVisibleState() {
    481         lblMyVisibleState.setText(visibleStateToString(model.getMyVisibleState()));
    482         lblMergedVisibleState.setText(visibleStateToStringMerged(model.getMergedVisibleState()));
    483         lblTheirVisibleState.setText(visibleStateToString(model.getTheirVisibleState()));
    484 
    485         if (! model.hasVisibleStateConflict()) {
    486             lblMyVisibleState.setBackground(BGCOLOR_NO_CONFLICT);
    487             lblMergedVisibleState.setBackground(BGCOLOR_NO_CONFLICT);
    488             lblTheirVisibleState.setBackground(BGCOLOR_NO_CONFLICT);
    489         } else {
    490             if (!model.isDecidedVisibleState()) {
    491                 lblMyVisibleState.setBackground(BGCOLOR_UNDECIDED);
    492                 lblMergedVisibleState.setBackground(BGCOLOR_NO_CONFLICT);
    493                 lblTheirVisibleState.setBackground(BGCOLOR_UNDECIDED);
    494             } else {
    495                 lblMyVisibleState.setBackground(
    496                         model.isVisibleStateDecision(MergeDecisionType.KEEP_MINE)
    497                         ? BGCOLOR_DECIDED : BGCOLOR_NO_CONFLICT
    498                 );
    499                 lblMergedVisibleState.setBackground(BGCOLOR_DECIDED);
    500                 lblTheirVisibleState.setBackground(
    501                         model.isVisibleStateDecision(MergeDecisionType.KEEP_THEIR)
    502                         ? BGCOLOR_DECIDED : BGCOLOR_NO_CONFLICT
    503                 );
    504             }
    505         }
    506     }
    507 
    508380    protected void updateReferrers() {
    509381        lblMyReferrers.setText(referrersToString(model.getMyReferrers()));
     
    516388        updateCoordinates();
    517389        updateDeletedState();
    518         updateVisibleState();
    519390        updateReferrers();
    520391    }
     
    611482        public void update(Observable o, Object arg) {
    612483            setEnabled(model.hasDeletedStateConflict() && model.isDecidedDeletedState());
    613         }
    614     }
    615 
    616     class KeepMyVisibleStateAction extends AbstractAction implements Observer {
    617         public KeepMyVisibleStateAction() {
    618             putValue(Action.SMALL_ICON, ImageProvider.get("dialogs/conflict", "tagkeepmine"));
    619             putValue(Action.SHORT_DESCRIPTION, tr("Keep my visible state"));
    620         }
    621 
    622         public void actionPerformed(ActionEvent e) {
    623             if (confirmKeepMine()) {
    624                 model.decideVisibleStateConflict(MergeDecisionType.KEEP_MINE);
    625             }
    626         }
    627 
    628         public void update(Observable o, Object arg) {
    629             setEnabled(model.hasVisibleStateConflict() && ! model.isDecidedVisibleState());
    630         }
    631 
    632         protected boolean confirmKeepMine() {
    633             String [] options = {
    634                     tr("Yes, reset the id"),
    635                     tr("No, abort")
    636             };
    637             int ret = JOptionPane.showOptionDialog(
    638                     null,
    639                     tr("<html>To keep your local version, JOSM<br>"
    640                             + "has to reset the id of primitive {0} to 0.<br>"
    641                             + "On the next upload the server will assign<br>"
    642                             + "it a new id.<br>"
    643                             + "Do you agree?</html>",
    644                             model.getMyPrimitive().getId()
    645                     ),
    646                     tr("Reset id to 0"),
    647                     JOptionPane.YES_NO_OPTION,
    648                     JOptionPane.QUESTION_MESSAGE,
    649                     null,
    650                     options,
    651                     options[1]
    652             );
    653             return ret == JOptionPane.YES_OPTION;
    654         }
    655     }
    656 
    657     class KeepTheirVisibleStateAction extends AbstractAction implements Observer {
    658         public KeepTheirVisibleStateAction() {
    659             putValue(Action.SMALL_ICON, ImageProvider.get("dialogs/conflict", "tagkeeptheir"));
    660             putValue(Action.SHORT_DESCRIPTION, tr("Keep their visible state"));
    661         }
    662 
    663         public void actionPerformed(ActionEvent e) {
    664             if (confirmKeepTheir()){
    665                 model.decideVisibleStateConflict(MergeDecisionType.KEEP_THEIR);
    666             }
    667         }
    668 
    669         public void update(Observable o, Object arg) {
    670             setEnabled(model.hasVisibleStateConflict() && ! model.isDecidedVisibleState());
    671         }
    672 
    673         protected boolean confirmKeepTheir() {
    674             String [] options = {
    675                     tr("Yes, purge it"),
    676                     tr("No, abort")
    677             };
    678             int ret = JOptionPane.showOptionDialog(
    679                     null,
    680                     tr("<html>JOSM will have to remove your local primitive with id {0}<br>"
    681                             + "from the dataset.<br>"
    682                             + "Do you agree?</html>",
    683                             model.getMyPrimitive().getId()
    684                     ),
    685                     tr("Remove from dataset"),
    686                     JOptionPane.YES_NO_OPTION,
    687                     JOptionPane.QUESTION_MESSAGE,
    688                     null,
    689                     options,
    690                     options[1]
    691             );
    692             return ret == JOptionPane.YES_OPTION;
    693         }
    694     }
    695 
    696     class UndecideVisibleStateConflictAction extends AbstractAction implements Observer {
    697         public UndecideVisibleStateConflictAction() {
    698             putValue(Action.SMALL_ICON, ImageProvider.get("dialogs/conflict", "tagundecide"));
    699             putValue(Action.SHORT_DESCRIPTION, tr("Undecide conflict between visible state"));
    700         }
    701 
    702         public void actionPerformed(ActionEvent e) {
    703             model.decideVisibleStateConflict(MergeDecisionType.UNDECIDED);
    704         }
    705 
    706         public void update(Observable o, Object arg) {
    707             setEnabled(model.hasVisibleStateConflict() && model.isDecidedVisibleState());
    708484        }
    709485    }
  • trunk/src/org/openstreetmap/josm/gui/dialogs/ConflictResolutionDialog.java

    r3083 r3362  
    2828import org.openstreetmap.josm.gui.DefaultNameFormatter;
    2929import org.openstreetmap.josm.gui.conflict.pair.ConflictResolver;
    30 import org.openstreetmap.josm.gui.conflict.pair.properties.OperationCancelledException;
    3130import org.openstreetmap.josm.gui.help.HelpBrowser;
    3231import org.openstreetmap.josm.gui.help.HelpUtil;
     
    262261                }
    263262            }
    264             try {
    265                 Command cmd = resolver.buildResolveCommand();
    266                 Main.main.undoRedo.add(cmd);
    267                 closeDialog();
    268             } catch(OperationCancelledException e) {
    269                 // do nothing. Exception already reported
    270             }
     263            Command cmd = resolver.buildResolveCommand();
     264            Main.main.undoRedo.add(cmd);
     265            closeDialog();
    271266        }
    272267
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/DownloadRelationMemberTask.java

    r3102 r3362  
    121121            if (dataSet == null)
    122122                return;
     123            dataSet.deleteInvisible();
    123124            synchronized (this) {
    124125                if (cancelled) return;
  • trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java

    r3245 r3362  
    3939import org.openstreetmap.josm.Main;
    4040import org.openstreetmap.josm.actions.RenameLayerAction;
    41 import org.openstreetmap.josm.command.PurgePrimitivesCommand;
    4241import org.openstreetmap.josm.data.Bounds;
    4342import org.openstreetmap.josm.data.SelectionChangedListener;
     
    326325            }
    327326        }
    328         PurgePrimitivesCommand cmd = buildPurgeCommand();
    329         if (cmd != null) {
    330             Main.main.undoRedo.add(cmd);
    331         }
    332327        // repaint to make sure new data is displayed properly.
    333328        Main.map.mapView.repaint();
    334         warnNumNewConflicts(
    335                 numNewConflicts,
    336                 cmd == null ? 0 : cmd.getPurgedPrimitives().size()
    337         );
     329        warnNumNewConflicts(numNewConflicts);
    338330    }
    339331
     
    342334     *
    343335     * @param numNewConflicts the number of detected conflicts
    344      * @param numPurgedPrimitives the number of automatically purged objects
    345      */
    346     protected void warnNumNewConflicts(int numNewConflicts, int numPurgedPrimitives) {
    347         if (numNewConflicts == 0 && numPurgedPrimitives == 0) return;
     336     */
     337    protected void warnNumNewConflicts(int numNewConflicts) {
     338        if (numNewConflicts == 0) return;
    348339
    349340        String msg1 = trn(
     
    353344                numNewConflicts
    354345        );
    355         String msg2 = trn(
    356                 "{0} conflict has been <strong>resolved automatically</strong> by purging {0} object<br>from the local dataset because it is deleted on the server.",
    357                 "{0} conflicts have been <strong>resolved automatically</strong> by purging {0} objects<br> from the local dataset because they are deleted on the server.",
    358                 numPurgedPrimitives,
    359                 numPurgedPrimitives
    360         );
    361         int numRemainingConflicts = numNewConflicts - numPurgedPrimitives;
    362         String msg3 = "";
    363         if (numRemainingConflicts >0) {
    364             msg3 = trn(
    365                     "{0} conflict remains to be resolved.<br><br>Please open the Conflict List Dialog and manually resolve it.",
    366                     "{0} conflicts remain to be resolved.<br><br>Please open the Conflict List Dialog and manually resolve them.",
    367                     numRemainingConflicts,
    368                     numRemainingConflicts
    369             );
    370         }
    371346
    372347        StringBuffer sb = new StringBuffer();
    373         sb.append("<html>").append(msg1);
    374         if (numPurgedPrimitives > 0) {
    375             sb.append("<br>").append(msg2);
    376         }
    377         if (numRemainingConflicts > 0) {
    378             sb.append("<br>").append(msg3);
    379         }
    380         sb.append("</html>");
     348        sb.append("<html>").append(msg1).append("</html>");
    381349        if (numNewConflicts > 0) {
    382350            ButtonSpec[] options = new ButtonSpec[] {
     
    403371    }
    404372
    405     /**
    406      * Builds the purge command for primitives which can be purged automatically
    407      * from the local dataset because they've been deleted on the
    408      * server.
    409      *
    410      * @return the purge command. <code>null</code> if no primitives have to
    411      * be purged
    412      */
    413     protected PurgePrimitivesCommand buildPurgeCommand() {
    414         ArrayList<OsmPrimitive> toPurge = new ArrayList<OsmPrimitive>();
    415         conflictLoop:
    416             for (Conflict<?> c: conflicts) {
    417                 if (c.getMy().isDeleted() && !c.getTheir().isVisible()) {
    418                     // Local and server version of the primitive are deleted. We
    419                     // can purge it from the local dataset.
    420                     //
    421                     toPurge.add(c.getMy());
    422                 } else if (!c.getMy().isModified() && ! c.getTheir().isVisible()) {
    423                     // We purge deleted *ways* and *relations* automatically if they are
    424                     // deleted on the server and if they aren't modified in the local
    425                     // dataset.
    426                     //
    427                     if (c.getMy() instanceof Way || c.getMy() instanceof Relation) {
    428                         toPurge.add(c.getMy());
    429                         continue conflictLoop;
    430                     }
    431                     // We only purge nodes if they aren't part of a modified way.
    432                     // Otherwise the number of nodes of a modified way could drop
    433                     // below 2 and we would lose the modified data when the way
    434                     // gets purged.
    435                     //
    436                     for (OsmPrimitive parent: c.getMy().getReferrers()) {
    437                         if (parent.isModified() && parent instanceof Way) {
    438                             continue conflictLoop;
    439                         }
    440                     }
    441                     toPurge.add(c.getMy());
    442                 }
    443             }
    444         if (toPurge.isEmpty()) return null;
    445         PurgePrimitivesCommand cmd = new PurgePrimitivesCommand(this, toPurge);
    446         return cmd;
    447     }
    448373
    449374    @Override public boolean isMergable(final Layer other) {
  • trunk/src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java

    r3083 r3362  
    456456            if (isCanceled())return null;
    457457            fetchPrimitives(relations,OsmPrimitiveType.RELATION, progressMonitor);
     458            if (outputDataSet != null) {
     459                outputDataSet.deleteInvisible();
     460            }
    458461            return outputDataSet;
    459462        } finally {
  • trunk/src/org/openstreetmap/josm/io/OsmServerBackreferenceReader.java

    r3083 r3362  
    274274            ret = visitor.getTargetDataSet();
    275275            readIncompletePrimitives(ret, progressMonitor.createSubTaskMonitor(1, false));
     276            if (ret != null) {
     277                ret.deleteInvisible();
     278            }
    276279            return ret;
    277280        } finally {
Note: See TracChangeset for help on using the changeset viewer.