Ignore:
Timestamp:
2009-06-07T23:22:54+02:00 (15 years ago)
Author:
Gubaer
Message:

added merge support for coordinate conflicts
added merge support for conflicts due to different deleted states

Location:
trunk/src/org/openstreetmap/josm/gui/conflict
Files:
3 added
8 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/conflict/ConflictResolver.java

    r1650 r1654  
    1616import org.openstreetmap.josm.command.Command;
    1717import org.openstreetmap.josm.command.SequenceCommand;
    18 import org.openstreetmap.josm.command.TagConflictResolveCommand;
    1918import org.openstreetmap.josm.command.VersionConflictResolveCommand;
    2019import org.openstreetmap.josm.data.osm.Node;
     
    2423import org.openstreetmap.josm.gui.conflict.nodes.NodeListMergeModel;
    2524import org.openstreetmap.josm.gui.conflict.nodes.NodeListMerger;
     25import org.openstreetmap.josm.gui.conflict.properties.PropertiesMergeModel;
     26import org.openstreetmap.josm.gui.conflict.properties.PropertiesMerger;
    2627import org.openstreetmap.josm.gui.conflict.relation.RelationMemberListMergeModel;
    2728import org.openstreetmap.josm.gui.conflict.relation.RelationMemberMerger;
     
    4243    private NodeListMerger nodeListMerger;
    4344    private RelationMemberMerger relationMemberMerger;
     45    private PropertiesMerger propertiesMerger;
    4446    private OsmPrimitive my;
    4547    private OsmPrimitive their;
     
    5658        tabbedPane = new JTabbedPane();
    5759
     60        propertiesMerger = new PropertiesMerger();
     61        propertiesMerger.setName("panel.propertiesmerger");
     62        propertiesMerger.getModel().addPropertyChangeListener(this);
     63        tabbedPane.add(tr("Properties"), propertiesMerger);
     64
    5865        tagMerger = new TagMerger();
    5966        tagMerger.setName("panel.tagmerger");
    6067        tagMerger.getModel().addPropertyChangeListener(this);
    61         tabbedPane.add("Tags", tagMerger);
     68        tabbedPane.add(tr("Tags"), tagMerger);
    6269
    6370        nodeListMerger = new NodeListMerger();
    6471        nodeListMerger.setName("panel.nodelistmerger");
    6572        nodeListMerger.getModel().addPropertyChangeListener(this);
    66         tabbedPane.add("Nodes", nodeListMerger);
     73        tabbedPane.add(tr("Nodes"), nodeListMerger);
    6774
    6875        relationMemberMerger = new RelationMemberMerger();
    6976        relationMemberMerger.setName("panel.relationmembermerger");
    7077        relationMemberMerger.getModel().addPropertyChangeListener(this);
    71         tabbedPane.add("Members", relationMemberMerger);
     78        tabbedPane.add(tr("Members"), relationMemberMerger);
    7279
    7380        setLayout(new BorderLayout());
     
    8188
    8289    public void propertyChange(PropertyChangeEvent evt) {
    83 
    8490        if (evt.getPropertyName().equals(TagMergeModel.PROP_NUM_UNDECIDED_TAGS)) {
    8591            int newValue = (Integer)evt.getNewValue();
    8692            if (newValue == 0) {
    87                 tabbedPane.setTitleAt(0, tr("Tags"));
    88                 tabbedPane.setToolTipTextAt(0, tr("No pending tag conflicts to be resolved"));
    89                 tabbedPane.setIconAt(0, mergeComplete);
    90             } else {
    91                 tabbedPane.setTitleAt(0, tr("Tags({0} conflicts)", newValue));
    92                 tabbedPane.setToolTipTextAt(0, tr("{0} pending tag conflicts to be resolved"));
    93                 tabbedPane.setIconAt(0, mergeIncomplete);
     93                tabbedPane.setTitleAt(1, tr("Tags"));
     94                tabbedPane.setToolTipTextAt(1, tr("No pending tag conflicts to be resolved"));
     95                tabbedPane.setIconAt(1, mergeComplete);
     96            } else {
     97                tabbedPane.setTitleAt(1, tr("Tags({0} conflicts)", newValue));
     98                tabbedPane.setToolTipTextAt(1, tr("{0} pending tag conflicts to be resolved"));
     99                tabbedPane.setIconAt(1, mergeIncomplete);
    94100            }
    95101        } else if (evt.getPropertyName().equals(ListMergeModel.FROZEN_PROP)) {
    96102            boolean frozen = (Boolean)evt.getNewValue();
    97103            if (frozen && evt.getSource() == nodeListMerger.getModel()) {
    98                 tabbedPane.setTitleAt(1, tr("Nodes(resolved)"));
    99                 tabbedPane.setToolTipTextAt(1, tr("Merged node list frozen. No pending conflicts in the node list of this way"));
    100                 tabbedPane.setIconAt(1, mergeComplete);
    101             } else {
    102                 tabbedPane.setTitleAt(1, tr("Nodes(with conflicts)"));
    103                 tabbedPane.setToolTipTextAt(1,tr("Pending conflicts in the node list of this way"));
    104                 tabbedPane.setIconAt(1, mergeIncomplete);
     104                tabbedPane.setTitleAt(2, tr("Nodes(resolved)"));
     105                tabbedPane.setToolTipTextAt(2, tr("Merged node list frozen. No pending conflicts in the node list of this way"));
     106                tabbedPane.setIconAt(2, mergeComplete);
     107            } else {
     108                tabbedPane.setTitleAt(2, tr("Nodes(with conflicts)"));
     109                tabbedPane.setToolTipTextAt(2,tr("Pending conflicts in the node list of this way"));
     110                tabbedPane.setIconAt(2, mergeIncomplete);
    105111            }
    106112            if (frozen && evt.getSource() == relationMemberMerger.getModel()) {
    107                 tabbedPane.setTitleAt(2, tr("Members(resolved)"));
    108                 tabbedPane.setToolTipTextAt(2, tr("Merged member list frozen. No pending conflicts in the member list of this relation"));
    109                 tabbedPane.setIconAt(2, mergeComplete);
    110             } else {
    111                 tabbedPane.setTitleAt(2, tr("Members(with conflicts)"));
    112                 tabbedPane.setToolTipTextAt(2, tr("Pending conflicts in the member list of this relation"));
    113                 tabbedPane.setIconAt(2, mergeIncomplete);
    114             }
    115         }
    116     }
     113                tabbedPane.setTitleAt(3, tr("Members(resolved)"));
     114                tabbedPane.setToolTipTextAt(3, tr("Merged member list frozen. No pending conflicts in the member list of this relation"));
     115                tabbedPane.setIconAt(3, mergeComplete);
     116            } else {
     117                tabbedPane.setTitleAt(3, tr("Members(with conflicts)"));
     118                tabbedPane.setToolTipTextAt(3, tr("Pending conflicts in the member list of this relation"));
     119                tabbedPane.setIconAt(3, mergeIncomplete);
     120            }
     121        } else if (evt.getPropertyName().equals(PropertiesMergeModel.RESOLVED_COMPLETELY_PROP)) {
     122            boolean resolved = (Boolean)evt.getNewValue();
     123            if (resolved) {
     124                tabbedPane.setTitleAt(0, tr("Properties"));
     125                tabbedPane.setToolTipTextAt(0, tr("No pending property conflicts"));
     126                tabbedPane.setIconAt(0, mergeComplete);
     127            } else {
     128                tabbedPane.setTitleAt(0, tr("Properties(with conflicts)"));
     129                tabbedPane.setToolTipTextAt(0, tr("Pending property conflicts to be resolved"));
     130                tabbedPane.setIconAt(0, mergeIncomplete);
     131            }
     132        }
     133    }
     134
    117135
    118136    /**
     
    126144        this.my = my;
    127145        this.their =  their;
     146        propertiesMerger.getModel().populate(my, their);
     147        tabbedPane.setEnabledAt(0, true);
    128148        tagMerger.getModel().populate(my, their);
    129         tabbedPane.setEnabledAt(0,true);
     149        tabbedPane.setEnabledAt(1, true);
     150
    130151        if (my instanceof Node) {
    131             tabbedPane.setEnabledAt(1,false);
    132152            tabbedPane.setEnabledAt(2,false);
     153            tabbedPane.setEnabledAt(3,false);
    133154        } else if (my instanceof Way) {
    134155            nodeListMerger.populate((Way)my, (Way)their);
    135             tabbedPane.setEnabledAt(1, true);
    136             tabbedPane.setEnabledAt(2, false);
     156            tabbedPane.setEnabledAt(2, true);
     157            tabbedPane.setEnabledAt(3, false);
     158            tabbedPane.setTitleAt(3,tr("Members"));
     159            tabbedPane.setIconAt(3, null);
    137160        } else if (my instanceof Relation) {
    138161            relationMemberMerger.populate((Relation)my, (Relation)their);
    139             tabbedPane.setEnabledAt(1, false);
    140             tabbedPane.setEnabledAt(2, true);
     162            tabbedPane.setEnabledAt(2, false);
     163            tabbedPane.setTitleAt(2,tr("Nodes"));
     164            tabbedPane.setIconAt(2, null);
     165            tabbedPane.setEnabledAt(3, true);
    141166        }
    142167    }
     
    150175    public Command buildResolveCommand() {
    151176        ArrayList<Command> commands = new ArrayList<Command>();
    152         TagConflictResolveCommand cmd = tagMerger.getModel().buildResolveCommand(my, their);
    153         commands.add(cmd);
     177        if (tagMerger.getModel().getNumResolvedConflicts() > 0) {
     178            commands.add(tagMerger.getModel().buildResolveCommand(my, their));
     179        }
     180        commands.addAll(propertiesMerger.getModel().buildResolveCommand(my, their));
    154181        if (my instanceof Way && nodeListMerger.getModel().isFrozen()) {
    155182            NodeListMergeModel model  =(NodeListMergeModel)nodeListMerger.getModel();
     
    159186            commands.add(model.buildResolveCommand((Relation)my, (Relation)their));
    160187        }
     188        if (isResolvedCompletely()) {
     189            commands.add(
     190                    new VersionConflictResolveCommand(my, their)
     191            );
     192        }
     193        return new SequenceCommand(tr("Conflict Resolution"), commands);
     194    }
     195
     196    public boolean isResolvedCompletely() {
    161197        if (my instanceof Node) {
    162198            // resolve the version conflict if this is a node and all tag
    163199            // conflicts have been resolved
    164200            //
    165             if (tagMerger.getModel().isResolvedCompletely()) {
    166                 commands.add(
    167                         new VersionConflictResolveCommand(my, their)
    168                 );
    169             }
    170         } else if (my instanceof Way) {
    171             // resolve the version conflict if this is a way, all tag
    172             // conflicts have been resolved, and conflicts in the node list
    173             // have been resolved
    174             //
    175             if (tagMerger.getModel().isResolvedCompletely() && nodeListMerger.getModel().isFrozen()) {
    176                 commands.add(
    177                         new VersionConflictResolveCommand(my, their)
    178                 );
    179             }
    180         }  else if (my instanceof Relation) {
    181             // resolve the version conflict if this is a relation, all tag
    182             // conflicts and all conflicts in the member list
    183             // have been resolved
    184             //
    185             if (tagMerger.getModel().isResolvedCompletely() && relationMemberMerger.getModel().isFrozen()) {
    186                 commands.add(
    187                         new VersionConflictResolveCommand(my, their)
    188                 );
    189             }
    190         }
    191         return new SequenceCommand(tr("Conflict Resolution"), commands);
    192     }
    193 
    194     public boolean isCompletelyResolved() {
    195         if (my instanceof Node) {
    196             // resolve the version conflict if this is a node and all tag
    197             // conflicts have been resolved
    198             //
    199             if (tagMerger.getModel().isResolvedCompletely())
     201            if (tagMerger.getModel().isResolvedCompletely()
     202                    && propertiesMerger.getModel().isResolvedCompletely())
    200203                return true;
    201204        } else if (my instanceof Way) {
     
    204207            // have been resolved
    205208            //
    206             if (tagMerger.getModel().isResolvedCompletely() && nodeListMerger.getModel().isFrozen())
     209            if (tagMerger.getModel().isResolvedCompletely()
     210                    &&  propertiesMerger.getModel().isResolvedCompletely()
     211                    && nodeListMerger.getModel().isFrozen())
    207212                return true;
    208213        }  else if (my instanceof Relation) {
     
    211216            // have been resolved
    212217            //
    213             if (tagMerger.getModel().isResolvedCompletely() && relationMemberMerger.getModel().isFrozen())
     218            if (tagMerger.getModel().isResolvedCompletely()
     219                    &&  propertiesMerger.getModel().isResolvedCompletely()
     220                    && relationMemberMerger.getModel().isFrozen())
    214221                return true;
    215222        }
  • trunk/src/org/openstreetmap/josm/gui/conflict/MergeDecisionType.java

    r1653 r1654  
    11// License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.conflict.tags;
     2package org.openstreetmap.josm.gui.conflict;
    33
    44public enum MergeDecisionType {
  • trunk/src/org/openstreetmap/josm/gui/conflict/nodes/NodeListTableCellRenderer.java

    r1650 r1654  
    8181    }
    8282
    83 
     83    /**
     84     * build the tool tip text for an {@see OsmPrimitive}. It consist of the formatted
     85     * key/value pairs for this primitive.
     86     *
     87     * @param primitive
     88     * @return the tool tip text
     89     */
    8490    public String buildToolTipText(OsmPrimitive primitive) {
    8591        StringBuilder sb = new StringBuilder();
     92
    8693        sb.append("<html>");
     94        // show the id
     95        //
    8796        sb.append("<strong>id</strong>=")
    8897        .append(primitive.id)
    8998        .append("<br>");
     99
     100        // show the key/value-pairs, sorted by key
     101        //
    90102        ArrayList<String> keyList = new ArrayList<String>(primitive.keySet());
    91103        Collections.sort(keyList);
     
    99111            .append("</strong>")
    100112            .append("=");
     113            // make sure long values are split into several rows. Otherwise
     114            // the tool tip window can become to wide
     115            //
    101116            String value = primitive.get(key);
    102117            while(value.length() != 0) {
     
    121136        setForeground(Color.BLACK);
    122137    }
    123 
    124 
    125138
    126139    /**
  • trunk/src/org/openstreetmap/josm/gui/conflict/tags/MergedTableCellRenderer.java

    r1642 r1654  
    55
    66import java.awt.Color;
     7
     8import org.openstreetmap.josm.gui.conflict.MergeDecisionType;
    79
    810public class MergedTableCellRenderer extends TagMergeTableCellRenderer {
  • trunk/src/org/openstreetmap/josm/gui/conflict/tags/MineTableCellRenderer.java

    r1622 r1654  
    33
    44import java.awt.Color;
     5
     6import org.openstreetmap.josm.gui.conflict.MergeDecisionType;
     7
    58import static org.openstreetmap.josm.tools.I18n.tr;
    69
  • trunk/src/org/openstreetmap/josm/gui/conflict/tags/TagMergeItem.java

    r1622 r1654  
    77
    88import org.openstreetmap.josm.data.osm.OsmPrimitive;
     9import org.openstreetmap.josm.gui.conflict.MergeDecisionType;
    910
    1011/**
  • trunk/src/org/openstreetmap/josm/gui/conflict/tags/TagMergeModel.java

    r1622 r1654  
    1313import org.openstreetmap.josm.command.TagConflictResolveCommand;
    1414import org.openstreetmap.josm.data.osm.OsmPrimitive;
     15import org.openstreetmap.josm.gui.conflict.MergeDecisionType;
    1516
    1617/**
     
    2122 *
    2223 *  {@see #decide(int, MergeDecisionType)} and {@see #decide(int[], MergeDecisionType)} can be used
    23  *  to remember a merge decision for a specific row in the model. 
    24  *  
     24 *  to remember a merge decision for a specific row in the model.
     25 *
    2526 *  The model notifies {@see PropertyChangeListener}s about updates of the number of
    2627 *  undecided tags (see {@see #PROP_NUM_UNDECIDED_TAGS}).
     
    3132
    3233    static public final String PROP_NUM_UNDECIDED_TAGS = TagMergeModel.class.getName() + ".numUndecidedTags";
    33    
     34
    3435    /** the list of tag merge items */
    35     private ArrayList<TagMergeItem> tagMergeItems;
    36    
     36    private final ArrayList<TagMergeItem> tagMergeItems;
     37
    3738    /** the property change listeners */
    38     private ArrayList<PropertyChangeListener> listeners;
    39    
     39    private final ArrayList<PropertyChangeListener> listeners;
     40
    4041    private int numUndecidedTags = 0;
    41    
    42    
     42
     43
    4344    public TagMergeModel() {
    4445        tagMergeItems = new ArrayList<TagMergeItem>();
    4546        listeners = new ArrayList<PropertyChangeListener>();
    4647    }
    47    
     48
    4849    public void addPropertyChangeListener(PropertyChangeListener listener) {
    4950        synchronized(listeners) {
     
    5354        }
    5455    }
    55    
     56
    5657    public void removePropertyChangeListener(PropertyChangeListener listener) {
    5758        synchronized(listeners) {
     
    6162        }
    6263    }
    63    
     64
    6465    /**
    6566     * notifies {@see PropertyChangeListener}s about an update of {@see TagMergeModel#PROP_NUM_UNDECIDED_TAGS}
    6667
    67      * @param oldValue the old value 
    68      * @param newValue the new value 
     68     * @param oldValue the old value
     69     * @param newValue the new value
    6970     */
    7071    protected void fireNumUndecidedTagsChanged(int oldValue, int newValue) {
     
    7677        }
    7778    }
    78    
     79
    7980    /**
    8081     * refreshes the number of undecided tag conflicts after an update in the list of
     
    8990            }
    9091        }
    91         if (newValue != numUndecidedTags) {
    92             int oldValue = numUndecidedTags;
    93             numUndecidedTags = newValue;
    94             fireNumUndecidedTagsChanged(oldValue, numUndecidedTags);
    95         }
    96     }
    97    
    98     /**
    99      * Populate the model with conflicts between the tag sets of the two
     92        int oldValue = numUndecidedTags;
     93        numUndecidedTags = newValue;
     94        fireNumUndecidedTagsChanged(oldValue, numUndecidedTags);
     95
     96    }
     97
     98    /**
     99     * Populate the model with conflicts between the tag sets of the two
    100100     * {@see OsmPrimitive} <code>my</code> and <code>their</code>.
    101101     *
    102102     * @param my  my primitive (i.e. the primitive from the local dataset)
    103      * @param their their primitive (i.e. the primitive from the server dataset) 
     103     * @param their their primitive (i.e. the primitive from the server dataset)
    104104     *
    105105     */
     
    114114            if (myValue == null || theirValue == null || ! myValue.equals(theirValue)) {
    115115                tagMergeItems.add(
    116                   new TagMergeItem(key, my, their)     
     116                        new TagMergeItem(key, my, their)
    117117                );
    118118            }
     
    121121        refreshNumUndecidedTags();
    122122    }
    123    
     123
    124124    /**
    125125     * add a {@see TagMergeItem} to the model
    126126     *
    127      * @param item the item 
     127     * @param item the item
    128128     */
    129129    public void addItem(TagMergeItem item) {
     
    134134        }
    135135    }
    136    
     136
    137137    protected void rememberDecision(int row, MergeDecisionType decision) {
    138138        TagMergeItem item = tagMergeItems.get(row);
     
    144144     * to <code>decision</code>.
    145145     *
    146      * @param row  the row 
    147      * @param decision the decision 
     146     * @param row  the row
     147     * @param decision the decision
    148148     */
    149149    public void decide(int row, MergeDecisionType decision) {
     
    157157     * to <code>decision</code>.
    158158     *
    159      * @param row  the array of row indices 
    160      * @param decision the decision 
     159     * @param row  the array of row indices
     160     * @param decision the decision
    161161     */
    162162
    163163    public void decide(int [] rows, MergeDecisionType decision) {
    164         if (rows == null || rows.length == 0) {
     164        if (rows == null || rows.length == 0)
    165165            return;
    166         }
    167166        for (int row : rows) {
    168167            rememberDecision(row, decision);
     
    182181        // return the tagMergeItem for both columns. The cell
    183182        // renderer will dispatch on the column index and get
    184         // the key or the value from the TagMergeItem 
     183        // the key or the value from the TagMergeItem
    185184        //
    186185        return tagMergeItems.get(row);
     
    191190        return false;
    192191    }
    193    
    194    
     192
    195193    public TagConflictResolveCommand buildResolveCommand(OsmPrimitive my, OsmPrimitive their) {
    196194        return new TagConflictResolveCommand(my,  their, tagMergeItems);
    197195    }
    198    
     196
    199197    public boolean isResolvedCompletely() {
    200198        for (TagMergeItem item: tagMergeItems) {
    201             if (item.getMergeDecision().equals(MergeDecisionType.UNDECIDED)) {
    202                 return false;
    203             }
    204         }
    205         return true;
     199            if (item.getMergeDecision().equals(MergeDecisionType.UNDECIDED))
     200                return false;
     201        }
     202        return true;
     203    }
     204
     205    public int getNumResolvedConflicts() {
     206        int n = 0;
     207        for (TagMergeItem item: tagMergeItems) {
     208            if (!item.getMergeDecision().equals(MergeDecisionType.UNDECIDED)) {
     209                n++;
     210            }
     211        }
     212        return n;
     213
    206214    }
    207215}
  • trunk/src/org/openstreetmap/josm/gui/conflict/tags/TagMerger.java

    r1642 r1654  
    2626import javax.swing.event.ListSelectionListener;
    2727
     28import org.openstreetmap.josm.gui.conflict.MergeDecisionType;
    2829import org.openstreetmap.josm.tools.ImageProvider;
    2930/**
  • trunk/src/org/openstreetmap/josm/gui/conflict/tags/TheirTableCellRenderer.java

    r1622 r1654  
    55
    66import java.awt.Color;
     7
     8import org.openstreetmap.josm.gui.conflict.MergeDecisionType;
    79
    810public class TheirTableCellRenderer extends TagMergeTableCellRenderer {
Note: See TracChangeset for help on using the changeset viewer.