Ignore:
Timestamp:
2009-06-01T22:20:03+02:00 (15 years ago)
Author:
Gubaer
Message:

added support for merging member lists of relations in extended conflict resolution dialog

Location:
trunk/src/org/openstreetmap/josm/gui/conflict
Files:
8 added
6 edited

Legend:

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

    r1626 r1631  
    77import java.beans.PropertyChangeEvent;
    88import java.beans.PropertyChangeListener;
    9 import java.net.URL;
    109import java.util.ArrayList;
    1110import java.util.logging.Logger;
     
    2524import org.openstreetmap.josm.gui.conflict.nodes.NodeListMergeModel;
    2625import org.openstreetmap.josm.gui.conflict.nodes.NodeListMerger;
     26import org.openstreetmap.josm.gui.conflict.relation.RelationMemberListMergeModel;
     27import org.openstreetmap.josm.gui.conflict.relation.RelationMemberMerger;
    2728import org.openstreetmap.josm.gui.conflict.tags.TagMergeModel;
    2829import org.openstreetmap.josm.gui.conflict.tags.TagMerger;
     30import org.openstreetmap.josm.tools.ImageProvider;
    2931
    3032/**
    3133 * An UI component for resolving conflicts between two {@see OsmPrimitive}s.
    32  *   
    33  *
     34 *
    3435 */
    3536public class ConflictResolver extends JPanel implements PropertyChangeListener  {
    36    
    37    private static final Logger logger = Logger.getLogger(ConflictResolver.class.getName());
     37
     38    private static final Logger logger = Logger.getLogger(ConflictResolver.class.getName());
    3839
    3940    private JTabbedPane tabbedPane = null;
    4041    private TagMerger tagMerger;
    4142    private NodeListMerger nodeListMerger;
     43    private RelationMemberMerger relationMemberMerger;
    4244    private OsmPrimitive my;
    4345    private OsmPrimitive their;
    44    
     46
    4547    private ImageIcon mergeComplete;
    4648    private ImageIcon mergeIncomplete;
    47    
    48     // FIXME copied code -> refactor
    49     /**
    50      * load an icon given by iconName
    51      *
    52      * @param iconName  the name of the icon (without path, i.e. <tt>copystartleft.png</tt>
    53      * @return the icon; null, if the icon was not found
    54      */
    55     protected ImageIcon getIcon(String iconName) {
    56         String fullIconName  = "/images/dialogs/conflict/" + iconName;
    57         URL imageURL   = this.getClass().getResource(fullIconName);           
    58         if (imageURL == null) {
    59             System.out.println(tr("WARNING: failed to load resource {0}", fullIconName));
    60             return null;
    61         }
    62         return new ImageIcon(imageURL);
     49
     50    protected void loadIcons() {
     51        mergeComplete = ImageProvider.get("dialogs/conflict","mergecomplete.png" );
     52        mergeIncomplete = ImageProvider.get("dialogs/conflict","mergeincomplete.png" );
    6353    }
    64    
    65     protected void loadIcons() {
    66         mergeComplete = getIcon("mergecomplete.png");
    67         mergeIncomplete = getIcon("mergeincomplete.png");
    68     }
    69    
     54
    7055    protected void build() {
    7156        tabbedPane = new JTabbedPane();
    72        
     57
    7358        tagMerger = new TagMerger();
     59        tagMerger.setName("panel.tagmerger");
    7460        tagMerger.getModel().addPropertyChangeListener(this);
    7561        tabbedPane.add("Tags", tagMerger);
    76        
     62
    7763        nodeListMerger = new NodeListMerger();
     64        nodeListMerger.setName("panel.nodelistmerger");
    7865        nodeListMerger.getModel().addPropertyChangeListener(this);
    7966        tabbedPane.add("Nodes", nodeListMerger);
    80        
    81         tabbedPane.add("Members", new JPanel());
    82        
     67
     68        relationMemberMerger = new RelationMemberMerger();
     69        relationMemberMerger.setName("panel.relationmembermerger");
     70        relationMemberMerger.getModel().addPropertyChangeListener(this);
     71        tabbedPane.add("Members", relationMemberMerger);
     72
    8373        setLayout(new BorderLayout());
    8474        add(tabbedPane, BorderLayout.CENTER);
    8575    }
    86    
    87    
     76
    8877    public ConflictResolver() {
    8978        build();
     
    9281
    9382    public void propertyChange(PropertyChangeEvent evt) {
    94        
     83
    9584        if (evt.getPropertyName().equals(TagMergeModel.PROP_NUM_UNDECIDED_TAGS)) {
    9685            int newValue = (Integer)evt.getNewValue();
     
    10493                tabbedPane.setIconAt(0, mergeIncomplete);
    10594            }
    106         } else if (evt.getPropertyName().equals(NodeListMergeModel.PROP_FROZEN)) {
     95        } else if (evt.getPropertyName().equals(ListMergeModel.PROP_FROZEN)) {
    10796            boolean frozen = (Boolean)evt.getNewValue();
    108             if (frozen) {
     97            if (frozen && evt.getSource() == nodeListMerger.getModel()) {
    10998                tabbedPane.setTitleAt(1, tr("Nodes(resolved)"));
    110                 tabbedPane.setToolTipTextAt(1, tr("Pending conflicts in the node list of this way"));
     99                tabbedPane.setToolTipTextAt(1, tr("Merged node list frozen. No pending conflicts in the node list of this way"));
    111100                tabbedPane.setIconAt(1, mergeComplete);
    112101            } else {
    113102                tabbedPane.setTitleAt(1, tr("Nodes(with conflicts)"));
    114                 tabbedPane.setToolTipTextAt(1, tr("Merged node list frozen. No pending conflicts in the node list of this way"));
     103                tabbedPane.setToolTipTextAt(1,tr("Pending conflicts in the node list of this way"));
    115104                tabbedPane.setIconAt(1, mergeIncomplete);
     105            }
     106            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);
    116114            }
    117115        }
    118116    }
    119    
    120     public void populate(OsmPrimitive my, OsmPrimitive their) {
     117
     118    /**
     119     * populates the conflict resolver with the conflicts between my and their
     120     *
     121     * @param my   my primitive (i.e. the primitive in the local dataset)
     122     * @param their their primitive (i.e. the primitive in the server dataset)
     123     *
     124     */
     125    public void populate(OsmPrimitive my, OsmPrimitive their) {
    121126        this.my = my;
    122         this.their =  their; 
     127        this.their =  their;
    123128        tagMerger.getModel().populate(my, their);
    124         if (my instanceof Way) {
    125            nodeListMerger.populate((Way)my, (Way)their);
    126            tabbedPane.setEnabledAt(1, true);
    127            tabbedPane.setEnabledAt(2, false);
     129        tabbedPane.setEnabledAt(0,true);
     130        if (my instanceof Node) {
     131            tabbedPane.setEnabledAt(1,false);
     132            tabbedPane.setEnabledAt(2,false);
     133        } else if (my instanceof Way) {
     134            nodeListMerger.populate((Way)my, (Way)their);
     135            tabbedPane.setEnabledAt(1, true);
     136            tabbedPane.setEnabledAt(2, false);
    128137        } else if (my instanceof Relation) {
     138            relationMemberMerger.populate((Relation)my, (Relation)their);
    129139            tabbedPane.setEnabledAt(1, false);
    130             tabbedPane.setEnabledAt(2, true);       
    131          }
     140            tabbedPane.setEnabledAt(2, true);
     141        }
    132142    }
    133    
     143
     144    /**
     145     * Builds the resolution command(s) for for the resolved conflicts in this
     146     * ConflictResolver
     147     *
     148     * @return the resolution command
     149     */
    134150    public Command buildResolveCommand() {
    135151        ArrayList<Command> commands = new ArrayList<Command>();
     
    137153        commands.add(cmd);
    138154        if (my instanceof Way && nodeListMerger.getModel().isFrozen()) {
    139             commands.add(nodeListMerger.getModel().buildResolveCommand((Way)my, (Way)their));           
     155            NodeListMergeModel model  =(NodeListMergeModel)nodeListMerger.getModel();
     156            commands.add(model.buildResolveCommand((Way)my, (Way)their));
     157        } else if (my instanceof Relation && relationMemberMerger.getModel().isFrozen()) {
     158            RelationMemberListMergeModel model  =(RelationMemberListMergeModel)relationMemberMerger.getModel();
     159            commands.add(model.buildResolveCommand((Relation)my, (Relation)their));
    140160        }
    141161        if (my instanceof Node) {
    142             // resolve the version conflict if this is a node and all tag 
    143             // conflicts have been resolved 
    144             // 
     162            // resolve the version conflict if this is a node and all tag
     163            // conflicts have been resolved
     164            //
    145165            if (tagMerger.getModel().isResolvedCompletely()) {
    146166                commands.add(
    147                    new VersionConflictResolveCommand(my, their)
     167                        new VersionConflictResolveCommand(my, their)
    148168                );
    149169            }
    150170        } else if (my instanceof Way) {
    151             // resolve the version conflict if this is a way, all tag 
     171            // resolve the version conflict if this is a way, all tag
    152172            // conflicts have been resolved, and conflicts in the node list
    153             // have been resolved 
    154             // 
     173            // have been resolved
     174            //
    155175            if (tagMerger.getModel().isResolvedCompletely() && nodeListMerger.getModel().isFrozen()) {
    156176                commands.add(
    157                    new VersionConflictResolveCommand(my, their)
     177                        new VersionConflictResolveCommand(my, their)
    158178                );
    159             }           
     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            }
    160190        }
    161         return new SequenceCommand("Conflict Resolution", commands);
     191
     192        return new SequenceCommand(tr("Conflict Resolution"), commands);
    162193    }
    163194}
  • trunk/src/org/openstreetmap/josm/gui/conflict/nodes/NodeListColumnModel.java

    r1622 r1631  
    1111
    1212    protected void createColumns(TableCellRenderer renderer) {
    13        
     13
    1414        TableColumn col = null;
    15        
    16         // column 0 - Node 
     15
     16        // column 0 - Node
    1717        col = new TableColumn(0);
    1818        col.setHeaderValue(tr("Node"));
    1919        col.setResizable(true);
    2020        col.setCellRenderer(renderer);
    21         addColumn(col);       
     21        addColumn(col);
    2222    }
    2323
  • trunk/src/org/openstreetmap/josm/gui/conflict/nodes/NodeListMergeModel.java

    r1622 r1631  
    22package org.openstreetmap.josm.gui.conflict.nodes;
    33
    4 import static org.openstreetmap.josm.tools.I18n.tr;
    5 
    6 import java.beans.PropertyChangeEvent;
    7 import java.beans.PropertyChangeListener;
    84import java.util.ArrayList;
    9 import java.util.List;
    105import java.util.logging.Logger;
    116
    12 import javax.swing.DefaultListSelectionModel;
    13 import javax.swing.ListSelectionModel;
    147import javax.swing.table.DefaultTableModel;
    15 import javax.swing.table.TableModel;
    168
    179import org.openstreetmap.josm.command.WayNodesConflictResolverCommand;
    1810import org.openstreetmap.josm.data.osm.Node;
    1911import org.openstreetmap.josm.data.osm.Way;
     12import org.openstreetmap.josm.gui.conflict.ListMergeModel;
    2013
    21 public class NodeListMergeModel {
     14public class NodeListMergeModel extends ListMergeModel<Node>{
     15
    2216    private static final Logger logger = Logger.getLogger(NodeListMergeModel.class.getName());
    23    
    24     public static final String PROP_FROZEN = NodeListMergeModel.class.getName() + ".frozen";
    25    
    2617
    27     private ArrayList<Node> myNodes;
    28     private ArrayList<Node> theirNodes;
    29     private ArrayList<Node> mergedNodes;
    30    
    31    
    32     private DefaultTableModel myNodesTableModel;
    33     private DefaultTableModel theirNodesTableModel;
    34     private DefaultTableModel mergedNodesTableModel;
    35    
    36     private DefaultListSelectionModel myNodesSelectionModel;
    37     private DefaultListSelectionModel theirNodesSelectionModel;
    38     private DefaultListSelectionModel mergedNodesSelectionModel;
    39    
    40     private ArrayList<PropertyChangeListener> listeners;
    41     private boolean isFrozen = false;
    42    
    43    
    44     public NodeListMergeModel() {
    45         myNodes = new ArrayList<Node>();
    46         theirNodes = new ArrayList<Node>();
    47         mergedNodes = new ArrayList<Node>();
    48        
    49         myNodesTableModel = new NodeListTableModel(myNodes);
    50         theirNodesTableModel = new NodeListTableModel(theirNodes);
    51         mergedNodesTableModel = new NodeListTableModel(mergedNodes);
    52        
    53         myNodesSelectionModel = new DefaultListSelectionModel();
    54         theirNodesSelectionModel = new DefaultListSelectionModel();
    55         mergedNodesSelectionModel = new DefaultListSelectionModel();
    56        
    57         listeners = new ArrayList<PropertyChangeListener>();
    58        
    59         setFrozen(true);
    60     }
    61    
    62    
    63     public void addPropertyChangeListener(PropertyChangeListener listener) {
    64         synchronized(listeners) {
    65             if (listener != null && ! listeners.contains(listener)) {
    66                 listeners.add(listener);
    67             }
    68         }
    69     }
    70    
    71     public void removePropertyChangeListener(PropertyChangeListener listener) {
    72         synchronized(listeners) {
    73             if (listener != null && listeners.contains(listener)) {
    74                 listeners.remove(listener);
    75             }
    76         }
    77     }
    78    
    79     protected void fireFrozenChanged(boolean oldValue, boolean newValue) {
    80         synchronized(listeners) {
    81             PropertyChangeEvent evt = new PropertyChangeEvent(this, PROP_FROZEN, oldValue, newValue);
    82             for (PropertyChangeListener listener: listeners) {
    83                 listener.propertyChange(evt);
    84             }
    85         }
    86     }
    87    
    88     public void setFrozen(boolean isFrozen) {
    89         boolean oldValue = this.isFrozen;
    90         this.isFrozen = isFrozen;
    91         fireFrozenChanged(oldValue, this.isFrozen);
    92     }
    93    
    94     public boolean isFrozen() {
    95         return isFrozen;
    96     }
    97    
    98     public TableModel getMyNodesTableModel() {
    99         return myNodesTableModel;
    100     }
    101    
    102     public TableModel getTheirNodesTableModel() {
    103         return theirNodesTableModel;
    104     }
    105    
    106     public TableModel getMergedNodesTableModel() {
    107         return mergedNodesTableModel;
    108     }
    109    
    110     public ListSelectionModel getMyNodesSelectionModel() {
    111         return myNodesSelectionModel;
    112     }
    11318
    114     public ListSelectionModel getTheirNodesSelectionModel() {
    115         return theirNodesSelectionModel;
    116     }
    117    
    118     public ListSelectionModel getMergedNodesSelectionModel() {
    119         return mergedNodesSelectionModel;
    120     }
    121    
    122    
    123     protected void fireModelDataChanged() {
    124         myNodesTableModel.fireTableDataChanged();
    125         theirNodesTableModel.fireTableDataChanged();
    126         mergedNodesTableModel.fireTableDataChanged();
    127     }
    128    
    129     protected void copyNodesToTop(List<Node> source, int []rows) {
    130         if (rows == null || rows.length == 0) {
    131             return;
    132         }
    133         for (int i = rows.length - 1; i >= 0; i--) {
    134             int row = rows[i];
    135             Node n = source.get(row);
    136             mergedNodes.add(0, n);
    137         }
    138         fireModelDataChanged();
    139         mergedNodesSelectionModel.setSelectionInterval(0, rows.length -1);
    140     }
    141    
    142     /**
    143      * Copies the nodes given by indices in rows from the list of my nodes to the
    144      * list of merged nodes. Inserts the nodes at the top of the list of merged
    145      * nodes. 
    146      *
    147      * @param rows the indices
    148      */
    149     public void copyMyNodesToTop(int [] rows) {
    150         copyNodesToTop(myNodes, rows);       
    151     }
    152    
    153     /**
    154      * Copies the nodes given by indices in rows from the list of their nodes to the
    155      * list of merged nodes. Inserts the nodes at the top of the list of merged
    156      * nodes. 
    157      *
    158      * @param rows the indices
    159      */
    160     public void copyTheirNodesToTop(int [] rows) {
    161         copyNodesToTop(theirNodes, rows);       
    162     }
    163    
    164     /**
    165      * Copies the nodes given by indices in rows from the list of  nodes in source to the
    166      * list of merged nodes. Inserts the nodes at the end of the list of merged
    167      * nodes. 
    168      *
    169      * @param source the list of nodes to copy from
    170      * @param rows the indices
    171      */   
    172 
    173     public void copyNodesToEnd(List<Node> source, int [] rows) {
    174         if (rows == null || rows.length == 0) {
    175             return;
    176         }
    177         for (int row : rows) {
    178             Node n = source.get(row);
    179             mergedNodes.add(n);
    180         }
    181         fireModelDataChanged();
    182         mergedNodesSelectionModel.setSelectionInterval(mergedNodes.size()-rows.length, mergedNodes.size() -1);
    183 
    184     }
    185    
    186     /**
    187      * Copies the nodes given by indices in rows from the list of my nodes to the
    188      * list of merged nodes. Inserts the nodes at the end of the list of merged
    189      * nodes. 
    190      *
    191      * @param rows the indices
    192      */   
    193     public void copyMyNodesToEnd(int [] rows) {
    194         copyNodesToEnd(myNodes, rows);
    195     }
    196    
    197     /**
    198      * Copies the nodes given by indices in rows from the list of their nodes to the
    199      * list of merged nodes. Inserts the nodes at the end of the list of merged
    200      * nodes. 
    201      *
    202      * @param rows the indices
    203      */   
    204     public void copyTheirNodesToEnd(int [] rows) {
    205         copyNodesToEnd(theirNodes, rows);
    206     }
    207    
    208     /**
    209      * Copies the nodes given by indices in rows from the list of  nodes <code>source</code> to the
    210      * list of merged nodes. Inserts the nodes before row given by current.
    211      *
    212      * @param source the list of nodes to copy from
    213      * @param rows the indices
    214      * @param current the row index before which the nodes are inserted
    215      * @exception IllegalArgumentException thrown, if current < 0 or >= #nodes in list of merged nodes
    216      *
    217      */ 
    218     protected void copyNodesBeforeCurrent(List<Node> source, int [] rows, int current) {
    219         if (rows == null || rows.length == 0) {
    220             return;
    221         }
    222         if (current < 0 || current >= mergedNodes.size()) {
    223             throw new IllegalArgumentException(tr("parameter current out of range: got {0}", current));
    224         }
    225         for (int i=rows.length -1; i>=0; i--) {
    226             int row = rows[i];
    227             Node n = source.get(row);
    228             mergedNodes.add(current, n);
    229         }
    230         fireModelDataChanged();
    231         mergedNodesSelectionModel.setSelectionInterval(current, current + rows.length-1);
    232      }
    233    
    234     /**
    235      * Copies the nodes given by indices in rows from the list of my nodes to the
    236      * list of merged nodes. Inserts the nodes before row given by current.
    237      *
    238      * @param rows the indices
    239      * @param current the row index before which the nodes are inserted
    240      * @exception IllegalArgumentException thrown, if current < 0 or >= #nodes in list of merged nodes
    241      *
    242      */       
    243     public void copyMyNodesBeforeCurrent(int [] rows, int current) {
    244         copyNodesBeforeCurrent(myNodes,rows,current);
    245     }
    246    
    247     /**
    248      * Copies the nodes given by indices in rows from the list of their nodes to the
    249      * list of merged nodes. Inserts the nodes before row given by current.
    250      *
    251      * @param rows the indices
    252      * @param current the row index before which the nodes are inserted
    253      * @exception IllegalArgumentException thrown, if current < 0 or >= #nodes in list of merged nodes
    254      *
    255      */       
    256     public void copyTheirNodesBeforeCurrent(int [] rows, int current) {
    257         copyNodesBeforeCurrent(theirNodes,rows,current);
    258     }
    259    
    260     /**
    261      * Copies the nodes given by indices in rows from the list of  nodes <code>source</code> to the
    262      * list of merged nodes. Inserts the nodes after the row given by current.
    263      *
    264      * @param source the list of nodes to copy from
    265      * @param rows the indices
    266      * @param current the row index after which the nodes are inserted
    267      * @exception IllegalArgumentException thrown, if current < 0 or >= #nodes in list of merged nodes
    268      *
    269      */       
    270     protected void copyNodesAfterCurrent(List<Node> source, int [] rows, int current) {
    271         if (rows == null || rows.length == 0) {
    272             return;
    273         }
    274         if (current < 0 || current >= mergedNodes.size()) {
    275             throw new IllegalArgumentException(tr("parameter current out of range: got {0}", current));
    276         }
    277         if (current == mergedNodes.size() -1) {
    278             copyMyNodesToEnd(rows);
    279         } else {
    280             for (int i=rows.length -1; i>=0; i--) {
    281                 int row = rows[i];
    282                 Node n = source.get(row);
    283                 mergedNodes.add(current+1, n);
    284             }
    285         }
    286         fireModelDataChanged();   
    287         mergedNodesSelectionModel.setSelectionInterval(current+1, current + rows.length-1);
    288     }
    289    
    290     /**
    291      * Copies the nodes given by indices in rows from the list of my nodes to the
    292      * list of merged nodes. Inserts the nodes after the row given by current.
    293      *
    294      * @param rows the indices
    295      * @param current the row index after which the nodes are inserted
    296      * @exception IllegalArgumentException thrown, if current < 0 or >= #nodes in list of merged nodes
    297      *
    298      */       
    299     public void copyMyNodesAfterCurrent(int [] rows, int current) {
    300         copyNodesAfterCurrent(myNodes, rows, current);
    301     }
    302    
    303     /**
    304      * Copies the nodes given by indices in rows from the list of my nodes to the
    305      * list of merged nodes. Inserts the nodes after the row given by current.
    306      *
    307      * @param rows the indices
    308      * @param current the row index after which the nodes are inserted
    309      * @exception IllegalArgumentException thrown, if current < 0 or >= #nodes in list of merged nodes
    310      *
    311      */       
    312     public void copyTheirNodesAfterCurrent(int [] rows, int current) {
    313         copyNodesAfterCurrent(theirNodes, rows, current);
    314     }
    315 
    316     /**
    317      * Moves the nodes given by indices in rows  up by one position in the list
    318      * of merged nodes.
    319      *
    320      * @param rows the indices
    321      *
    322      */
    323     protected void moveUpMergedNodes(int [] rows) {
    324         if (rows == null || rows.length == 0) {
    325             return;
    326         }
    327         if (rows[0] == 0) {
    328             // can't move up
    329             return;
    330         }
    331         for (int row: rows) {
    332            Node n = mergedNodes.get(row);
    333            mergedNodes.remove(row);
    334            mergedNodes.add(row -1, n);
    335         }
    336         fireModelDataChanged();
    337         mergedNodesSelectionModel.clearSelection();
    338         for (int row: rows) {
    339             mergedNodesSelectionModel.addSelectionInterval(row-1, row-1);
    340         }
    341     }
    342 
    343     /**
    344      * Moves the nodes given by indices in rows down by one position in the list
    345      * of merged nodes.
    346      *
    347      * @param rows the indices
    348      */
    349     protected void moveDownMergedNodes(int [] rows) {
    350         if (rows == null || rows.length == 0) {
    351             return;
    352         }
    353         if (rows[rows.length -1] == mergedNodes.size() -1) {
    354             // can't move down
    355             return;
    356         }
    357         for (int i = rows.length-1; i>=0;i--) {
    358             int row = rows[i];
    359             Node n = mergedNodes.get(row);
    360             mergedNodes.remove(row);
    361             mergedNodes.add(row +1, n);
    362          }
    363         fireModelDataChanged();
    364         mergedNodesSelectionModel.clearSelection();
    365         for (int row: rows) {
    366             mergedNodesSelectionModel.addSelectionInterval(row+1, row+1);
    367         }       
    368     }
    369    
    370     /**
    371      * Removes the nodes given by indices in rows from the list
    372      * of merged nodes.
    373      *
    374      * @param rows the indices
    375      */   
    376     protected void removeMergedNodes(int [] rows) {
    377         if (rows == null || rows.length == 0) {
    378             return;
    379         }
    380         for (int i = rows.length-1; i>=0;i--) {
    381             mergedNodes.remove(rows[i]);
    382          }
    383         fireModelDataChanged();
    384         mergedNodesSelectionModel.clearSelection();
    385     }
    386    
    387 
    388     /**
    389      * Replies true if the list of my nodes and the list of their
    390      * nodes are equal, i.e. if they consists of a list of nodes with
    391      * identical ids in the same order.
    392      *
    393      * @return true, if the lists are equal; false otherwise
    394      */
    395     protected boolean myAndTheirNodesEqual() {
    396         if (myNodes.size() != theirNodes.size()) {
    397             return false;
    398         }
    399         for (int i=0; i < myNodes.size(); i++) {
    400             if (myNodes.get(i).id != theirNodes.get(i).id) {
    401                 return false;
    402             }
    403         }
    404         return true;
    405     }
    406    
    40719    /**
    40820     * Populates the model with the nodes in the two {@see Way}s <code>my</code> and
    40921     * <code>their</code>.
    410      *  
    411      * @param my  my way (i.e. the way in the local dataset) 
     22     *
     23     * @param my  my way (i.e. the way in the local dataset)
    41224     * @param their their way (i.e. the way in the server dataset)
    41325     * @exception IllegalArgumentException thrown, if my is null
     
    41527     */
    41628    public void populate(Way my, Way their) {
    417         if (my == null) 
     29        if (my == null)
    41830            throw new IllegalArgumentException("parameter 'way' must not be null");
    419         if (their == null) 
     31        if (their == null)
    42032            throw new IllegalArgumentException("parameter 'their' must not be null");
    421         mergedNodes.clear();
    422         myNodes.clear();
    423         theirNodes.clear();
     33        mergedEntries.clear();
     34        myEntries.clear();
     35        theirEntries.clear();
    42436        for (Node n : my.nodes) {
    425             myNodes.add(n);
     37            myEntries.add(n);
    42638        }
    42739        for (Node n : their.nodes) {
    428             theirNodes.add(n);
     40            theirEntries.add(n);
    42941        }
    430         if (myAndTheirNodesEqual()) {
    431             mergedNodes = new ArrayList<Node>(myNodes);
     42        if (myAndTheirEntriesEqual()) {
     43            mergedEntries = new ArrayList<Node>(myEntries);
    43244            setFrozen(true);
    43345        } else {
    43446            setFrozen(false);
    43547        }
    436        
     48
    43749        fireModelDataChanged();
    43850    }
    439    
     51
    44052    /**
    44153     * Builds the command to resolve conflicts in the node list of a way
    44254     *
    443      * @param my  my way. Must not be null. 
     55     * @param my  my way. Must not be null.
    44456     * @param their  their way. Must not be null
    44557     * @return the command
    44658     * @exception IllegalArgumentException thrown, if my is null or not a {@see Way}
    44759     * @exception IllegalArgumentException thrown, if their is null or not a {@see Way}
    448      * @exception IllegalStateException thrown, if the merge is not yet frozen 
     60     * @exception IllegalStateException thrown, if the merge is not yet frozen
    44961     */
    450     public WayNodesConflictResolverCommand buildResolveCommand(Way my, Way their) {       
    451         if (my == null) {
    452             throw new IllegalArgumentException("parameter my most not be null");           
    453         }
    454         if (their == null) {
    455             throw new IllegalArgumentException("parameter my most not be null");           
    456         }
    457         if (! isFrozen()) {
     62    public WayNodesConflictResolverCommand buildResolveCommand(Way my, Way their) {
     63        if (my == null)
     64            throw new IllegalArgumentException("parameter my most not be null");
     65        if (their == null)
     66            throw new IllegalArgumentException("parameter my most not be null");
     67        if (! isFrozen())
    45868            throw new IllegalArgumentException("merged nodes not frozen yet. Can't build resolution command");
    459         }
    460         return new WayNodesConflictResolverCommand(my, their, mergedNodes);
     69        return new WayNodesConflictResolverCommand(my, their, mergedEntries);
    46170    }
    462    
    463     class NodeListTableModel extends DefaultTableModel {
    464         private ArrayList<Node> nodes;
    465        
    466         public NodeListTableModel(ArrayList<Node> nodes) {
    467             this.nodes = nodes;
    468         }
    469        
    470         @Override
    471         public int getRowCount() {
    472             return nodes == null ? 0 : nodes.size();
    473         }
    474 
    475         @Override
    476         public Object getValueAt(int row, int column) {
    477             return nodes.get(row);           
    478         }
    479 
    480         @Override
    481         public boolean isCellEditable(int row, int column) {
    482             return false;
    483         } 
    484     }   
    48571
    48672
     73    @Override
     74    public boolean isEqualEntry(Node e1, Node e2) {
     75        return e1.id == e2.id;
     76    }
     77
     78    @Override
     79    protected void setValueAt(DefaultTableModel model, Object value, int row, int col) {
     80        // do nothing - node list tables are not editable
     81    }
     82
     83    @Override
     84    protected Node cloneEntry(Node entry) {
     85        Node n = new Node(entry.id);
     86        n.cloneFrom(entry);
     87        return n;
     88    }
    48789}
  • trunk/src/org/openstreetmap/josm/gui/conflict/nodes/NodeListMerger.java

    r1626 r1631  
    11package org.openstreetmap.josm.gui.conflict.nodes;
    22
    3 import static org.openstreetmap.josm.tools.I18n.tr;
    4 
    5 import java.awt.GridBagConstraints;
    6 import java.awt.GridBagLayout;
    7 import java.awt.event.ActionEvent;
    8 import java.awt.event.ItemEvent;
    9 import java.awt.event.ItemListener;
    10 import java.beans.PropertyChangeEvent;
    11 import java.beans.PropertyChangeListener;
    12 import java.net.URL;
    133import java.util.logging.Logger;
    144
    15 import javax.swing.AbstractAction;
    16 import javax.swing.Action;
    17 import javax.swing.ImageIcon;
    18 import javax.swing.JButton;
    19 import javax.swing.JLabel;
    20 import javax.swing.JPanel;
    215import javax.swing.JScrollPane;
    226import javax.swing.JTable;
    23 import javax.swing.JToggleButton;
    24 import javax.swing.event.ListSelectionEvent;
    25 import javax.swing.event.ListSelectionListener;
    267
     8import org.openstreetmap.josm.data.osm.Node;
    279import org.openstreetmap.josm.data.osm.Way;
     10import org.openstreetmap.josm.gui.conflict.ListMerger;
    2811
    2912/**
     
    3114 *
    3215 */
    33 public class NodeListMerger extends JPanel implements PropertyChangeListener {
     16public class NodeListMerger extends ListMerger<Node> {
    3417    private static final Logger logger = Logger.getLogger(NodeListMerger.class.getName());
    35    
    36     private JTable myNodes;
    37     private JTable mergedNodes;
    38     private JTable theirNodes;
    39    
    40     private NodeListMergeModel model;
    41    
    42    
    43     private CopyStartLeftAction copyStartLeftAction;
    44     private CopyBeforeCurrentLeftAction copyBeforeCurrentLeftAction;
    45     private CopyAfterCurrentLeftAction copyAfterCurrentLeftAction;
    46     private CopyEndLeftAction copyEndLeftAction;
    4718
    48     private CopyStartRightAction copyStartRightAction;
    49     private CopyBeforeCurrentRightAction copyBeforeCurrentRightAction;
    50     private CopyAfterCurrentRightAction copyAfterCurrentRightAction;
    51     private CopyEndRightAction copyEndRightAction;
    52    
    53     private MoveUpMergedAction moveUpMergedAction;
    54     private MoveDownMergedAction moveDownMergedAction;
    55     private RemoveMergedAction removeMergedAction;
    56     private FreezeAction freezeAction;
    57    
    5819
    59    
    60     protected JScrollPane embeddInScrollPane(JTable table) {
    61         JScrollPane pane = new JScrollPane(table);
    62         pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    63         pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
    64        return pane;
    65     }
    66    
    67     protected JScrollPane buildMyNodesTable() {
    68         myNodes  = new JTable(
    69             model.getMyNodesTableModel(),
    70             new NodeListColumnModel(
    71                new NodeListTableCellRenderer()
    72             ),
    73             model.getMyNodesSelectionModel()
    74          );
    75          myNodes.setName("table.mynodes");
    76          return embeddInScrollPane(myNodes);
     20    public NodeListMerger() {
     21        super(new NodeListMergeModel());
    7722    }
    7823
    79     protected JScrollPane buildMergedNodesTable() {
    80         mergedNodes  = new JTable(
    81             model.getMergedNodesTableModel(),
    82             new NodeListColumnModel(
    83                 new NodeListTableCellRenderer()
    84             ),
    85             model.getMergedNodesSelectionModel()
    86          );
    87          mergedNodes.setName("table.mergednodes");
    88          return embeddInScrollPane(mergedNodes);
    89     }
    90    
    91     protected JScrollPane buildTheirNodesTable() {
    92         theirNodes  = new JTable(
    93             model.getTheirNodesTableModel(),
    94             new NodeListColumnModel(
    95                 new NodeListTableCellRenderer()
    96             ),
    97             model.getTheirNodesSelectionModel()
    98          );
    99         theirNodes.setName("table.theirnodes");
    100         return embeddInScrollPane(theirNodes);
    101     }
    102    
    103     protected void wireActionsToSelectionModels() {
    104         myNodes.getSelectionModel().addListSelectionListener(copyStartLeftAction);
    105        
    106         myNodes.getSelectionModel().addListSelectionListener(copyBeforeCurrentLeftAction);
    107         mergedNodes.getSelectionModel().addListSelectionListener(copyBeforeCurrentLeftAction);
    108        
    109         myNodes.getSelectionModel().addListSelectionListener(copyAfterCurrentLeftAction);
    110         mergedNodes.getSelectionModel().addListSelectionListener(copyAfterCurrentLeftAction);
    111        
    112         myNodes.getSelectionModel().addListSelectionListener(copyEndLeftAction);
    113        
    114        
    115         theirNodes.getSelectionModel().addListSelectionListener(copyStartRightAction);
    116        
    117         theirNodes.getSelectionModel().addListSelectionListener(copyBeforeCurrentRightAction);
    118         mergedNodes.getSelectionModel().addListSelectionListener(copyBeforeCurrentRightAction);
    119        
    120         theirNodes.getSelectionModel().addListSelectionListener(copyAfterCurrentRightAction);
    121         mergedNodes.getSelectionModel().addListSelectionListener(copyAfterCurrentRightAction);
    122        
    123         theirNodes.getSelectionModel().addListSelectionListener(copyEndRightAction);     
    124        
    125         mergedNodes.getSelectionModel().addListSelectionListener(moveUpMergedAction);
    126         mergedNodes.getSelectionModel().addListSelectionListener(moveDownMergedAction);
    127         mergedNodes.getSelectionModel().addListSelectionListener(removeMergedAction);
    128     }
    129    
    130    
    131    
    132     protected JPanel buildLeftButtonPanel() {
    133         JPanel pnl = new JPanel();
    134         pnl.setLayout(new GridBagLayout());
    135         GridBagConstraints gc = new GridBagConstraints();
    136 
    137         gc.gridx = 0;
    138         gc.gridy = 0;     
    139         copyStartLeftAction = new CopyStartLeftAction();   
    140         JButton btn = new JButton(copyStartLeftAction);
    141         btn.setName("button.copystartleft");
    142         pnl.add(btn, gc);
    143        
    144         gc.gridx = 0;
    145         gc.gridy = 1;
    146         copyBeforeCurrentLeftAction = new CopyBeforeCurrentLeftAction();
    147         btn = new JButton(copyBeforeCurrentLeftAction);
    148         btn.setName("button.copybeforecurrentleft");
    149         pnl.add(btn, gc);
    150 
    151         gc.gridx = 0;
    152         gc.gridy = 2;       
    153         copyAfterCurrentLeftAction = new CopyAfterCurrentLeftAction();
    154         btn = new JButton(copyAfterCurrentLeftAction);
    155         btn.setName("button.copyaftercurrentleft");
    156         pnl.add(btn, gc);
    157        
    158         gc.gridx = 0;
    159         gc.gridy = 3;
    160         copyEndLeftAction = new CopyEndLeftAction();
    161         btn = new JButton(copyEndLeftAction);
    162         btn.setName("button.copyendleft");
    163         pnl.add(btn, gc);
    164 
    165        
    166         return pnl;
    167     }
    168    
    169     protected JPanel buildRightButtonPanel() {
    170         JPanel pnl = new JPanel();
    171         pnl.setLayout(new GridBagLayout());
    172         GridBagConstraints gc = new GridBagConstraints();
    173 
    174         gc.gridx = 0;
    175         gc.gridy = 0;     
    176         copyStartRightAction = new CopyStartRightAction();
    177         pnl.add(new JButton(copyStartRightAction), gc);
    178        
    179         gc.gridx = 0;
    180         gc.gridy = 1;
    181         copyBeforeCurrentRightAction = new CopyBeforeCurrentRightAction();
    182         pnl.add(new JButton(copyBeforeCurrentRightAction), gc);
    183 
    184         gc.gridx = 0;
    185         gc.gridy = 2;       
    186         copyAfterCurrentRightAction = new CopyAfterCurrentRightAction();
    187         pnl.add(new JButton(copyAfterCurrentRightAction), gc);
    188        
    189         gc.gridx = 0;
    190         gc.gridy = 3;
    191         copyEndRightAction = new CopyEndRightAction();
    192         pnl.add(new JButton(copyEndRightAction), gc);
    193        
    194         return pnl;
    195     }
    196    
    197     protected JPanel buildMergedListControlButtons() {
    198         JPanel pnl = new JPanel();
    199         pnl.setLayout(new GridBagLayout());
    200         GridBagConstraints gc = new GridBagConstraints();
    201 
    202         gc.gridx = 0;
    203         gc.gridy = 0;
    204         gc.gridwidth = 1;
    205         gc.gridheight = 1;
    206         gc.fill = GridBagConstraints.HORIZONTAL;
    207         gc.anchor = GridBagConstraints.CENTER; 
    208         gc.weightx = 0.3;
    209         gc.weighty = 0.0;
    210         moveUpMergedAction = new MoveUpMergedAction();
    211         pnl.add(new JButton(moveUpMergedAction), gc);
    212 
    213         gc.gridx = 1;
    214         gc.gridy = 0;
    215         moveDownMergedAction = new MoveDownMergedAction();
    216         pnl.add(new JButton(moveDownMergedAction), gc);
    217 
    218         gc.gridx = 2;
    219         gc.gridy = 0;
    220         removeMergedAction = new RemoveMergedAction();
    221         pnl.add(new JButton(removeMergedAction), gc);
    222 
    223         gc.gridx = 0;
    224         gc.gridy = 1;
    225         gc.gridwidth = 3;
    226         gc.weightx = 1.0;
    227         freezeAction = new FreezeAction();
    228         JToggleButton btn = new JToggleButton(freezeAction);
    229         btn.setName("button.freeze");
    230         btn.addItemListener(freezeAction);
    231         pnl.add(btn, gc);
    232        
    233         return pnl;
    234     }
    235        
    236    
    237     protected void build() {
    238        
    239         setLayout(new GridBagLayout());
    240         GridBagConstraints gc = new GridBagConstraints();
    241        
    242         gc.gridx = 0;
    243         gc.gridy = 0;
    244         gc.gridwidth = 1;
    245         gc.gridheight = 1;
    246         gc.fill = GridBagConstraints.NONE;
    247         gc.anchor = GridBagConstraints.CENTER; 
    248         gc.weightx = 0.0;
    249         gc.weighty = 0.0;
    250         JLabel lbl = new JLabel(tr("Nodes in my version (local dataset)"));
    251         add(lbl, gc);
    252 
    253         gc.gridx = 2;
    254         gc.gridy = 0;
    255         gc.gridwidth = 1;
    256         gc.gridheight = 1;
    257         gc.fill = GridBagConstraints.NONE;
    258         gc.anchor = GridBagConstraints.CENTER;
    259         gc.weightx = 0.0;
    260         gc.weighty = 0.0;
    261         lbl = new JLabel(tr("Merged version"));
    262         add(lbl, gc);
    263 
    264         gc.gridx = 4;
    265         gc.gridy = 0;
    266         gc.gridwidth = 1;
    267         gc.gridheight = 1;
    268         gc.fill = GridBagConstraints.NONE;
    269         gc.anchor = GridBagConstraints.CENTER;
    270         gc.weightx = 0.0;
    271         gc.weighty = 0.0;
    272         lbl = new JLabel(tr("Nodes in their version (server dataset)"));
    273         add(lbl, gc);
    274        
    275 
    276         gc.gridx = 0;
    277         gc.gridy = 1;
    278         gc.gridwidth = 1;
    279         gc.gridheight = 1;
    280         gc.fill = GridBagConstraints.BOTH;
    281         gc.anchor = GridBagConstraints.FIRST_LINE_START;
    282         gc.weightx = 0.3;
    283         gc.weighty = 1.0;
    284         add(buildMyNodesTable(), gc);
    285        
    286         gc.gridx = 1;
    287         gc.gridy = 1;
    288         gc.gridwidth = 1;
    289         gc.gridheight = 1;
    290         gc.fill = GridBagConstraints.NONE;
    291         gc.anchor = GridBagConstraints.CENTER;
    292         gc.weightx = 0.0;
    293         gc.weighty = 0.0;
    294         add(buildLeftButtonPanel(), gc);
    295        
    296         gc.gridx = 2;
    297         gc.gridy = 1;
    298         gc.gridwidth = 1;
    299         gc.gridheight = 1;
    300         gc.fill = GridBagConstraints.BOTH;
    301         gc.anchor = GridBagConstraints.FIRST_LINE_START;
    302         gc.weightx = 0.3;
    303         gc.weighty = 0.0;
    304         add(buildMergedNodesTable(), gc);
    305        
    306         gc.gridx = 3;
    307         gc.gridy = 1;
    308         gc.gridwidth = 1;
    309         gc.gridheight = 1;
    310         gc.fill = GridBagConstraints.NONE;
    311         gc.anchor = GridBagConstraints.CENTER;
    312         gc.weightx = 0.0;
    313         gc.weighty = 0.0;
    314         add(buildRightButtonPanel(), gc);
    315        
    316         gc.gridx = 4;
    317         gc.gridy = 1;
    318         gc.gridwidth = 1;
    319         gc.gridheight = 1;
    320         gc.fill = GridBagConstraints.BOTH;
    321         gc.anchor = GridBagConstraints.FIRST_LINE_START;
    322         gc.weightx = 0.3;
    323         gc.weighty = 0.0;
    324         add(buildTheirNodesTable(), gc);
    325        
    326         gc.gridx = 2;
    327         gc.gridy = 2;
    328         gc.gridwidth = 1;
    329         gc.gridheight = 1;
    330         gc.fill = GridBagConstraints.BOTH;
    331         gc.anchor = GridBagConstraints.CENTER;
    332         gc.weightx = 0.3;
    333         gc.weighty = 0.0;
    334         add(buildMergedListControlButtons(), gc);
    335                
    336         wireActionsToSelectionModels();
    337     }
    338        
    339     public NodeListMerger() {
    340         model = new NodeListMergeModel();       
    341         build();
    342         model.addPropertyChangeListener(this);
    343     }
    344    
    345     public void populate(Way my, Way their) {
    346         model.populate(my, their);
    347     }
    348    
    349     /**
    350      * Action for copying selected nodes in the list of my nodes to the list of merged
    351      * nodes. Inserts the nodes at the beginning of the list of merged nodes.
    352      *
    353      */ 
    354     abstract class AbstractNodeManipulationAction extends AbstractAction {
    355 
    356         /**
    357          * load an icon given by iconName
    358          *
    359          * @param iconName  the name of the icon (without path, i.e. <tt>copystartleft.png</tt>
    360          * @return the icon; null, if the icon was not found
    361          */
    362         protected ImageIcon getIcon(String iconName) {
    363             String fullIconName  = "/images/dialogs/conflict/" + iconName;
    364             URL imageURL   = this.getClass().getResource(fullIconName);           
    365             if (imageURL == null) {
    366                 System.out.println(tr("WARNING: failed to load resource {0}", fullIconName));
    367                 return null;
    368             }
    369             return new ImageIcon(imageURL);
    370         }
     24    @Override
     25    protected JScrollPane buildMyElementsTable() {
     26        myEntriesTable  = new JTable(
     27                model.getMyTableModel(),
     28                new NodeListColumnModel(
     29                        new NodeListTableCellRenderer()
     30                ),
     31                model.getMySelectionModel()
     32        );
     33        myEntriesTable.setName("table.mynodes");
     34        return embeddInScrollPane(myEntriesTable);
    37135    }
    37236
    373     /**
    374      * Action for copying selected nodes in the list of my nodes to the list of merged
    375      * nodes. Inserts the nodes at the beginning of the list of merged nodes.
    376      *
    377      */
    378     class CopyStartLeftAction extends AbstractNodeManipulationAction implements ListSelectionListener {
    379 
    380         public CopyStartLeftAction() {           
    381             ImageIcon icon = getIcon("copystartleft.png");
    382             putValue(Action.SMALL_ICON, icon);
    383             if (icon == null) {
    384                 putValue(Action.NAME, tr("> top"));
    385             }
    386             putValue(Action.SHORT_DESCRIPTION, tr("Copy my selected nodes to the start of the merged node list"));
    387             setEnabled(false);
    388         }
    389 
    390         public void actionPerformed(ActionEvent arg0) {
    391             int [] rows = myNodes.getSelectedRows();
    392             model.copyMyNodesToTop(rows);           
    393         }
    394 
    395         public void valueChanged(ListSelectionEvent e) {
    396             setEnabled(!myNodes.getSelectionModel().isSelectionEmpty());           
    397         }
    398     }
    399    
    400     /**
    401      * Action for copying selected nodes in the list of my nodes to the list of merged
    402      * nodes. Inserts the nodes at the end of the list of merged nodes.
    403      *
    404      */
    405     class CopyEndLeftAction extends AbstractNodeManipulationAction implements ListSelectionListener {
    406 
    407         public CopyEndLeftAction() {           
    408             ImageIcon icon = getIcon("copyendleft.png");
    409             putValue(Action.SMALL_ICON, icon);
    410             if (icon == null) {
    411                 putValue(Action.NAME, tr("> bottom"));
    412             }
    413             putValue(Action.SHORT_DESCRIPTION, tr("Copy my selected nodes to the end of the merged node list"));
    414             setEnabled(false);
    415         }
    416 
    417         public void actionPerformed(ActionEvent arg0) {
    418             int [] rows = myNodes.getSelectedRows();
    419             model.copyMyNodesToEnd(rows); 
    420         }
    421 
    422         public void valueChanged(ListSelectionEvent e) {
    423             setEnabled(!myNodes.getSelectionModel().isSelectionEmpty());           
    424         }
    425     }
    426    
    427     /**
    428      * Action for copying selected nodes in the list of my nodes to the list of merged
    429      * nodes. Inserts the nodes before the first selected row in the list of merged nodes.
    430      *
    431      */
    432     class CopyBeforeCurrentLeftAction extends AbstractNodeManipulationAction implements ListSelectionListener {
    433 
    434         public CopyBeforeCurrentLeftAction() {           
    435             ImageIcon icon = getIcon("copybeforecurrentleft.png");
    436             putValue(Action.SMALL_ICON, icon);
    437             if (icon == null) {
    438                 putValue(Action.NAME, "> before");
    439             }
    440             putValue(Action.SHORT_DESCRIPTION, tr("Copy my selected nodes before the first selected node in the merged node list"));
    441             setEnabled(false);
    442         }
    443 
    444         public void actionPerformed(ActionEvent arg0) {
    445             int [] myRows = myNodes.getSelectedRows();
    446             int [] mergedRows = mergedNodes.getSelectedRows();
    447             if (mergedRows == null || mergedRows.length == 0) {
    448                 return;
    449             }
    450             int current = mergedRows[0];           
    451             model.copyMyNodesBeforeCurrent(myRows, current);           
    452         }
    453 
    454         public void valueChanged(ListSelectionEvent e) {       
    455             setEnabled(
    456                     !myNodes.getSelectionModel().isSelectionEmpty()
    457                   && ! mergedNodes.getSelectionModel().isSelectionEmpty()
    458             );           
    459         }
    460     }
    461    
    462     /**
    463      * Action for copying selected nodes in the list of my nodes to the list of merged
    464      * nodes. Inserts the nodes after the first selected row in the list of merged nodes.
    465      *
    466      */   
    467     class CopyAfterCurrentLeftAction extends AbstractNodeManipulationAction implements ListSelectionListener {
    468 
    469         public CopyAfterCurrentLeftAction() {           
    470             ImageIcon icon = getIcon("copyaftercurrentleft.png");
    471             putValue(Action.SMALL_ICON, icon);
    472             if (icon == null) {
    473                 putValue(Action.NAME, "> after");
    474             }
    475             putValue(Action.SHORT_DESCRIPTION, tr("Copy my selected nodes after the first selected node in the merged node list"));
    476             setEnabled(false);
    477         }
    478 
    479         public void actionPerformed(ActionEvent arg0) {
    480             int [] myRows = myNodes.getSelectedRows();
    481             int [] mergedRows = mergedNodes.getSelectedRows();
    482             if (mergedRows == null || mergedRows.length == 0) {
    483                 return;
    484             }
    485             int current = mergedRows[0];           
    486             model.copyMyNodesAfterCurrent(myRows, current);                       
    487         }
    488 
    489         public void valueChanged(ListSelectionEvent e) {       
    490             setEnabled(
    491                     !myNodes.getSelectionModel().isSelectionEmpty()
    492                   && ! mergedNodes.getSelectionModel().isSelectionEmpty()
    493             );           
    494         }
    495     }
    496    
    497    
    498     class CopyStartRightAction extends AbstractNodeManipulationAction implements ListSelectionListener {
    499 
    500         public CopyStartRightAction() {           
    501             ImageIcon icon = getIcon("copystartright.png");
    502             putValue(Action.SMALL_ICON, icon);
    503             if (icon == null) {
    504                 putValue(Action.NAME, "< top");
    505             }
    506             putValue(Action.SHORT_DESCRIPTION, tr("Copy their selected nodes to the start of the merged node list"));
    507             setEnabled(false);
    508         }
    509 
    510         public void actionPerformed(ActionEvent arg0) {
    511             int [] rows = theirNodes.getSelectedRows();
    512             model.copyTheirNodesToTop(rows);                       
    513         }
    514 
    515         public void valueChanged(ListSelectionEvent e) {
    516             setEnabled(!theirNodes.getSelectionModel().isSelectionEmpty());           
    517         }
    518     }
    519    
    520    
    521     class CopyEndRightAction extends AbstractNodeManipulationAction implements ListSelectionListener {
    522 
    523         public CopyEndRightAction() {           
    524             ImageIcon icon = getIcon("copyendright.png");
    525             putValue(Action.SMALL_ICON, icon);
    526             if (icon == null) {
    527                 putValue(Action.NAME, "< bottom");
    528             }
    529             putValue(Action.SHORT_DESCRIPTION, tr("Copy their selected nodes to the end of the merged node list"));
    530             setEnabled(false);
    531         }
    532 
    533         public void actionPerformed(ActionEvent arg0) {
    534             int [] rows = theirNodes.getSelectedRows();
    535             model.copyTheirNodesToEnd(rows); 
    536         }
    537 
    538         public void valueChanged(ListSelectionEvent e) {
    539             setEnabled(!theirNodes.getSelectionModel().isSelectionEmpty());           
    540         }
    541     }
    542    
    543     class CopyBeforeCurrentRightAction extends AbstractNodeManipulationAction implements ListSelectionListener {
    544 
    545         public CopyBeforeCurrentRightAction() {           
    546             ImageIcon icon = getIcon("copybeforecurrentright.png");
    547             putValue(Action.SMALL_ICON, icon);
    548             if (icon == null) {
    549                 putValue(Action.NAME, "< before");
    550             }
    551             putValue(Action.SHORT_DESCRIPTION, tr("Copy their selected nodes before the first selected node in the merged node list"));
    552             setEnabled(false);
    553         }
    554 
    555         public void actionPerformed(ActionEvent arg0) {
    556             int [] myRows = theirNodes.getSelectedRows();
    557             int [] mergedRows = mergedNodes.getSelectedRows();
    558             if (mergedRows == null || mergedRows.length == 0) {
    559                 return;
    560             }
    561             int current = mergedRows[0];           
    562             model.copyTheirNodesBeforeCurrent(myRows, current);           
    563         }
    564 
    565         public void valueChanged(ListSelectionEvent e) {       
    566             setEnabled(
    567                     !theirNodes.getSelectionModel().isSelectionEmpty()
    568                   && ! mergedNodes.getSelectionModel().isSelectionEmpty()
    569             );           
    570         }
    571     }
    572    
    573    
    574     class CopyAfterCurrentRightAction extends AbstractNodeManipulationAction implements ListSelectionListener {
    575 
    576         public CopyAfterCurrentRightAction() {           
    577             ImageIcon icon = getIcon("copyaftercurrentright.png");
    578             putValue(Action.SMALL_ICON, icon);
    579             if (icon == null) {
    580                 putValue(Action.NAME, "< after");
    581             }
    582             putValue(Action.SHORT_DESCRIPTION, tr("Copy their selected nodes after the first selected node in the merged node list"));
    583             setEnabled(false);
    584         }
    585 
    586         public void actionPerformed(ActionEvent arg0) {
    587             int [] myRows = theirNodes.getSelectedRows();
    588             int [] mergedRows = mergedNodes.getSelectedRows();
    589             if (mergedRows == null || mergedRows.length == 0) {
    590                 return;
    591             }
    592             int current = mergedRows[0];           
    593             model.copyTheirNodesAfterCurrent(myRows, current);                       
    594         }
    595 
    596         public void valueChanged(ListSelectionEvent e) {       
    597             setEnabled(
    598                     !theirNodes.getSelectionModel().isSelectionEmpty()
    599                   && ! mergedNodes.getSelectionModel().isSelectionEmpty()
    600             );           
    601         }
    602     }
    603    
    604    
    605     class MoveUpMergedAction extends AbstractNodeManipulationAction implements ListSelectionListener {
    606 
    607         public MoveUpMergedAction() {           
    608             ImageIcon icon = getIcon("moveup.png");
    609             putValue(Action.SMALL_ICON, icon);
    610             if (icon == null) {
    611                 putValue(Action.NAME, tr("Up"));
    612             }
    613             putValue(Action.SHORT_DESCRIPTION, tr("Move up the selected nodes by one position"));
    614             setEnabled(false);
    615         }
    616 
    617         public void actionPerformed(ActionEvent arg0) {
    618             int [] rows = mergedNodes.getSelectedRows();
    619             model.moveUpMergedNodes(rows);           
    620         }
    621 
    622         public void valueChanged(ListSelectionEvent e) {
    623             int [] rows = mergedNodes.getSelectedRows();
    624             setEnabled(
    625                     rows != null
    626                   && rows.length > 0
    627                   && rows[0] != 0
    628             );           
    629         }
    630     }
    631    
    632     class MoveDownMergedAction extends AbstractNodeManipulationAction implements ListSelectionListener {
    633 
    634         public MoveDownMergedAction() {           
    635             ImageIcon icon = getIcon("movedown.png");
    636             putValue(Action.SMALL_ICON, icon);
    637             if (icon == null) {
    638                 putValue(Action.NAME, tr("Down"));
    639             }
    640             putValue(Action.SHORT_DESCRIPTION, tr("Move down the selected nodes by one position"));
    641             setEnabled(false);
    642         }
    643 
    644         public void actionPerformed(ActionEvent arg0) {
    645             int [] rows = mergedNodes.getSelectedRows();
    646             model.moveDownMergedNodes(rows);                       
    647         }
    648 
    649         public void valueChanged(ListSelectionEvent e) {
    650             int [] rows = mergedNodes.getSelectedRows();
    651             setEnabled(
    652                     rows != null
    653                   && rows.length > 0
    654                   && rows[rows.length -1] != mergedNodes.getRowCount() -1
    655             );           
    656         }
    657     }
    658    
    659     class RemoveMergedAction extends AbstractNodeManipulationAction implements ListSelectionListener {
    660 
    661         public RemoveMergedAction() {           
    662             ImageIcon icon = getIcon("remove.png");
    663             putValue(Action.SMALL_ICON, icon);
    664             if (icon == null) {
    665                 putValue(Action.NAME, tr("Remove"));
    666             }
    667             putValue(Action.SHORT_DESCRIPTION, tr("Remove the selected nodes from the list of merged nodes"));
    668             setEnabled(false);
    669         }
    670 
    671         public void actionPerformed(ActionEvent arg0) {
    672             int [] rows = mergedNodes.getSelectedRows();
    673             model.removeMergedNodes(rows);                       
    674         }
    675 
    676         public void valueChanged(ListSelectionEvent e) {
    677             int [] rows = mergedNodes.getSelectedRows();
    678             setEnabled(
    679                     rows != null
    680                   && rows.length > 0
    681             );           
    682         }
    683     }
    684    
    685     class FreezeAction extends AbstractNodeManipulationAction implements ItemListener  {
    686 
    687         public FreezeAction() {           
    688             // FIXME
    689 //            ImageIcon icon = getIcon("remove.png");
    690 //            putValue(Action.SMALL_ICON, icon);
    691 //            if (icon == null) {
    692 //                putValue(Action.NAME, tr("Remove"));
    693 //            }
    694             putValue(Action.NAME, tr("Freeze"));
    695             putValue(Action.SHORT_DESCRIPTION, tr("Freeze the current list of merged nodes."));
    696 //            putValue(Action.SELECTED_KEY, false);
    697             setEnabled(true);
    698            
    699         }
    700 
    701         public void actionPerformed(ActionEvent arg0) {
    702             int [] rows = mergedNodes.getSelectedRows();
    703             model.removeMergedNodes(rows);                       
    704         }
    705        
    706         public void itemStateChanged(ItemEvent e) {
    707             int state = e.getStateChange();
    708             if (state == ItemEvent.SELECTED) {
    709                 model.setFrozen(true);
    710                 putValue(Action.NAME, tr("Unfreeze"));
    711                 putValue(Action.SHORT_DESCRIPTION, tr("Unfreeze the list of merged nodes and start merging"));
    712             } else if (state == ItemEvent.DESELECTED) {
    713                 model.setFrozen(false);
    714                 putValue(Action.NAME, tr("Freeze"));
    715                 putValue(Action.SHORT_DESCRIPTION, tr("Freeze the current list of merged nodes"));
    716             }           
    717         } 
     37    @Override
     38    protected JScrollPane buildMergedElementsTable() {
     39        mergedEntriesTable  = new JTable(
     40                model.getMergedTableModel(),
     41                new NodeListColumnModel(
     42                        new NodeListTableCellRenderer()
     43                ),
     44                model.getMergedSelectionModel()
     45        );
     46        mergedEntriesTable.setName("table.mergednodes");
     47        return embeddInScrollPane(mergedEntriesTable);
    71848    }
    71949
    720     protected void handlePropertyChangeFrozen(boolean oldValue, boolean newValue) {
    721         myNodes.getSelectionModel().clearSelection();
    722         myNodes.setEnabled(!newValue);       
    723         theirNodes.getSelectionModel().clearSelection();
    724         theirNodes.setEnabled(!newValue);
    725         mergedNodes.getSelectionModel().clearSelection();
    726         mergedNodes.setEnabled(!newValue);
    727 //        freezeAction.putValue(Action.SELECTED_KEY, newValue);
     50    @Override
     51    protected JScrollPane buildTheirElementsTable() {
     52        theirEntriesTable  = new JTable(
     53                model.getTheirTableModel(),
     54                new NodeListColumnModel(
     55                        new NodeListTableCellRenderer()
     56                ),
     57                model.getTheirSelectionModel()
     58        );
     59        theirEntriesTable.setName("table.theirnodes");
     60        return embeddInScrollPane(theirEntriesTable);
    72861    }
    729    
    730     public void propertyChange(PropertyChangeEvent evt) {
    731         if (evt.getPropertyName().equals(NodeListMergeModel.PROP_FROZEN)) {
    732             handlePropertyChangeFrozen((Boolean)evt.getOldValue(), (Boolean)evt.getNewValue());
    733         }
    734        
    735     }
    736    
    737     public NodeListMergeModel getModel() {
    738         return model;
     62
     63
     64    public void populate(Way my, Way their) {
     65        ((NodeListMergeModel)model).populate(my, their);
    73966    }
    74067}
  • trunk/src/org/openstreetmap/josm/gui/conflict/nodes/NodeListTableCellRenderer.java

    r1626 r1631  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.gui.conflict.nodes;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
    35
    46import java.awt.Color;
     
    1315
    1416import org.openstreetmap.josm.data.osm.Node;
    15 import static org.openstreetmap.josm.tools.I18n.tr;
    1617
    1718/**
     
    2526
    2627    /**
    27      * Load the image icon for an OSM primitive of type node 
     28     * Load the image icon for an OSM primitive of type node
    2829     *
    29      * @return the icon; null, if not found 
     30     * @return the icon; null, if not found
    3031     */
    3132    protected ImageIcon loadIcon() {
     
    3738        return new ImageIcon(url);
    3839    }
    39    
     40
    4041    /**
    41      * constructor 
     42     * constructor
    4243     */
    4344    public NodeListTableCellRenderer() {
     
    4546        setOpaque(true);
    4647    }
    47    
     48
    4849    /**
    4950     * creates the display name for a node. The name is derived from the nodes id,
    5051     * its name (i.e. the value of the tag with key name) and its coordinates.
    51      *  
    52      * @param node  the node 
    53      * @return the display name 
     52     *
     53     * @param node  the node
     54     * @return the display name
    5455     */
    5556    protected String getDisplayName(Node node) {
    56        StringBuilder sb = new StringBuilder();
    57        if (node.get("name") != null) {
    58            sb.append(node.get("name"));
    59            sb.append("/");
    60            sb.append(node.id);
    61        } else {
    62            sb.append(node.id);
    63        }
    64        sb.append(" (");
    65        
    66        if (node.coor != null) {
    67            sb.append(COORD_FORMATTER.format(node.coor.lat()));
    68            sb.append(",");
    69            sb.append(COORD_FORMATTER.format(node.coor.lon()));
    70        } else {
    71            sb.append("?,?");
    72        }
    73        sb.append(")");
    74        return sb.toString();
     57        StringBuilder sb = new StringBuilder();
     58        if (node.get("name") != null) {
     59            sb.append(node.get("name"));
     60            sb.append("/");
     61            sb.append(node.id);
     62        } else {
     63            sb.append(node.id);
     64        }
     65        sb.append(" (");
     66
     67        if (node.coor != null) {
     68            sb.append(COORD_FORMATTER.format(node.coor.lat()));
     69            sb.append(",");
     70            sb.append(COORD_FORMATTER.format(node.coor.lon()));
     71        } else {
     72            sb.append("?,?");
     73        }
     74        sb.append(")");
     75        return sb.toString();
    7576    }
    76    
     77
    7778    /**
    78      * reset the renderer 
     79     * reset the renderer
    7980     */
    8081    protected void reset() {
     
    8283        setForeground(Color.BLACK);
    8384    }
    84    
     85
    8586    /**
    86      * render a node 
    87      * @param node the node 
     87     * render a node
     88     * @param node the node
    8889     * @param isSelected
    8990     */
     
    9192        if (isSelected) {
    9293            setBackground(BGCOLOR_SELECTED);
    93         } 
     94        }
    9495        setText(getDisplayName(node));
    9596    }
    96    
     97
    9798    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
    9899            int row, int column) {
    99        
     100
    100101        Node node = (Node)value;
    101102        reset();
  • trunk/src/org/openstreetmap/josm/gui/conflict/tags/TagMerger.java

    r1626 r1631  
    77import java.awt.GridBagConstraints;
    88import java.awt.GridBagLayout;
     9import java.awt.Insets;
    910import java.awt.event.ActionEvent;
    1011import java.awt.event.AdjustmentEvent;
     
    2930
    3031    private JTable mineTable;
    31     private JTable undecidedTable;
     32    private JTable mergedTable;
    3233    private JTable theirTable;
    33     private TagMergeModel model;
     34    private final TagMergeModel model;
    3435    private JButton btnKeepMine;
    3536    private JButton btnKeepTheir;
     
    4041        pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    4142        pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
    42        
     43
    4344        adjustmentSynchronizer.synchronizeAdjustment(pane.getVerticalScrollBar());
    4445        return pane;
    4546    }
    46    
     47
    4748    protected JScrollPane buildMineTagTable() {
    4849        mineTable  = new JTable(
    49            model,
    50            new TagMergeColumnModel(
    51               new MineTableCellRenderer()
    52            )
     50                model,
     51                new TagMergeColumnModel(
     52                        new MineTableCellRenderer()
     53                )
    5354        );
     55        mineTable.setName("table.my");
    5456        return embeddInScrollPane(mineTable);
    5557    }
     
    5759    protected JScrollPane buildTheirTable() {
    5860        theirTable  = new JTable(
    59             model,
    60             new TagMergeColumnModel(
    61                new TheirTableCellRenderer()
    62             )
    63          );
    64          return embeddInScrollPane(theirTable);
    65     }
    66    
     61                model,
     62                new TagMergeColumnModel(
     63                        new TheirTableCellRenderer()
     64                )
     65        );
     66        theirTable.setName("table.their");
     67        return embeddInScrollPane(theirTable);
     68    }
     69
    6770    protected JScrollPane buildUndecidedTable() {
    68         undecidedTable  = new JTable(
    69             model,
    70             new TagMergeColumnModel(
    71                new UndecidedTableCellRenderer()
    72             )
    73          );
    74          return embeddInScrollPane(undecidedTable);
    75     }
    76    
     71        mergedTable  = new JTable(
     72                model,
     73                new TagMergeColumnModel(
     74                        new UndecidedTableCellRenderer()
     75                )
     76        );
     77        mergedTable.setName("table.merged");
     78        return embeddInScrollPane(mergedTable);
     79    }
     80
    7781    protected void build() {
    7882        GridBagConstraints gc = new GridBagConstraints();
    7983        setLayout(new GridBagLayout());
    80        
     84
    8185        adjustmentSynchronizer = new AdjustmentSynchronizer();
    82        
     86
    8387        gc.gridx = 0;
    8488        gc.gridy = 0;
     
    8690        gc.gridheight = 1;
    8791        gc.fill = GridBagConstraints.NONE;
    88         gc.anchor = GridBagConstraints.CENTER; 
    89         gc.weightx = 0.0;
    90         gc.weighty = 0.0;
     92        gc.anchor = GridBagConstraints.CENTER;
     93        gc.weightx = 0.0;
     94        gc.weighty = 0.0;
     95        gc.insets = new Insets(10,0,10,0);
    9196        JLabel lbl = new JLabel(tr("My version (local dataset)"));
    9297        add(lbl, gc);
     
    111116        gc.weightx = 0.0;
    112117        gc.weighty = 0.0;
     118        gc.insets = new Insets(0,0,0,0);
    113119        lbl = new JLabel(tr("Their version (server dataset)"));
    114120        add(lbl, gc);
     
    123129        gc.weighty = 1.0;
    124130        add(buildMineTagTable(), gc);
    125        
     131
    126132        gc.gridx = 1;
    127133        gc.gridy = 1;
     
    135141        mineTable.getSelectionModel().addListSelectionListener(keepMineAction);
    136142        btnKeepMine = new JButton(keepMineAction);
     143        btnKeepMine.setName("button.keepmine");
    137144        add(btnKeepMine, gc);
    138        
     145
    139146        gc.gridx = 2;
    140147        gc.gridy = 1;
     
    146153        gc.weighty = 1.0;
    147154        add(buildUndecidedTable(), gc);
    148        
     155
    149156        gc.gridx = 3;
    150157        gc.gridy = 1;
     
    157164        KeepTheirAction keepTheirAction = new KeepTheirAction();
    158165        btnKeepTheir = new JButton(keepTheirAction);
     166        btnKeepTheir.setName("button.keeptheir");
    159167        add(btnKeepTheir, gc);
    160        
     168
    161169        gc.gridx = 4;
    162170        gc.gridy = 1;
     
    169177        add(buildTheirTable(), gc);
    170178        theirTable.getSelectionModel().addListSelectionListener(keepTheirAction);
    171        
    172        
     179
     180
    173181        DoubleClickAdapter dblClickAdapter = new DoubleClickAdapter();
    174182        mineTable.addMouseListener(dblClickAdapter);
    175183        theirTable.addMouseListener(dblClickAdapter);
    176        
    177        
     184
     185
    178186        gc.gridx = 2;
    179187        gc.gridy = 2;
     
    185193        gc.weighty = 0.0;
    186194        UndecideAction undecidedAction = new UndecideAction();
    187         undecidedTable.getSelectionModel().addListSelectionListener(undecidedAction);
     195        mergedTable.getSelectionModel().addListSelectionListener(undecidedAction);
    188196        JButton btnUndecide = new JButton(undecidedAction);
     197        btnUndecide.setName("button.undecide");
    189198        add(btnUndecide, gc);
    190        
    191     }
    192    
     199
     200    }
     201
    193202    public TagMerger() {
    194203        model = new TagMergeModel();
    195204        build();
    196205    }
    197    
    198    
     206
    199207    public TagMergeModel getModel() {
    200208        return model;
    201209    }
    202    
     210
    203211    protected ImageIcon loadIcon(String name) {
    204        String path = "/images/dialogs/conflict/" + name;
    205        URL url = this.getClass().getResource(path);
    206        if (url == null) {
    207            System.out.println(tr("WARNING: failed to load resource {0}", path));
    208            return null;
    209        }
    210        return new ImageIcon(url);
    211     }
    212    
     212        String path = "/images/dialogs/conflict/" + name;
     213        URL url = this.getClass().getResource(path);
     214        if (url == null) {
     215            System.out.println(tr("WARNING: failed to load resource {0}", path));
     216            return null;
     217        }
     218        return new ImageIcon(url);
     219    }
     220
    213221    class KeepMineAction extends AbstractAction implements ListSelectionListener {
    214222
    215        
     223
    216224        public KeepMineAction() {
    217225            ImageIcon icon = loadIcon("tagkeepmine.png");
     
    225233            setEnabled(false);
    226234        }
    227        
     235
    228236        public void actionPerformed(ActionEvent arg0) {
    229237            int rows[] = mineTable.getSelectedRows();
    230             if (rows == null || rows.length == 0) {
    231                 return;
    232             }
    233             model.decide(rows, MergeDecisionType.KEEP_MINE);     
     238            if (rows == null || rows.length == 0)
     239                return;
     240            model.decide(rows, MergeDecisionType.KEEP_MINE);
    234241        }
    235242
    236243        public void valueChanged(ListSelectionEvent e) {
    237            setEnabled(mineTable.getSelectedRowCount() > 0);           
    238         }
    239     }
    240    
     244            setEnabled(mineTable.getSelectedRowCount() > 0);
     245        }
     246    }
     247
    241248    class KeepTheirAction extends AbstractAction implements ListSelectionListener {
    242        
     249
    243250        public KeepTheirAction() {
    244251            ImageIcon icon = loadIcon("tagkeeptheir.png");
     
    252259            setEnabled(false);
    253260        }
    254        
     261
    255262        public void actionPerformed(ActionEvent arg0) {
    256263            int rows[] = theirTable.getSelectedRows();
    257             if (rows == null || rows.length == 0) {
    258                 return;
    259             }
    260             model.decide(rows, MergeDecisionType.KEEP_THEIR);     
     264            if (rows == null || rows.length == 0)
     265                return;
     266            model.decide(rows, MergeDecisionType.KEEP_THEIR);
    261267        }
    262268
    263269        public void valueChanged(ListSelectionEvent e) {
    264            setEnabled(theirTable.getSelectedRowCount() > 0);           
    265         }
    266     }
    267    
     270            setEnabled(theirTable.getSelectedRowCount() > 0);
     271        }
     272    }
     273
    268274    class AdjustmentSynchronizer implements AdjustmentListener {
    269         private ArrayList<Adjustable> synchronizedAdjustables;
    270        
     275        private final ArrayList<Adjustable> synchronizedAdjustables;
     276
    271277        public AdjustmentSynchronizer() {
    272278            synchronizedAdjustables = new ArrayList<Adjustable>();
    273279        }
    274        
     280
    275281        public void synchronizeAdjustment(Adjustable adjustable) {
    276             if (adjustable == null) {
    277                 return;
    278             }
    279             if (synchronizedAdjustables.contains(adjustable)) {
    280                 return;
    281             }
     282            if (adjustable == null)
     283                return;
     284            if (synchronizedAdjustables.contains(adjustable))
     285                return;
    282286            synchronizedAdjustables.add(adjustable);
    283287            adjustable.addAdjustmentListener(this);
     
    292296        }
    293297    }
    294    
     298
    295299    class DoubleClickAdapter extends MouseAdapter {
    296300
     301        @Override
    297302        public void mouseClicked(MouseEvent e) {
    298             if (e.getClickCount() != 2) {
    299                 return;
    300             }
     303            if (e.getClickCount() != 2)
     304                return;
    301305            JTable table = null;
    302306            MergeDecisionType mergeDecision;
    303            
     307
    304308            if (e.getSource() == mineTable) {
    305                 table = (JTable)mineTable;
     309                table = mineTable;
    306310                mergeDecision = MergeDecisionType.KEEP_MINE;
    307311            } else if (e.getSource() == theirTable) {
    308                 table = (JTable)theirTable;
     312                table = theirTable;
    309313                mergeDecision = MergeDecisionType.KEEP_THEIR;
    310             } else if (e.getSource() == undecidedTable) {
    311                 table = (JTable)undecidedTable;
     314            } else if (e.getSource() == mergedTable) {
     315                table = mergedTable;
    312316                mergeDecision = MergeDecisionType.UNDECIDED;
    313             } else {
     317            } else
    314318                // double click in another component; shouldn't happen,
    315                 // but just in case
    316                 return;
    317             }
     319                // but just in case
     320                return;
    318321            int row = table.rowAtPoint(e.getPoint());
    319322            model.decide(row, mergeDecision);
    320323        }
    321     } 
    322    
     324    }
     325
    323326    class UndecideAction extends AbstractAction implements ListSelectionListener  {
    324327
     
    334337            setEnabled(false);
    335338        }
    336        
     339
    337340        public void actionPerformed(ActionEvent arg0) {
    338             int rows[] = undecidedTable.getSelectedRows();
    339             if (rows == null || rows.length == 0) {
    340                 return;
    341             }
    342             model.decide(rows, MergeDecisionType.UNDECIDED);     
     341            int rows[] = mergedTable.getSelectedRows();
     342            if (rows == null || rows.length == 0)
     343                return;
     344            model.decide(rows, MergeDecisionType.UNDECIDED);
    343345        }
    344346
    345347        public void valueChanged(ListSelectionEvent e) {
    346            setEnabled(undecidedTable.getSelectedRowCount() > 0);           
    347         }   
     348            setEnabled(mergedTable.getSelectedRowCount() > 0);
     349        }
    348350    }
    349351}
Note: See TracChangeset for help on using the changeset viewer.