Changeset 26023 in osm for applications/editors


Ignore:
Timestamp:
2011-05-21T05:33:30+02:00 (13 years ago)
Author:
joshdoe
Message:

josm-conflation: redesign GUI, add table/conflict resolver, but still far from usable

Location:
applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationAction.java

    r25942 r26023  
    88import java.awt.event.InputEvent;
    99import java.awt.event.KeyEvent;
    10 import java.util.ArrayList;
    11 import java.util.Collection;
    1210import java.util.List;
    1311import javax.swing.JOptionPane;
     
    1513
    1614import org.openstreetmap.josm.actions.JosmAction;
    17 import org.openstreetmap.josm.actions.search.SearchAction.SearchMode;
    18 import org.openstreetmap.josm.actions.search.SearchAction.SearchSetting;
    19 import org.openstreetmap.josm.actions.search.SearchCompiler;
    20 import org.openstreetmap.josm.data.conflict.ConflictCollection;
    21 import org.openstreetmap.josm.data.coor.EastNorth;
    22 import org.openstreetmap.josm.data.coor.LatLon;
    23 import org.openstreetmap.josm.data.osm.DataSet;
    24 import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2515import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    2616import org.openstreetmap.josm.tools.Shortcut;
     
    2818//@SuppressWarnings("serial")
    2919public class ConflationAction extends JosmAction {
    30     ConflictCollection conflicts;
    31 
    3220    public ConflationAction() {
    3321        super(tr("Conflation"), "conflation", tr("Conflation tool for merging data"),
     
    3826        //DataSet.selListeners.add(this);
    3927
    40         conflicts = new ConflictCollection();
    4128    }
    4229
     
    5744        ConflationOptionsDialog conflationDialog = new ConflationOptionsDialog(Main.parent, layerList);
    5845        conflationDialog.setVisible(true);
    59 
    60         if (conflationDialog.isCanceled()) {
    61             return;
    62         }
    63 
    64         // get layer and filter settings
    65         final OsmDataLayer refLayer = conflationDialog.getPanel().getRefLayer();
    66         final OsmDataLayer nonRefLayer = conflationDialog.getPanel().getNonRefLayer();
    67         SearchSetting refSearchSetting = conflationDialog.getPanel().getRefSearchSetting();
    68         SearchSetting nonRefSearchSetting = conflationDialog.getPanel().getNonRefSearchSetting();
    69 
    70         // apply filter criteria to each layer
    71         Collection<OsmPrimitive> refColl = getSelection(refSearchSetting, refLayer.data);
    72         Collection<OsmPrimitive> nonRefColl = getSelection(nonRefSearchSetting, nonRefLayer.data);
    73 
    74         if (refColl.isEmpty() || nonRefColl.isEmpty()) {
    75             JOptionPane.showMessageDialog(Main.parent, tr("At least one layer has no primitives given current filter settings."),
    76                     tr("Cannot perform conflation"), JOptionPane.ERROR_MESSAGE);
    77             return;
    78         }
    79 
    80         ArrayList<OsmPrimitive> refList = new ArrayList<OsmPrimitive>(refColl);
    81         ArrayList<OsmPrimitive> nonRefList = new ArrayList<OsmPrimitive>(nonRefColl);
    82 
    83         int n = refList.size();
    84         int m = nonRefList.size();
    85         int maxLen = Math.max(n, m);
    86         double cost[][] = new double[maxLen][maxLen];
    87 
    88         // calculate cost matrix
    89         for (int i = 0; i < n; i++) {
    90             for (int j = 0; j < m; j++) {
    91                 cost[i][j] = calcCost(refList.get(i), nonRefList.get(j));
    92             }
    93         }
    94 
    95         // perform assignment using Hungarian algorithm
    96         int[][] assignment = new int[maxLen][2];
    97         assignment = HungarianAlgorithm.hgAlgorithm(cost, "min");
    98 
    99         // create array of primitives based on indices from assignment
    100         OsmPrimitive[][] pairs = new OsmPrimitive[maxLen][2];
    101         for (int i = 0; i < maxLen; i++) {
    102             if (assignment[i][0] < n)
    103                 pairs[i][0] = refList.get(assignment[i][0]);
    104             else
    105                 pairs[i][0] = null;
    106             if (assignment[i][1] < m)
    107                 pairs[i][1] = nonRefList.get(assignment[i][1]);
    108             else
    109                 pairs[i][1] = null;
    110 
    111             if (pairs[i][0] != null && pairs[i][1] != null) {
    112                 conflicts.add(pairs[i][0], pairs[i][1]);
    113             }
    114         }
    115 
    116         // add conflation layer
    117         try {
    118             ConflationLayer conflationLayer = new ConflationLayer(refLayer.data, conflicts);
    119             Main.main.addLayer(conflationLayer);
    120         } catch (Exception ex) {
    121             JOptionPane.showMessageDialog(Main.parent, ex.toString(),
    122                     "Error adding conflation layer", JOptionPane.ERROR_MESSAGE);
    123         }
    124 
    125         // print list of matched pairsalong with distance
    126         // upon selection of one pair, highlight them and draw arrow
    127 
    128 
    129     }
    130 
    131     /**
    132      * Get selection of primitives for a given layer based on filter settings.
    133      *
    134      * @param   s    the given <code>SearchSetting</code>'s.
    135      * @param   ds   the <code>DataSet</code> of the selected <code>Layer</code>.
    136      */
    137     public static Collection<OsmPrimitive> getSelection(SearchSetting s, DataSet ds) {
    138         Collection<OsmPrimitive> sel = new ArrayList<OsmPrimitive>();
    139         try {
    140             String searchText = s.text;
    141             SearchCompiler.Match matcher = SearchCompiler.compile(searchText, s.caseSensitive, s.regexSearch);
    142 
    143             Collection<OsmPrimitive> all;
    144             if (s.allElements)
    145                 all = ds.allPrimitives();
    146             else
    147                 all = ds.allNonDeletedCompletePrimitives();
    148 
    149             if (s.mode != SearchMode.replace)
    150                 sel = ds.getSelected();
    151 
    152             for (OsmPrimitive osm : all) {
    153                 if (s.mode == SearchMode.replace) {
    154                     if (matcher.match(osm)) {
    155                         sel.add(osm);
    156                     }
    157                 } else if (s.mode == SearchMode.add && !ds.isSelected(osm) && matcher.match(osm)) {
    158                     sel.add(osm);
    159                 } else if (s.mode == SearchMode.remove && ds.isSelected(osm) && matcher.match(osm)) {
    160                     sel.remove(osm);
    161                 } else if (s.mode == SearchMode.in_selection && ds.isSelected(osm)&& !matcher.match(osm)) {
    162                     sel.remove(osm);
    163                 }
    164             }
    165         } catch (SearchCompiler.ParseError e) {
    166             JOptionPane.showMessageDialog(
    167                     Main.parent,
    168                     e.getMessage(),
    169                     tr("Error"),
    170                     JOptionPane.ERROR_MESSAGE
    171 
    172             );
    173         }
    174         return sel;
    175     }
    176 
    177     public static EastNorth getCenter(OsmPrimitive prim) {
    178             LatLon center = prim.getBBox().getTopLeft().getCenter(prim.getBBox().getBottomRight());
    179             return Main.map.mapView.getProjection().latlon2eastNorth(center);
    180     }
    181 
    182     /**
    183      * Calculate the cost of a pair of <code>OsmPrimitive</code>'s. A
    184      * simple cost consisting of the Euclidean distance is used
    185      * now, later we can also use dissimilarity between tags.
    186      *
    187      * @param   refPrim      the reference <code>OsmPrimitive</code>.
    188      * @param   nonRefPrim   the non-reference <code>OsmPrimitive</code>.
    189      */
    190     public double calcCost(OsmPrimitive refPrim, OsmPrimitive nonRefPrim) {
    191         double dist;
    192         try {
    193             dist = getCenter(refPrim).distance(getCenter(nonRefPrim));
    194         } catch (Exception e) {
    195             dist = 1000; // FIXME: what number to use?
    196         }
    197 
    198         // TODO: use other "distance" measures, i.e. matching tags
    199         return dist;
    20046    }
    20147}
  • applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationLayer.java

    r25942 r26023  
    6767            OsmPrimitive q = c.getTheir();
    6868            if (p != null && q != null) {
    69                 // we have a pair, so draw line between them
    70                 Point p1 = mv.getPoint(ConflationAction.getCenter(p));
    71                 Point p2 = mv.getPoint(ConflationAction.getCenter(q));
     69                // we have a pair, so draw line between them, FIXME: not good to use getCenter() from here, move to utils?
     70                Point p1 = mv.getPoint(ConflationOptionsPanel.getCenter(p));
     71                Point p2 = mv.getPoint(ConflationOptionsPanel.getCenter(q));
    7272                path.moveTo(p1.x, p1.y);
    7373                path.lineTo(p2.x, p2.y);
  • applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationOptionsDialog.java

    r25942 r26023  
    2626
    2727    public ConflationOptionsDialog(Component parent, List<OsmDataLayer> layers) {
    28         super(JOptionPane.getFrameForComponent(parent),tr("Conflation Options"), ModalityType.DOCUMENT_MODAL);
     28        super(JOptionPane.getFrameForComponent(parent),tr("Conflation Options"), ModalityType.MODELESS);
    2929        getContentPane().setLayout(new BorderLayout());
    3030        panel = new ConflationOptionsPanel(this, layers);
  • applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationOptionsPanel.form

    r25942 r26023  
    11<?xml version="1.1" encoding="UTF-8" ?>
    22
    3 <Form version="1.3" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    4   <NonVisualComponents>
    5     <Component class="javax.swing.ButtonGroup" name="refSearchModeButtonGroup">
    6     </Component>
    7     <Component class="javax.swing.ButtonGroup" name="nonRefSearchModeButtonGroup">
    8     </Component>
    9   </NonVisualComponents>
     3<Form version="1.6" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    104  <AuxValues>
    115    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
     
    1812    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
    1913    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
    20     <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,-46,0,0,1,86"/>
     14    <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,2,4,0,0,2,-102"/>
    2115  </AuxValues>
    2216
     
    7569                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
    7670                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
    77                     <TitledBorder title="Reference Set"/>
     71                    <TitledBorder title="My Set"/>
    7872                  </Border>
    7973                </Property>
     
    8377                <DimensionLayout dim="0">
    8478                  <Group type="103" groupAlignment="0" attributes="0">
    85                       <Component id="jPanel4" alignment="0" max="32767" attributes="0"/>
     79                      <Group type="102" attributes="0">
     80                          <EmptySpace max="-2" attributes="0"/>
     81                          <Group type="103" groupAlignment="0" attributes="0">
     82                              <Group type="102" attributes="0">
     83                                  <Component id="freezeMySetButton" min="-2" max="-2" attributes="0"/>
     84                                  <EmptySpace pref="387" max="32767" attributes="0"/>
     85                                  <Component id="restoreMySetButton" min="-2" max="-2" attributes="0"/>
     86                              </Group>
     87                              <Group type="102" alignment="0" attributes="0">
     88                                  <Group type="103" groupAlignment="0" attributes="0">
     89                                      <Component id="jLabel4" alignment="0" min="-2" max="-2" attributes="0"/>
     90                                      <Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
     91                                      <Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
     92                                      <Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
     93                                  </Group>
     94                                  <EmptySpace type="unrelated" max="-2" attributes="0"/>
     95                                  <Group type="103" groupAlignment="0" attributes="0">
     96                                      <Component id="myLayerLabel" alignment="0" min="-2" max="-2" attributes="0"/>
     97                                      <Component id="myNodeCountLabel" alignment="0" min="-2" max="-2" attributes="0"/>
     98                                      <Component id="myWayCountLabel" alignment="0" min="-2" max="-2" attributes="0"/>
     99                                      <Component id="myRelationCountLabel" alignment="0" min="-2" max="-2" attributes="0"/>
     100                                  </Group>
     101                              </Group>
     102                          </Group>
     103                          <EmptySpace max="-2" attributes="0"/>
     104                      </Group>
    86105                  </Group>
    87106                </DimensionLayout>
    88107                <DimensionLayout dim="1">
    89108                  <Group type="103" groupAlignment="0" attributes="0">
    90                       <Component id="jPanel4" min="-2" max="-2" attributes="0"/>
     109                      <Group type="102" alignment="0" attributes="0">
     110                          <EmptySpace max="-2" attributes="0"/>
     111                          <Group type="103" groupAlignment="3" attributes="0">
     112                              <Component id="freezeMySetButton" alignment="3" min="-2" max="-2" attributes="0"/>
     113                              <Component id="restoreMySetButton" alignment="3" min="-2" max="-2" attributes="0"/>
     114                          </Group>
     115                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
     116                          <Group type="103" groupAlignment="3" attributes="0">
     117                              <Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
     118                              <Component id="myLayerLabel" alignment="3" min="-2" max="-2" attributes="0"/>
     119                          </Group>
     120                          <EmptySpace min="-2" pref="11" max="-2" attributes="0"/>
     121                          <Group type="103" groupAlignment="3" attributes="0">
     122                              <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
     123                              <Component id="myNodeCountLabel" alignment="3" min="-2" pref="14" max="-2" attributes="0"/>
     124                          </Group>
     125                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
     126                          <Group type="103" groupAlignment="3" attributes="0">
     127                              <Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/>
     128                              <Component id="myWayCountLabel" alignment="3" min="-2" max="-2" attributes="0"/>
     129                          </Group>
     130                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
     131                          <Group type="103" groupAlignment="3" attributes="0">
     132                              <Component id="jLabel4" alignment="3" min="-2" max="-2" attributes="0"/>
     133                              <Component id="myRelationCountLabel" alignment="3" min="-2" max="-2" attributes="0"/>
     134                          </Group>
     135                          <EmptySpace pref="38" max="32767" attributes="0"/>
     136                      </Group>
    91137                  </Group>
    92138                </DimensionLayout>
    93139              </Layout>
    94140              <SubComponents>
    95                 <Container class="javax.swing.JPanel" name="jPanel4">
    96 
    97                   <Layout>
    98                     <DimensionLayout dim="0">
    99                       <Group type="103" groupAlignment="0" attributes="0">
    100                           <Group type="102" attributes="0">
    101                               <Group type="103" groupAlignment="0" attributes="0">
    102                                   <Group type="102" attributes="0">
    103                                       <EmptySpace max="-2" attributes="0"/>
    104                                       <Group type="103" groupAlignment="0" attributes="0">
    105                                           <Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
    106                                           <Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
    107                                       </Group>
    108                                       <EmptySpace type="separate" max="-2" attributes="0"/>
    109                                       <Group type="103" groupAlignment="0" attributes="0">
    110                                           <Component id="refLayerComboBox" pref="246" max="32767" attributes="0"/>
    111                                           <Component id="refFilterTextField" alignment="0" pref="246" max="32767" attributes="0"/>
    112                                       </Group>
    113                                   </Group>
    114                                   <Group type="102" alignment="0" attributes="0">
    115                                       <Component id="jPanel5" min="-2" max="-2" attributes="0"/>
    116                                       <EmptySpace type="unrelated" max="-2" attributes="0"/>
    117                                       <Group type="103" groupAlignment="0" attributes="0">
    118                                           <Component id="refCaseSensitiveCheckBox" min="-2" max="-2" attributes="0"/>
    119                                           <Component id="refAllObjectsCheckBox" min="-2" max="-2" attributes="0"/>
    120                                           <Component id="refRegExCheckBox" min="-2" max="-2" attributes="0"/>
    121                                       </Group>
    122                                   </Group>
    123                               </Group>
    124                               <EmptySpace max="-2" attributes="0"/>
    125                           </Group>
    126                       </Group>
    127                     </DimensionLayout>
    128                     <DimensionLayout dim="1">
    129                       <Group type="103" groupAlignment="0" attributes="0">
    130                           <Group type="102" alignment="0" attributes="0">
    131                               <EmptySpace max="32767" attributes="0"/>
    132                               <Group type="103" groupAlignment="3" attributes="0">
    133                                   <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
    134                                   <Component id="refLayerComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
    135                               </Group>
    136                               <EmptySpace max="-2" attributes="0"/>
    137                               <Group type="103" groupAlignment="3" attributes="0">
    138                                   <Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
    139                                   <Component id="refFilterTextField" alignment="3" min="-2" max="-2" attributes="0"/>
    140                               </Group>
    141                               <EmptySpace max="-2" attributes="0"/>
    142                               <Group type="103" groupAlignment="0" attributes="0">
    143                                   <Component id="jPanel5" min="-2" max="-2" attributes="0"/>
    144                                   <Group type="102" alignment="0" attributes="0">
    145                                       <Component id="refCaseSensitiveCheckBox" min="-2" max="-2" attributes="0"/>
    146                                       <EmptySpace max="-2" attributes="0"/>
    147                                       <Component id="refAllObjectsCheckBox" min="-2" max="-2" attributes="0"/>
    148                                       <EmptySpace max="-2" attributes="0"/>
    149                                       <Component id="refRegExCheckBox" min="-2" max="-2" attributes="0"/>
    150                                   </Group>
    151                               </Group>
    152                           </Group>
    153                       </Group>
    154                     </DimensionLayout>
    155                   </Layout>
    156                   <SubComponents>
    157                     <Component class="javax.swing.JLabel" name="jLabel1">
    158                       <Properties>
    159                         <Property name="text" type="java.lang.String" value="Layer"/>
    160                       </Properties>
    161                     </Component>
    162                     <Component class="javax.swing.JComboBox" name="refLayerComboBox">
    163                       <Properties>
    164                         <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
    165                           <StringArray count="4">
    166                             <StringItem index="0" value="Item 1"/>
    167                             <StringItem index="1" value="Item 2"/>
    168                             <StringItem index="2" value="Item 3"/>
    169                             <StringItem index="3" value="Item 4"/>
    170                           </StringArray>
    171                         </Property>
    172                       </Properties>
    173                     </Component>
    174                     <Component class="javax.swing.JLabel" name="jLabel2">
    175                       <Properties>
    176                         <Property name="text" type="java.lang.String" value="Filter"/>
    177                       </Properties>
    178                     </Component>
    179                     <Component class="javax.swing.JTextField" name="refFilterTextField">
    180                     </Component>
    181                     <Container class="javax.swing.JPanel" name="jPanel5">
    182                       <Properties>
    183                         <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
    184                           <Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
    185                             <EtchetBorder/>
    186                           </Border>
    187                         </Property>
    188                       </Properties>
    189 
    190                       <Layout>
    191                         <DimensionLayout dim="0">
    192                           <Group type="103" groupAlignment="0" attributes="0">
    193                               <Group type="102" attributes="0">
    194                                   <EmptySpace max="-2" attributes="0"/>
    195                                   <Group type="103" groupAlignment="0" attributes="0">
    196                                       <Component id="refReplaceRadio" alignment="0" min="-2" max="-2" attributes="0"/>
    197                                       <Component id="refAddRadio" alignment="0" min="-2" max="-2" attributes="0"/>
    198                                       <Component id="refRemoveRadio" alignment="0" min="-2" max="-2" attributes="0"/>
    199                                       <Component id="refInSelectionRadio" alignment="0" min="-2" max="-2" attributes="0"/>
    200                                   </Group>
    201                                   <EmptySpace max="32767" attributes="0"/>
    202                               </Group>
    203                           </Group>
    204                         </DimensionLayout>
    205                         <DimensionLayout dim="1">
    206                           <Group type="103" groupAlignment="0" attributes="0">
    207                               <Group type="102" alignment="0" attributes="0">
    208                                   <EmptySpace max="32767" attributes="0"/>
    209                                   <Component id="refReplaceRadio" min="-2" max="-2" attributes="0"/>
    210                                   <EmptySpace max="-2" attributes="0"/>
    211                                   <Component id="refAddRadio" min="-2" max="-2" attributes="0"/>
    212                                   <EmptySpace max="-2" attributes="0"/>
    213                                   <Component id="refRemoveRadio" min="-2" max="-2" attributes="0"/>
    214                                   <EmptySpace max="-2" attributes="0"/>
    215                                   <Component id="refInSelectionRadio" min="-2" max="-2" attributes="0"/>
    216                               </Group>
    217                           </Group>
    218                         </DimensionLayout>
    219                       </Layout>
    220                       <SubComponents>
    221                         <Component class="javax.swing.JRadioButton" name="refReplaceRadio">
    222                           <Properties>
    223                             <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
    224                               <ComponentRef name="refSearchModeButtonGroup"/>
    225                             </Property>
    226                             <Property name="selected" type="boolean" value="true"/>
    227                             <Property name="text" type="java.lang.String" value="Replace selection"/>
    228                           </Properties>
    229                         </Component>
    230                         <Component class="javax.swing.JRadioButton" name="refAddRadio">
    231                           <Properties>
    232                             <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
    233                               <ComponentRef name="refSearchModeButtonGroup"/>
    234                             </Property>
    235                             <Property name="text" type="java.lang.String" value="Add to selection"/>
    236                           </Properties>
    237                           <Events>
    238                             <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="refAddRadioActionPerformed"/>
    239                           </Events>
    240                         </Component>
    241                         <Component class="javax.swing.JRadioButton" name="refRemoveRadio">
    242                           <Properties>
    243                             <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
    244                               <ComponentRef name="refSearchModeButtonGroup"/>
    245                             </Property>
    246                             <Property name="text" type="java.lang.String" value="Remove from selection"/>
    247                           </Properties>
    248                         </Component>
    249                         <Component class="javax.swing.JRadioButton" name="refInSelectionRadio">
    250                           <Properties>
    251                             <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
    252                               <ComponentRef name="refSearchModeButtonGroup"/>
    253                             </Property>
    254                             <Property name="text" type="java.lang.String" value="Find in selection"/>
    255                           </Properties>
    256                         </Component>
    257                       </SubComponents>
    258                     </Container>
    259                     <Component class="javax.swing.JCheckBox" name="refCaseSensitiveCheckBox">
    260                       <Properties>
    261                         <Property name="text" type="java.lang.String" value="Case sensitive"/>
    262                       </Properties>
    263                     </Component>
    264                     <Component class="javax.swing.JCheckBox" name="refAllObjectsCheckBox">
    265                       <Properties>
    266                         <Property name="text" type="java.lang.String" value="All objects"/>
    267                       </Properties>
    268                     </Component>
    269                     <Component class="javax.swing.JCheckBox" name="refRegExCheckBox">
    270                       <Properties>
    271                         <Property name="text" type="java.lang.String" value="Regular expression"/>
    272                       </Properties>
    273                     </Component>
    274                   </SubComponents>
    275                 </Container>
     141                <Component class="javax.swing.JButton" name="freezeMySetButton">
     142                  <Properties>
     143                    <Property name="text" type="java.lang.String" value="Freeze Selection"/>
     144                  </Properties>
     145                  <Events>
     146                    <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="freezeMySetButtonActionPerformed"/>
     147                  </Events>
     148                </Component>
     149                <Component class="javax.swing.JButton" name="restoreMySetButton">
     150                  <Properties>
     151                    <Property name="text" type="java.lang.String" value="Restore Selection"/>
     152                  </Properties>
     153                  <Events>
     154                    <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="restoreMySetButtonActionPerformed"/>
     155                  </Events>
     156                </Component>
     157                <Component class="javax.swing.JLabel" name="jLabel1">
     158                  <Properties>
     159                    <Property name="text" type="java.lang.String" value="Nodes"/>
     160                  </Properties>
     161                </Component>
     162                <Component class="javax.swing.JLabel" name="jLabel2">
     163                  <Properties>
     164                    <Property name="text" type="java.lang.String" value="Layer"/>
     165                  </Properties>
     166                </Component>
     167                <Component class="javax.swing.JLabel" name="jLabel3">
     168                  <Properties>
     169                    <Property name="text" type="java.lang.String" value="Ways"/>
     170                  </Properties>
     171                </Component>
     172                <Component class="javax.swing.JLabel" name="jLabel4">
     173                  <Properties>
     174                    <Property name="text" type="java.lang.String" value="Relations"/>
     175                  </Properties>
     176                </Component>
     177                <Component class="javax.swing.JLabel" name="myRelationCountLabel">
     178                  <Properties>
     179                    <Property name="text" type="java.lang.String" value="0"/>
     180                  </Properties>
     181                </Component>
     182                <Component class="javax.swing.JLabel" name="myWayCountLabel">
     183                  <Properties>
     184                    <Property name="text" type="java.lang.String" value="0"/>
     185                  </Properties>
     186                </Component>
     187                <Component class="javax.swing.JLabel" name="myNodeCountLabel">
     188                  <Properties>
     189                    <Property name="text" type="java.lang.String" value="0"/>
     190                  </Properties>
     191                </Component>
     192                <Component class="javax.swing.JLabel" name="myLayerLabel">
     193                  <Properties>
     194                    <Property name="text" type="java.lang.String" value="(invalid)"/>
     195                  </Properties>
     196                </Component>
    276197              </SubComponents>
    277198            </Container>
     
    280201                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
    281202                  <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
    282                     <TitledBorder title="Non-Reference Set"/>
     203                    <TitledBorder title="Their Set"/>
    283204                  </Border>
    284205                </Property>
     
    288209                <DimensionLayout dim="0">
    289210                  <Group type="103" groupAlignment="0" attributes="0">
    290                       <Component id="jPanel7" alignment="0" max="32767" attributes="0"/>
     211                      <Group type="102" attributes="0">
     212                          <EmptySpace max="-2" attributes="0"/>
     213                          <Group type="103" groupAlignment="0" attributes="0">
     214                              <Group type="102" alignment="1" attributes="0">
     215                                  <Component id="freezeTheirSelectionButton" min="-2" max="-2" attributes="0"/>
     216                                  <EmptySpace pref="387" max="32767" attributes="0"/>
     217                                  <Component id="restoreTheirSetButton" min="-2" max="-2" attributes="0"/>
     218                              </Group>
     219                              <Group type="102" alignment="0" attributes="0">
     220                                  <Group type="103" groupAlignment="0" attributes="0">
     221                                      <Component id="jLabel5" alignment="0" min="-2" max="-2" attributes="0"/>
     222                                      <Component id="jLabel9" alignment="0" min="-2" max="-2" attributes="0"/>
     223                                      <Component id="jLabel7" alignment="0" min="-2" max="-2" attributes="0"/>
     224                                      <Component id="jLabel6" alignment="0" min="-2" max="-2" attributes="0"/>
     225                                  </Group>
     226                                  <EmptySpace type="unrelated" max="-2" attributes="0"/>
     227                                  <Group type="103" groupAlignment="0" attributes="0">
     228                                      <Component id="theirLayerLabel" alignment="0" min="-2" max="-2" attributes="0"/>
     229                                      <Component id="theirNodeCountLabel" alignment="0" min="-2" max="-2" attributes="0"/>
     230                                      <Component id="theirWayCountLabel" alignment="0" min="-2" max="-2" attributes="0"/>
     231                                      <Component id="theirRelationCountLabel" alignment="0" min="-2" max="-2" attributes="0"/>
     232                                  </Group>
     233                              </Group>
     234                          </Group>
     235                          <EmptySpace max="-2" attributes="0"/>
     236                      </Group>
    291237                  </Group>
    292238                </DimensionLayout>
    293239                <DimensionLayout dim="1">
    294240                  <Group type="103" groupAlignment="0" attributes="0">
    295                       <Component id="jPanel7" min="-2" max="-2" attributes="0"/>
     241                      <Group type="102" alignment="0" attributes="0">
     242                          <EmptySpace max="-2" attributes="0"/>
     243                          <Group type="103" groupAlignment="3" attributes="0">
     244                              <Component id="freezeTheirSelectionButton" alignment="3" min="-2" max="-2" attributes="0"/>
     245                              <Component id="restoreTheirSetButton" alignment="3" min="-2" max="-2" attributes="0"/>
     246                          </Group>
     247                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
     248                          <Group type="103" groupAlignment="3" attributes="0">
     249                              <Component id="jLabel6" alignment="3" min="-2" max="-2" attributes="0"/>
     250                              <Component id="theirLayerLabel" alignment="3" min="-2" max="-2" attributes="0"/>
     251                          </Group>
     252                          <EmptySpace min="-2" pref="11" max="-2" attributes="0"/>
     253                          <Group type="103" groupAlignment="3" attributes="0">
     254                              <Component id="jLabel7" alignment="3" min="-2" max="-2" attributes="0"/>
     255                              <Component id="theirNodeCountLabel" alignment="3" min="-2" pref="14" max="-2" attributes="0"/>
     256                          </Group>
     257                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
     258                          <Group type="103" groupAlignment="3" attributes="0">
     259                              <Component id="jLabel9" alignment="3" min="-2" max="-2" attributes="0"/>
     260                              <Component id="theirWayCountLabel" alignment="3" min="-2" max="-2" attributes="0"/>
     261                          </Group>
     262                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
     263                          <Group type="103" groupAlignment="3" attributes="0">
     264                              <Component id="jLabel5" alignment="3" min="-2" max="-2" attributes="0"/>
     265                              <Component id="theirRelationCountLabel" alignment="3" min="-2" max="-2" attributes="0"/>
     266                          </Group>
     267                          <EmptySpace pref="32" max="32767" attributes="0"/>
     268                      </Group>
    296269                  </Group>
    297270                </DimensionLayout>
    298271              </Layout>
    299272              <SubComponents>
    300                 <Container class="javax.swing.JPanel" name="jPanel7">
    301 
    302                   <Layout>
    303                     <DimensionLayout dim="0">
    304                       <Group type="103" groupAlignment="0" attributes="0">
    305                           <Group type="102" alignment="0" attributes="0">
    306                               <Group type="103" groupAlignment="0" attributes="0">
    307                                   <Group type="102" alignment="0" attributes="0">
    308                                       <EmptySpace max="-2" attributes="0"/>
    309                                       <Group type="103" groupAlignment="0" attributes="0">
    310                                           <Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
    311                                           <Component id="jLabel4" alignment="0" min="-2" max="-2" attributes="0"/>
    312                                       </Group>
    313                                       <EmptySpace type="separate" max="-2" attributes="0"/>
    314                                       <Group type="103" groupAlignment="0" attributes="0">
    315                                           <Component id="nonRefLayerComboBox" alignment="0" pref="246" max="32767" attributes="0"/>
    316                                           <Component id="nonRefFilterTextField" alignment="0" pref="246" max="32767" attributes="0"/>
    317                                       </Group>
    318                                   </Group>
    319                                   <Group type="102" alignment="0" attributes="0">
    320                                       <Component id="jPanel8" min="-2" max="-2" attributes="0"/>
    321                                       <EmptySpace type="unrelated" max="-2" attributes="0"/>
    322                                       <Group type="103" groupAlignment="0" attributes="0">
    323                                           <Component id="nonRefCaseSensitiveCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
    324                                           <Component id="nonRefAllObjectsCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
    325                                           <Component id="nonRefRegExCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
    326                                       </Group>
    327                                   </Group>
    328                               </Group>
    329                               <EmptySpace max="-2" attributes="0"/>
    330                           </Group>
    331                       </Group>
    332                     </DimensionLayout>
    333                     <DimensionLayout dim="1">
    334                       <Group type="103" groupAlignment="0" attributes="0">
    335                           <Group type="102" alignment="0" attributes="0">
    336                               <EmptySpace max="32767" attributes="0"/>
    337                               <Group type="103" groupAlignment="3" attributes="0">
    338                                   <Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/>
    339                                   <Component id="nonRefLayerComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
    340                               </Group>
    341                               <EmptySpace max="-2" attributes="0"/>
    342                               <Group type="103" groupAlignment="3" attributes="0">
    343                                   <Component id="jLabel4" alignment="3" min="-2" max="-2" attributes="0"/>
    344                                   <Component id="nonRefFilterTextField" alignment="3" min="-2" max="-2" attributes="0"/>
    345                               </Group>
    346                               <EmptySpace max="-2" attributes="0"/>
    347                               <Group type="103" groupAlignment="0" attributes="0">
    348                                   <Component id="jPanel8" alignment="0" min="-2" max="-2" attributes="0"/>
    349                                   <Group type="102" alignment="0" attributes="0">
    350                                       <Component id="nonRefCaseSensitiveCheckBox" min="-2" max="-2" attributes="0"/>
    351                                       <EmptySpace max="-2" attributes="0"/>
    352                                       <Component id="nonRefAllObjectsCheckBox" min="-2" max="-2" attributes="0"/>
    353                                       <EmptySpace max="-2" attributes="0"/>
    354                                       <Component id="nonRefRegExCheckBox" min="-2" max="-2" attributes="0"/>
    355                                   </Group>
    356                               </Group>
    357                           </Group>
    358                       </Group>
    359                     </DimensionLayout>
    360                   </Layout>
    361                   <SubComponents>
    362                     <Component class="javax.swing.JLabel" name="jLabel3">
    363                       <Properties>
    364                         <Property name="text" type="java.lang.String" value="Layer"/>
    365                       </Properties>
    366                     </Component>
    367                     <Component class="javax.swing.JComboBox" name="nonRefLayerComboBox">
    368                       <Properties>
    369                         <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
    370                           <StringArray count="4">
    371                             <StringItem index="0" value="Item 1"/>
    372                             <StringItem index="1" value="Item 2"/>
    373                             <StringItem index="2" value="Item 3"/>
    374                             <StringItem index="3" value="Item 4"/>
    375                           </StringArray>
    376                         </Property>
    377                       </Properties>
    378                     </Component>
    379                     <Component class="javax.swing.JLabel" name="jLabel4">
    380                       <Properties>
    381                         <Property name="text" type="java.lang.String" value="Filter"/>
    382                       </Properties>
    383                     </Component>
    384                     <Component class="javax.swing.JTextField" name="nonRefFilterTextField">
    385                     </Component>
    386                     <Container class="javax.swing.JPanel" name="jPanel8">
    387                       <Properties>
    388                         <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
    389                           <Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
    390                             <EtchetBorder/>
    391                           </Border>
    392                         </Property>
    393                       </Properties>
    394 
    395                       <Layout>
    396                         <DimensionLayout dim="0">
    397                           <Group type="103" groupAlignment="0" attributes="0">
    398                               <Group type="102" alignment="0" attributes="0">
    399                                   <EmptySpace max="-2" attributes="0"/>
    400                                   <Group type="103" groupAlignment="0" attributes="0">
    401                                       <Component id="nonRefReplaceRadio" alignment="0" min="-2" max="-2" attributes="0"/>
    402                                       <Component id="nonRefAddRadio" alignment="0" min="-2" max="-2" attributes="0"/>
    403                                       <Component id="nonRefRemoveRadio" alignment="0" min="-2" max="-2" attributes="0"/>
    404                                       <Component id="nonRefInSelectionRadio" alignment="0" min="-2" max="-2" attributes="0"/>
    405                                   </Group>
    406                                   <EmptySpace max="32767" attributes="0"/>
    407                               </Group>
    408                           </Group>
    409                         </DimensionLayout>
    410                         <DimensionLayout dim="1">
    411                           <Group type="103" groupAlignment="0" attributes="0">
    412                               <Group type="102" alignment="0" attributes="0">
    413                                   <EmptySpace max="32767" attributes="0"/>
    414                                   <Component id="nonRefReplaceRadio" min="-2" max="-2" attributes="0"/>
    415                                   <EmptySpace max="-2" attributes="0"/>
    416                                   <Component id="nonRefAddRadio" min="-2" max="-2" attributes="0"/>
    417                                   <EmptySpace max="-2" attributes="0"/>
    418                                   <Component id="nonRefRemoveRadio" min="-2" max="-2" attributes="0"/>
    419                                   <EmptySpace max="-2" attributes="0"/>
    420                                   <Component id="nonRefInSelectionRadio" min="-2" max="-2" attributes="0"/>
    421                               </Group>
    422                           </Group>
    423                         </DimensionLayout>
    424                       </Layout>
    425                       <SubComponents>
    426                         <Component class="javax.swing.JRadioButton" name="nonRefReplaceRadio">
    427                           <Properties>
    428                             <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
    429                               <ComponentRef name="nonRefSearchModeButtonGroup"/>
    430                             </Property>
    431                             <Property name="selected" type="boolean" value="true"/>
    432                             <Property name="text" type="java.lang.String" value="Replace selection"/>
    433                           </Properties>
    434                         </Component>
    435                         <Component class="javax.swing.JRadioButton" name="nonRefAddRadio">
    436                           <Properties>
    437                             <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
    438                               <ComponentRef name="nonRefSearchModeButtonGroup"/>
    439                             </Property>
    440                             <Property name="text" type="java.lang.String" value="Add to selection"/>
    441                           </Properties>
    442                           <Events>
    443                             <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="nonRefAddRadioActionPerformed"/>
    444                           </Events>
    445                         </Component>
    446                         <Component class="javax.swing.JRadioButton" name="nonRefRemoveRadio">
    447                           <Properties>
    448                             <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
    449                               <ComponentRef name="nonRefSearchModeButtonGroup"/>
    450                             </Property>
    451                             <Property name="text" type="java.lang.String" value="Remove from selection"/>
    452                           </Properties>
    453                         </Component>
    454                         <Component class="javax.swing.JRadioButton" name="nonRefInSelectionRadio">
    455                           <Properties>
    456                             <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
    457                               <ComponentRef name="nonRefSearchModeButtonGroup"/>
    458                             </Property>
    459                             <Property name="text" type="java.lang.String" value="Find in selection"/>
    460                           </Properties>
    461                         </Component>
    462                       </SubComponents>
    463                     </Container>
    464                     <Component class="javax.swing.JCheckBox" name="nonRefCaseSensitiveCheckBox">
    465                       <Properties>
    466                         <Property name="text" type="java.lang.String" value="Case sensitive"/>
    467                       </Properties>
    468                     </Component>
    469                     <Component class="javax.swing.JCheckBox" name="nonRefAllObjectsCheckBox">
    470                       <Properties>
    471                         <Property name="text" type="java.lang.String" value="All objects"/>
    472                       </Properties>
    473                     </Component>
    474                     <Component class="javax.swing.JCheckBox" name="nonRefRegExCheckBox">
    475                       <Properties>
    476                         <Property name="text" type="java.lang.String" value="Regular expression"/>
    477                       </Properties>
    478                     </Component>
    479                   </SubComponents>
    480                 </Container>
     273                <Component class="javax.swing.JButton" name="freezeTheirSelectionButton">
     274                  <Properties>
     275                    <Property name="text" type="java.lang.String" value="Freeze Selection"/>
     276                  </Properties>
     277                  <Events>
     278                    <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="freezeTheirSelectionButtonActionPerformed"/>
     279                  </Events>
     280                </Component>
     281                <Component class="javax.swing.JButton" name="restoreTheirSetButton">
     282                  <Properties>
     283                    <Property name="text" type="java.lang.String" value="Restore Selection"/>
     284                  </Properties>
     285                  <Events>
     286                    <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="restoreTheirSetButtonActionPerformed"/>
     287                  </Events>
     288                </Component>
     289                <Component class="javax.swing.JLabel" name="jLabel5">
     290                  <Properties>
     291                    <Property name="text" type="java.lang.String" value="Relations"/>
     292                  </Properties>
     293                </Component>
     294                <Component class="javax.swing.JLabel" name="jLabel6">
     295                  <Properties>
     296                    <Property name="text" type="java.lang.String" value="Layer"/>
     297                  </Properties>
     298                </Component>
     299                <Component class="javax.swing.JLabel" name="jLabel7">
     300                  <Properties>
     301                    <Property name="text" type="java.lang.String" value="Nodes"/>
     302                  </Properties>
     303                </Component>
     304                <Component class="javax.swing.JLabel" name="jLabel9">
     305                  <Properties>
     306                    <Property name="text" type="java.lang.String" value="Ways"/>
     307                  </Properties>
     308                </Component>
     309                <Component class="javax.swing.JLabel" name="theirNodeCountLabel">
     310                  <Properties>
     311                    <Property name="text" type="java.lang.String" value="0"/>
     312                  </Properties>
     313                </Component>
     314                <Component class="javax.swing.JLabel" name="theirLayerLabel">
     315                  <Properties>
     316                    <Property name="text" type="java.lang.String" value="(invalid)"/>
     317                  </Properties>
     318                </Component>
     319                <Component class="javax.swing.JLabel" name="theirWayCountLabel">
     320                  <Properties>
     321                    <Property name="text" type="java.lang.String" value="0"/>
     322                  </Properties>
     323                </Component>
     324                <Component class="javax.swing.JLabel" name="theirRelationCountLabel">
     325                  <Properties>
     326                    <Property name="text" type="java.lang.String" value="0"/>
     327                  </Properties>
     328                </Component>
    481329              </SubComponents>
    482330            </Container>
     
    513361              <Group type="103" groupAlignment="0" attributes="0">
    514362                  <Group type="102" alignment="1" attributes="0">
    515                       <EmptySpace pref="254" max="32767" attributes="0"/>
     363                      <EmptySpace pref="578" max="32767" attributes="0"/>
    516364                      <Component id="criteriaTabConflateButton" min="-2" max="-2" attributes="0"/>
    517365                      <EmptySpace max="-2" attributes="0"/>
     366                  </Group>
     367                  <Group type="102" alignment="0" attributes="0">
     368                      <EmptySpace max="-2" attributes="0"/>
     369                      <Component id="jPanel2" min="-2" max="-2" attributes="0"/>
     370                      <EmptySpace pref="292" max="32767" attributes="0"/>
    518371                  </Group>
    519372              </Group>
     
    522375              <Group type="103" groupAlignment="0" attributes="0">
    523376                  <Group type="102" alignment="1" attributes="0">
    524                       <EmptySpace pref="404" max="32767" attributes="0"/>
     377                      <EmptySpace max="-2" attributes="0"/>
     378                      <Component id="jPanel2" min="-2" max="-2" attributes="0"/>
     379                      <EmptySpace pref="217" max="32767" attributes="0"/>
    525380                      <Component id="criteriaTabConflateButton" min="-2" max="-2" attributes="0"/>
    526381                      <EmptySpace max="-2" attributes="0"/>
     
    539394              </Events>
    540395            </Component>
     396            <Container class="javax.swing.JPanel" name="jPanel2">
     397              <Properties>
     398                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
     399                  <Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
     400                    <EtchetBorder/>
     401                  </Border>
     402                </Property>
     403              </Properties>
     404
     405              <Layout>
     406                <DimensionLayout dim="0">
     407                  <Group type="103" groupAlignment="0" attributes="0">
     408                      <Group type="102" alignment="0" attributes="0">
     409                          <EmptySpace max="-2" attributes="0"/>
     410                          <Component id="jCheckBox1" min="-2" max="-2" attributes="0"/>
     411                          <EmptySpace pref="282" max="32767" attributes="0"/>
     412                      </Group>
     413                  </Group>
     414                </DimensionLayout>
     415                <DimensionLayout dim="1">
     416                  <Group type="103" groupAlignment="0" attributes="0">
     417                      <Group type="102" alignment="0" attributes="0">
     418                          <EmptySpace max="-2" attributes="0"/>
     419                          <Component id="jCheckBox1" min="-2" max="-2" attributes="0"/>
     420                          <EmptySpace pref="192" max="32767" attributes="0"/>
     421                      </Group>
     422                  </Group>
     423                </DimensionLayout>
     424              </Layout>
     425              <SubComponents>
     426                <Component class="javax.swing.JCheckBox" name="jCheckBox1">
     427                  <Properties>
     428                    <Property name="selected" type="boolean" value="true"/>
     429                    <Property name="text" type="java.lang.String" value="Distance"/>
     430                  </Properties>
     431                  <Events>
     432                    <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jCheckBox1ActionPerformed"/>
     433                  </Events>
     434                </Component>
     435              </SubComponents>
     436            </Container>
    541437          </SubComponents>
    542438        </Container>
    543         <Container class="javax.swing.JPanel" name="jPanel1">
     439        <Container class="javax.swing.JPanel" name="resultsPanel">
    544440          <Constraints>
    545441            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
     
    550446          </Constraints>
    551447
    552           <Layout>
    553             <DimensionLayout dim="0">
    554               <Group type="103" groupAlignment="0" attributes="0">
    555                   <EmptySpace min="0" pref="337" max="32767" attributes="0"/>
    556               </Group>
    557             </DimensionLayout>
    558             <DimensionLayout dim="1">
    559               <Group type="103" groupAlignment="0" attributes="0">
    560                   <EmptySpace min="0" pref="438" max="32767" attributes="0"/>
    561               </Group>
    562             </DimensionLayout>
     448          <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
     449            <Property name="axis" type="int" value="3"/>
    563450          </Layout>
     451          <SubComponents>
     452            <Container class="javax.swing.JScrollPane" name="jScrollPane1">
     453              <AuxValues>
     454                <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
     455              </AuxValues>
     456
     457              <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
     458              <SubComponents>
     459                <Component class="javax.swing.JTable" name="resultsTable">
     460                  <Properties>
     461                    <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
     462                      <Table columnCount="5" rowCount="4">
     463                        <Column editable="true" title="Mine" type="java.lang.Object"/>
     464                        <Column editable="true" title="Theirs" type="java.lang.Object"/>
     465                        <Column editable="true" title="Distance (m)" type="java.lang.Object"/>
     466                        <Column editable="true" title="Cost" type="java.lang.Object"/>
     467                        <Column editable="true" title="Tags" type="java.lang.Object"/>
     468                      </Table>
     469                    </Property>
     470                    <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
     471                      <JTableSelectionModel selectionMode="2"/>
     472                    </Property>
     473                  </Properties>
     474                </Component>
     475              </SubComponents>
     476            </Container>
     477            <Container class="javax.swing.JPanel" name="jPanel1">
     478              <Properties>
     479                <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
     480                  <Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
     481                    <EtchetBorder/>
     482                  </Border>
     483                </Property>
     484              </Properties>
     485
     486              <Layout>
     487                <DimensionLayout dim="0">
     488                  <Group type="103" groupAlignment="0" attributes="0">
     489                      <Group type="102" alignment="0" attributes="0">
     490                          <EmptySpace max="-2" attributes="0"/>
     491                          <Component id="jLabel8" min="-2" max="-2" attributes="0"/>
     492                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
     493                          <Component id="useMyTagsButton" min="-2" max="-2" attributes="0"/>
     494                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
     495                          <Component id="useTheirTagsButton" min="-2" max="-2" attributes="0"/>
     496                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
     497                          <Component id="jButton1" min="-2" max="-2" attributes="0"/>
     498                          <EmptySpace pref="300" max="32767" attributes="0"/>
     499                      </Group>
     500                  </Group>
     501                </DimensionLayout>
     502                <DimensionLayout dim="1">
     503                  <Group type="103" groupAlignment="0" attributes="0">
     504                      <Group type="102" alignment="0" attributes="0">
     505                          <EmptySpace max="-2" attributes="0"/>
     506                          <Group type="103" groupAlignment="3" attributes="0">
     507                              <Component id="jLabel8" alignment="3" min="-2" max="-2" attributes="0"/>
     508                              <Component id="useMyTagsButton" alignment="3" min="-2" max="-2" attributes="0"/>
     509                              <Component id="useTheirTagsButton" alignment="3" min="-2" max="-2" attributes="0"/>
     510                              <Component id="jButton1" alignment="3" min="-2" max="-2" attributes="0"/>
     511                          </Group>
     512                          <EmptySpace max="32767" attributes="0"/>
     513                      </Group>
     514                  </Group>
     515                </DimensionLayout>
     516              </Layout>
     517              <SubComponents>
     518                <Component class="javax.swing.JButton" name="useMyTagsButton">
     519                  <Properties>
     520                    <Property name="text" type="java.lang.String" value="My Tags"/>
     521                  </Properties>
     522                  <Events>
     523                    <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="useMyTagsButtonActionPerformed"/>
     524                  </Events>
     525                </Component>
     526                <Component class="javax.swing.JLabel" name="jLabel8">
     527                  <Properties>
     528                    <Property name="text" type="java.lang.String" value="Resolve using:"/>
     529                  </Properties>
     530                </Component>
     531                <Component class="javax.swing.JButton" name="useTheirTagsButton">
     532                  <Properties>
     533                    <Property name="text" type="java.lang.String" value="Their Tags"/>
     534                  </Properties>
     535                </Component>
     536                <Component class="javax.swing.JButton" name="jButton1">
     537                  <Properties>
     538                    <Property name="text" type="java.lang.String" value="Not a match"/>
     539                    <Property name="enabled" type="boolean" value="false"/>
     540                  </Properties>
     541                </Component>
     542              </SubComponents>
     543            </Container>
     544            <Container class="javax.swing.JPanel" name="tagMergerPlaceholderPanel">
     545              <Properties>
     546                <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
     547                  <Dimension value="[661, 250]"/>
     548                </Property>
     549              </Properties>
     550
     551              <Layout>
     552                <DimensionLayout dim="0">
     553                  <Group type="103" groupAlignment="0" attributes="0">
     554                      <EmptySpace min="0" pref="661" max="32767" attributes="0"/>
     555                  </Group>
     556                </DimensionLayout>
     557                <DimensionLayout dim="1">
     558                  <Group type="103" groupAlignment="0" attributes="0">
     559                      <EmptySpace min="0" pref="150" max="32767" attributes="0"/>
     560                  </Group>
     561                </DimensionLayout>
     562              </Layout>
     563            </Container>
     564            <Component class="javax.swing.JButton" name="resolveButton">
     565              <Properties>
     566                <Property name="text" type="java.lang.String" value="Resolve"/>
     567              </Properties>
     568              <Events>
     569                <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="resolveButtonActionPerformed"/>
     570              </Events>
     571            </Component>
     572          </SubComponents>
    564573        </Container>
    565574      </SubComponents>
  • applications/editors/josm/plugins/conflation/src/org/openstreetmap/josm/plugins/conflation/ConflationOptionsPanel.java

    r25942 r26023  
    1010
    1111import java.awt.Component;
     12import java.util.ArrayList;
     13import java.util.HashSet;
    1214
    1315import java.util.List;
     16import java.util.Set;
    1417import javax.swing.DefaultListCellRenderer;
    1518import javax.swing.Icon;
    1619import javax.swing.JLabel;
    1720import javax.swing.JList;
    18 import org.openstreetmap.josm.actions.search.SearchAction;
    19 import org.openstreetmap.josm.actions.search.SearchAction.SearchSetting;
     21import javax.swing.JOptionPane;
     22import javax.swing.JTable;
     23import javax.swing.ListSelectionModel;
     24import javax.swing.event.ListSelectionEvent;
     25import javax.swing.event.ListSelectionListener;
     26import javax.swing.table.AbstractTableModel;
     27import javax.swing.table.TableCellRenderer;
     28
     29import static org.openstreetmap.josm.tools.I18n.tr;
     30import org.openstreetmap.josm.Main;
     31import org.openstreetmap.josm.command.Command;
     32import org.openstreetmap.josm.data.conflict.Conflict;
     33import org.openstreetmap.josm.data.conflict.ConflictCollection;
     34import org.openstreetmap.josm.data.conflict.IConflictListener;
     35import org.openstreetmap.josm.data.coor.EastNorth;
     36import org.openstreetmap.josm.data.coor.LatLon;
     37import org.openstreetmap.josm.data.osm.DataSet;
     38import org.openstreetmap.josm.data.osm.OsmPrimitive;
     39import org.openstreetmap.josm.data.osm.TagCollection;
     40import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
     41import org.openstreetmap.josm.gui.conflict.pair.ConflictResolver;
    2042import org.openstreetmap.josm.gui.layer.Layer;
    2143import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     
    2547 * @author Josh
    2648 */
    27 public class ConflationOptionsPanel extends javax.swing.JPanel {
     49public class ConflationOptionsPanel extends javax.swing.JPanel implements IConflictListener {
    2850    ConflationOptionsDialog dlg = null;
     51    ConflationLayer conflationLayer = null;
     52    DataSet myDataSet = null;
     53    DataSet theirDataSet = null;
     54    ArrayList<OsmPrimitive> mySelection = null;
     55    ArrayList<OsmPrimitive> theirSelection = null;
     56    OsmDataLayer myLayer = null;
     57    OsmDataLayer theirLayer = null;
     58    ConflictCollection conflicts = null;
     59    ConflictResolver conflictResolver;
     60    OsmPrimitive[][] pairs;
     61    int[][] assignment;
     62    MatchTableModel tableModel;
    2963
    3064    /** Creates new form ConflationPanel */
     
    3266        initComponents();
    3367
     68        // add selection handler, to change ConflictResolver contents and center/zoom view
     69        resultsTable.getSelectionModel().addListSelectionListener(
     70                new MatchListSelectionHandler());
     71        resultsTable.getColumnModel().getSelectionModel().addListSelectionListener(
     72                new MatchListSelectionHandler());
     73
     74        // FIXME: doesn't work right now
     75        ColorTableCellRenderer cr = new ColorTableCellRenderer("Tags");
     76        resultsTable.getColumnModel().getColumn(4).setCellRenderer(cr);
     77
     78        // replace dummy panel with conflictResolver
     79        conflictResolver = new ConflictResolver();
     80        for (int i = 0; i < resultsPanel.getComponentCount(); i++) {
     81            if (resultsPanel.getComponent(i) == tagMergerPlaceholderPanel) {
     82                resultsPanel.add(conflictResolver, i);
     83                resultsPanel.remove(tagMergerPlaceholderPanel);
     84                break;
     85            }
     86        }
     87        resultsPanel.validate();
     88
    3489        this.dlg = dlg;
    3590
     91        conflicts = new ConflictCollection();
     92
    3693        // set layer names to comboboxes
    37         if (layers != null && layers.size() > 0) {
    38             refLayerComboBox.setModel(new javax.swing.DefaultComboBoxModel(layers.toArray()));
    39             refLayerComboBox.setRenderer(new LayerListCellRenderer());
    40             nonRefLayerComboBox.setModel(new javax.swing.DefaultComboBoxModel(layers.toArray()));
    41             nonRefLayerComboBox.setRenderer(new LayerListCellRenderer());
    42         }
     94//        if (layers != null && layers.size() > 0) {
     95//            refLayerComboBox.setModel(new javax.swing.DefaultComboBoxModel(layers.toArray()));
     96//            refLayerComboBox.setRenderer(new LayerListCellRenderer());
     97//            nonRefLayerComboBox.setModel(new javax.swing.DefaultComboBoxModel(layers.toArray()));
     98//            nonRefLayerComboBox.setRenderer(new LayerListCellRenderer());
     99//        }
    43100
    44101    }
     
    53110    private void initComponents() {
    54111
    55         refSearchModeButtonGroup = new javax.swing.ButtonGroup();
    56         nonRefSearchModeButtonGroup = new javax.swing.ButtonGroup();
    57112        resultsTabPanel = new javax.swing.JTabbedPane();
    58113        objectTabPanel = new javax.swing.JPanel();
    59114        refSetPanel = new javax.swing.JPanel();
    60         jPanel4 = new javax.swing.JPanel();
     115        freezeMySetButton = new javax.swing.JButton();
     116        restoreMySetButton = new javax.swing.JButton();
    61117        jLabel1 = new javax.swing.JLabel();
    62         refLayerComboBox = new javax.swing.JComboBox();
    63118        jLabel2 = new javax.swing.JLabel();
    64         refFilterTextField = new javax.swing.JTextField();
    65         jPanel5 = new javax.swing.JPanel();
    66         refReplaceRadio = new javax.swing.JRadioButton();
    67         refAddRadio = new javax.swing.JRadioButton();
    68         refRemoveRadio = new javax.swing.JRadioButton();
    69         refInSelectionRadio = new javax.swing.JRadioButton();
    70         refCaseSensitiveCheckBox = new javax.swing.JCheckBox();
    71         refAllObjectsCheckBox = new javax.swing.JCheckBox();
    72         refRegExCheckBox = new javax.swing.JCheckBox();
     119        jLabel3 = new javax.swing.JLabel();
     120        jLabel4 = new javax.swing.JLabel();
     121        myRelationCountLabel = new javax.swing.JLabel();
     122        myWayCountLabel = new javax.swing.JLabel();
     123        myNodeCountLabel = new javax.swing.JLabel();
     124        myLayerLabel = new javax.swing.JLabel();
    73125        nonRefSetPanel = new javax.swing.JPanel();
    74         jPanel7 = new javax.swing.JPanel();
    75         jLabel3 = new javax.swing.JLabel();
    76         nonRefLayerComboBox = new javax.swing.JComboBox();
    77         jLabel4 = new javax.swing.JLabel();
    78         nonRefFilterTextField = new javax.swing.JTextField();
    79         jPanel8 = new javax.swing.JPanel();
    80         nonRefReplaceRadio = new javax.swing.JRadioButton();
    81         nonRefAddRadio = new javax.swing.JRadioButton();
    82         nonRefRemoveRadio = new javax.swing.JRadioButton();
    83         nonRefInSelectionRadio = new javax.swing.JRadioButton();
    84         nonRefCaseSensitiveCheckBox = new javax.swing.JCheckBox();
    85         nonRefAllObjectsCheckBox = new javax.swing.JCheckBox();
    86         nonRefRegExCheckBox = new javax.swing.JCheckBox();
     126        freezeTheirSelectionButton = new javax.swing.JButton();
     127        restoreTheirSetButton = new javax.swing.JButton();
     128        jLabel5 = new javax.swing.JLabel();
     129        jLabel6 = new javax.swing.JLabel();
     130        jLabel7 = new javax.swing.JLabel();
     131        jLabel9 = new javax.swing.JLabel();
     132        theirNodeCountLabel = new javax.swing.JLabel();
     133        theirLayerLabel = new javax.swing.JLabel();
     134        theirWayCountLabel = new javax.swing.JLabel();
     135        theirRelationCountLabel = new javax.swing.JLabel();
    87136        objectTabCancelButton = new javax.swing.JButton();
    88137        objectTabNextButton = new javax.swing.JButton();
    89138        criteriaTabPanel = new javax.swing.JPanel();
    90139        criteriaTabConflateButton = new javax.swing.JButton();
     140        jPanel2 = new javax.swing.JPanel();
     141        jCheckBox1 = new javax.swing.JCheckBox();
     142        resultsPanel = new javax.swing.JPanel();
     143        jScrollPane1 = new javax.swing.JScrollPane();
     144        resultsTable = new javax.swing.JTable();
    91145        jPanel1 = new javax.swing.JPanel();
     146        useMyTagsButton = new javax.swing.JButton();
     147        jLabel8 = new javax.swing.JLabel();
     148        useTheirTagsButton = new javax.swing.JButton();
     149        jButton1 = new javax.swing.JButton();
     150        tagMergerPlaceholderPanel = new javax.swing.JPanel();
     151        resolveButton = new javax.swing.JButton();
    92152
    93153        setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.LINE_AXIS));
    94154
    95         refSetPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Reference Set"));
    96 
    97         jLabel1.setText("Layer");
    98 
    99         refLayerComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
    100 
    101         jLabel2.setText("Filter");
    102 
    103         jPanel5.setBorder(javax.swing.BorderFactory.createEtchedBorder());
    104 
    105         refSearchModeButtonGroup.add(refReplaceRadio);
    106         refReplaceRadio.setSelected(true);
    107         refReplaceRadio.setText("Replace selection");
    108 
    109         refSearchModeButtonGroup.add(refAddRadio);
    110         refAddRadio.setText("Add to selection");
    111         refAddRadio.addActionListener(new java.awt.event.ActionListener() {
    112             public void actionPerformed(java.awt.event.ActionEvent evt) {
    113                 refAddRadioActionPerformed(evt);
    114             }
    115         });
    116 
    117         refSearchModeButtonGroup.add(refRemoveRadio);
    118         refRemoveRadio.setText("Remove from selection");
    119 
    120         refSearchModeButtonGroup.add(refInSelectionRadio);
    121         refInSelectionRadio.setText("Find in selection");
    122 
    123         javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
    124         jPanel5.setLayout(jPanel5Layout);
    125         jPanel5Layout.setHorizontalGroup(
    126             jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    127             .addGroup(jPanel5Layout.createSequentialGroup()
    128                 .addContainerGap()
    129                 .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    130                     .addComponent(refReplaceRadio)
    131                     .addComponent(refAddRadio)
    132                     .addComponent(refRemoveRadio)
    133                     .addComponent(refInSelectionRadio))
    134                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
    135         );
    136         jPanel5Layout.setVerticalGroup(
    137             jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    138             .addGroup(jPanel5Layout.createSequentialGroup()
    139                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    140                 .addComponent(refReplaceRadio)
    141                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    142                 .addComponent(refAddRadio)
    143                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    144                 .addComponent(refRemoveRadio)
    145                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    146                 .addComponent(refInSelectionRadio))
    147         );
    148 
    149         refCaseSensitiveCheckBox.setText("Case sensitive");
    150 
    151         refAllObjectsCheckBox.setText("All objects");
    152 
    153         refRegExCheckBox.setText("Regular expression");
    154 
    155         javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
    156         jPanel4.setLayout(jPanel4Layout);
    157         jPanel4Layout.setHorizontalGroup(
    158             jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    159             .addGroup(jPanel4Layout.createSequentialGroup()
    160                 .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    161                     .addGroup(jPanel4Layout.createSequentialGroup()
    162                         .addContainerGap()
    163                         .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    164                             .addComponent(jLabel1)
    165                             .addComponent(jLabel2))
    166                         .addGap(18, 18, 18)
    167                         .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    168                             .addComponent(refLayerComboBox, 0, 246, Short.MAX_VALUE)
    169                             .addComponent(refFilterTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 246, Short.MAX_VALUE)))
    170                     .addGroup(jPanel4Layout.createSequentialGroup()
    171                         .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
    172                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
    173                         .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    174                             .addComponent(refCaseSensitiveCheckBox)
    175                             .addComponent(refAllObjectsCheckBox)
    176                             .addComponent(refRegExCheckBox))))
    177                 .addContainerGap())
    178         );
    179         jPanel4Layout.setVerticalGroup(
    180             jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    181             .addGroup(jPanel4Layout.createSequentialGroup()
    182                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    183                 .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
    184                     .addComponent(jLabel1)
    185                     .addComponent(refLayerComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
    186                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    187                 .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
    188                     .addComponent(jLabel2)
    189                     .addComponent(refFilterTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
    190                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    191                 .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    192                     .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
    193                     .addGroup(jPanel4Layout.createSequentialGroup()
    194                         .addComponent(refCaseSensitiveCheckBox)
    195                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    196                         .addComponent(refAllObjectsCheckBox)
    197                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    198                         .addComponent(refRegExCheckBox))))
    199         );
     155        refSetPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("My Set"));
     156
     157        freezeMySetButton.setText("Freeze Selection");
     158        freezeMySetButton.addActionListener(new java.awt.event.ActionListener() {
     159            public void actionPerformed(java.awt.event.ActionEvent evt) {
     160                freezeMySetButtonActionPerformed(evt);
     161            }
     162        });
     163
     164        restoreMySetButton.setText("Restore Selection");
     165        restoreMySetButton.addActionListener(new java.awt.event.ActionListener() {
     166            public void actionPerformed(java.awt.event.ActionEvent evt) {
     167                restoreMySetButtonActionPerformed(evt);
     168            }
     169        });
     170
     171        jLabel1.setText("Nodes");
     172
     173        jLabel2.setText("Layer");
     174
     175        jLabel3.setText("Ways");
     176
     177        jLabel4.setText("Relations");
     178
     179        myRelationCountLabel.setText("0");
     180
     181        myWayCountLabel.setText("0");
     182
     183        myNodeCountLabel.setText("0");
     184
     185        myLayerLabel.setText("(invalid)");
    200186
    201187        javax.swing.GroupLayout refSetPanelLayout = new javax.swing.GroupLayout(refSetPanel);
     
    203189        refSetPanelLayout.setHorizontalGroup(
    204190            refSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    205             .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
     191            .addGroup(refSetPanelLayout.createSequentialGroup()
     192                .addContainerGap()
     193                .addGroup(refSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
     194                    .addGroup(refSetPanelLayout.createSequentialGroup()
     195                        .addComponent(freezeMySetButton)
     196                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 387, Short.MAX_VALUE)
     197                        .addComponent(restoreMySetButton))
     198                    .addGroup(refSetPanelLayout.createSequentialGroup()
     199                        .addGroup(refSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
     200                            .addComponent(jLabel4)
     201                            .addComponent(jLabel3)
     202                            .addComponent(jLabel1)
     203                            .addComponent(jLabel2))
     204                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
     205                        .addGroup(refSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
     206                            .addComponent(myLayerLabel)
     207                            .addComponent(myNodeCountLabel)
     208                            .addComponent(myWayCountLabel)
     209                            .addComponent(myRelationCountLabel))))
     210                .addContainerGap())
    206211        );
    207212        refSetPanelLayout.setVerticalGroup(
    208213            refSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    209             .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
    210         );
    211 
    212         nonRefSetPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Non-Reference Set"));
    213 
    214         jLabel3.setText("Layer");
    215 
    216         nonRefLayerComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
    217 
    218         jLabel4.setText("Filter");
    219 
    220         jPanel8.setBorder(javax.swing.BorderFactory.createEtchedBorder());
    221 
    222         nonRefSearchModeButtonGroup.add(nonRefReplaceRadio);
    223         nonRefReplaceRadio.setSelected(true);
    224         nonRefReplaceRadio.setText("Replace selection");
    225 
    226         nonRefSearchModeButtonGroup.add(nonRefAddRadio);
    227         nonRefAddRadio.setText("Add to selection");
    228         nonRefAddRadio.addActionListener(new java.awt.event.ActionListener() {
    229             public void actionPerformed(java.awt.event.ActionEvent evt) {
    230                 nonRefAddRadioActionPerformed(evt);
    231             }
    232         });
    233 
    234         nonRefSearchModeButtonGroup.add(nonRefRemoveRadio);
    235         nonRefRemoveRadio.setText("Remove from selection");
    236 
    237         nonRefSearchModeButtonGroup.add(nonRefInSelectionRadio);
    238         nonRefInSelectionRadio.setText("Find in selection");
    239 
    240         javax.swing.GroupLayout jPanel8Layout = new javax.swing.GroupLayout(jPanel8);
    241         jPanel8.setLayout(jPanel8Layout);
    242         jPanel8Layout.setHorizontalGroup(
    243             jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    244             .addGroup(jPanel8Layout.createSequentialGroup()
    245                 .addContainerGap()
    246                 .addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    247                     .addComponent(nonRefReplaceRadio)
    248                     .addComponent(nonRefAddRadio)
    249                     .addComponent(nonRefRemoveRadio)
    250                     .addComponent(nonRefInSelectionRadio))
    251                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
    252         );
    253         jPanel8Layout.setVerticalGroup(
    254             jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    255             .addGroup(jPanel8Layout.createSequentialGroup()
    256                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    257                 .addComponent(nonRefReplaceRadio)
    258                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    259                 .addComponent(nonRefAddRadio)
    260                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    261                 .addComponent(nonRefRemoveRadio)
    262                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    263                 .addComponent(nonRefInSelectionRadio))
    264         );
    265 
    266         nonRefCaseSensitiveCheckBox.setText("Case sensitive");
    267 
    268         nonRefAllObjectsCheckBox.setText("All objects");
    269 
    270         nonRefRegExCheckBox.setText("Regular expression");
    271 
    272         javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7);
    273         jPanel7.setLayout(jPanel7Layout);
    274         jPanel7Layout.setHorizontalGroup(
    275             jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    276             .addGroup(jPanel7Layout.createSequentialGroup()
    277                 .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    278                     .addGroup(jPanel7Layout.createSequentialGroup()
    279                         .addContainerGap()
    280                         .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    281                             .addComponent(jLabel3)
    282                             .addComponent(jLabel4))
    283                         .addGap(18, 18, 18)
    284                         .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    285                             .addComponent(nonRefLayerComboBox, 0, 246, Short.MAX_VALUE)
    286                             .addComponent(nonRefFilterTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 246, Short.MAX_VALUE)))
    287                     .addGroup(jPanel7Layout.createSequentialGroup()
    288                         .addComponent(jPanel8, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
    289                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
    290                         .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    291                             .addComponent(nonRefCaseSensitiveCheckBox)
    292                             .addComponent(nonRefAllObjectsCheckBox)
    293                             .addComponent(nonRefRegExCheckBox))))
    294                 .addContainerGap())
    295         );
    296         jPanel7Layout.setVerticalGroup(
    297             jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    298             .addGroup(jPanel7Layout.createSequentialGroup()
    299                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    300                 .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
     214            .addGroup(refSetPanelLayout.createSequentialGroup()
     215                .addContainerGap()
     216                .addGroup(refSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
     217                    .addComponent(freezeMySetButton)
     218                    .addComponent(restoreMySetButton))
     219                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
     220                .addGroup(refSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
     221                    .addComponent(jLabel2)
     222                    .addComponent(myLayerLabel))
     223                .addGap(11, 11, 11)
     224                .addGroup(refSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
     225                    .addComponent(jLabel1)
     226                    .addComponent(myNodeCountLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
     227                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
     228                .addGroup(refSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
    301229                    .addComponent(jLabel3)
    302                     .addComponent(nonRefLayerComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
    303                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    304                 .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
     230                    .addComponent(myWayCountLabel))
     231                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
     232                .addGroup(refSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
    305233                    .addComponent(jLabel4)
    306                     .addComponent(nonRefFilterTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
    307                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    308                 .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    309                     .addComponent(jPanel8, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
    310                     .addGroup(jPanel7Layout.createSequentialGroup()
    311                         .addComponent(nonRefCaseSensitiveCheckBox)
    312                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    313                         .addComponent(nonRefAllObjectsCheckBox)
    314                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    315                         .addComponent(nonRefRegExCheckBox))))
    316         );
     234                    .addComponent(myRelationCountLabel))
     235                .addContainerGap(38, Short.MAX_VALUE))
     236        );
     237
     238        nonRefSetPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Their Set"));
     239
     240        freezeTheirSelectionButton.setText("Freeze Selection");
     241        freezeTheirSelectionButton.addActionListener(new java.awt.event.ActionListener() {
     242            public void actionPerformed(java.awt.event.ActionEvent evt) {
     243                freezeTheirSelectionButtonActionPerformed(evt);
     244            }
     245        });
     246
     247        restoreTheirSetButton.setText("Restore Selection");
     248        restoreTheirSetButton.addActionListener(new java.awt.event.ActionListener() {
     249            public void actionPerformed(java.awt.event.ActionEvent evt) {
     250                restoreTheirSetButtonActionPerformed(evt);
     251            }
     252        });
     253
     254        jLabel5.setText("Relations");
     255
     256        jLabel6.setText("Layer");
     257
     258        jLabel7.setText("Nodes");
     259
     260        jLabel9.setText("Ways");
     261
     262        theirNodeCountLabel.setText("0");
     263
     264        theirLayerLabel.setText("(invalid)");
     265
     266        theirWayCountLabel.setText("0");
     267
     268        theirRelationCountLabel.setText("0");
    317269
    318270        javax.swing.GroupLayout nonRefSetPanelLayout = new javax.swing.GroupLayout(nonRefSetPanel);
     
    320272        nonRefSetPanelLayout.setHorizontalGroup(
    321273            nonRefSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    322             .addComponent(jPanel7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
     274            .addGroup(nonRefSetPanelLayout.createSequentialGroup()
     275                .addContainerGap()
     276                .addGroup(nonRefSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
     277                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, nonRefSetPanelLayout.createSequentialGroup()
     278                        .addComponent(freezeTheirSelectionButton)
     279                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 387, Short.MAX_VALUE)
     280                        .addComponent(restoreTheirSetButton))
     281                    .addGroup(nonRefSetPanelLayout.createSequentialGroup()
     282                        .addGroup(nonRefSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
     283                            .addComponent(jLabel5)
     284                            .addComponent(jLabel9)
     285                            .addComponent(jLabel7)
     286                            .addComponent(jLabel6))
     287                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
     288                        .addGroup(nonRefSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
     289                            .addComponent(theirLayerLabel)
     290                            .addComponent(theirNodeCountLabel)
     291                            .addComponent(theirWayCountLabel)
     292                            .addComponent(theirRelationCountLabel))))
     293                .addContainerGap())
    323294        );
    324295        nonRefSetPanelLayout.setVerticalGroup(
    325296            nonRefSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    326             .addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
     297            .addGroup(nonRefSetPanelLayout.createSequentialGroup()
     298                .addContainerGap()
     299                .addGroup(nonRefSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
     300                    .addComponent(freezeTheirSelectionButton)
     301                    .addComponent(restoreTheirSetButton))
     302                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
     303                .addGroup(nonRefSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
     304                    .addComponent(jLabel6)
     305                    .addComponent(theirLayerLabel))
     306                .addGap(11, 11, 11)
     307                .addGroup(nonRefSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
     308                    .addComponent(jLabel7)
     309                    .addComponent(theirNodeCountLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
     310                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
     311                .addGroup(nonRefSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
     312                    .addComponent(jLabel9)
     313                    .addComponent(theirWayCountLabel))
     314                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
     315                .addGroup(nonRefSetPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
     316                    .addComponent(jLabel5)
     317                    .addComponent(theirRelationCountLabel))
     318                .addContainerGap(32, Short.MAX_VALUE))
    327319        );
    328320
     
    380372        });
    381373
     374        jPanel2.setBorder(javax.swing.BorderFactory.createEtchedBorder());
     375
     376        jCheckBox1.setSelected(true);
     377        jCheckBox1.setText("Distance");
     378        jCheckBox1.addActionListener(new java.awt.event.ActionListener() {
     379            public void actionPerformed(java.awt.event.ActionEvent evt) {
     380                jCheckBox1ActionPerformed(evt);
     381            }
     382        });
     383
     384        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
     385        jPanel2.setLayout(jPanel2Layout);
     386        jPanel2Layout.setHorizontalGroup(
     387            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
     388            .addGroup(jPanel2Layout.createSequentialGroup()
     389                .addContainerGap()
     390                .addComponent(jCheckBox1)
     391                .addContainerGap(282, Short.MAX_VALUE))
     392        );
     393        jPanel2Layout.setVerticalGroup(
     394            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
     395            .addGroup(jPanel2Layout.createSequentialGroup()
     396                .addContainerGap()
     397                .addComponent(jCheckBox1)
     398                .addContainerGap(192, Short.MAX_VALUE))
     399        );
     400
    382401        javax.swing.GroupLayout criteriaTabPanelLayout = new javax.swing.GroupLayout(criteriaTabPanel);
    383402        criteriaTabPanel.setLayout(criteriaTabPanelLayout);
     
    385404            criteriaTabPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    386405            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, criteriaTabPanelLayout.createSequentialGroup()
    387                 .addContainerGap(254, Short.MAX_VALUE)
     406                .addContainerGap(578, Short.MAX_VALUE)
    388407                .addComponent(criteriaTabConflateButton)
    389408                .addContainerGap())
     409            .addGroup(criteriaTabPanelLayout.createSequentialGroup()
     410                .addContainerGap()
     411                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
     412                .addContainerGap(292, Short.MAX_VALUE))
    390413        );
    391414        criteriaTabPanelLayout.setVerticalGroup(
    392415            criteriaTabPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    393416            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, criteriaTabPanelLayout.createSequentialGroup()
    394                 .addContainerGap(404, Short.MAX_VALUE)
     417                .addContainerGap()
     418                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
     419                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 217, Short.MAX_VALUE)
    395420                .addComponent(criteriaTabConflateButton)
    396421                .addContainerGap())
     
    398423
    399424        resultsTabPanel.addTab("Matching criteria", criteriaTabPanel);
     425
     426        resultsPanel.setLayout(new javax.swing.BoxLayout(resultsPanel, javax.swing.BoxLayout.PAGE_AXIS));
     427
     428        resultsTable.setModel(new javax.swing.table.DefaultTableModel(
     429            new Object [][] {
     430                {null, null, null, null, null},
     431                {null, null, null, null, null},
     432                {null, null, null, null, null},
     433                {null, null, null, null, null}
     434            },
     435            new String [] {
     436                "Mine", "Theirs", "Distance (m)", "Cost", "Tags"
     437            }
     438        ));
     439        resultsTable.setSelectionMode(javax.swing.ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
     440        jScrollPane1.setViewportView(resultsTable);
     441
     442        resultsPanel.add(jScrollPane1);
     443
     444        jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
     445
     446        useMyTagsButton.setText("My Tags");
     447        useMyTagsButton.addActionListener(new java.awt.event.ActionListener() {
     448            public void actionPerformed(java.awt.event.ActionEvent evt) {
     449                useMyTagsButtonActionPerformed(evt);
     450            }
     451        });
     452
     453        jLabel8.setText("Resolve using:");
     454
     455        useTheirTagsButton.setText("Their Tags");
     456
     457        jButton1.setText("Not a match");
     458        jButton1.setEnabled(false);
    400459
    401460        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
     
    403462        jPanel1Layout.setHorizontalGroup(
    404463            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    405             .addGap(0, 337, Short.MAX_VALUE)
     464            .addGroup(jPanel1Layout.createSequentialGroup()
     465                .addContainerGap()
     466                .addComponent(jLabel8)
     467                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
     468                .addComponent(useMyTagsButton)
     469                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
     470                .addComponent(useTheirTagsButton)
     471                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
     472                .addComponent(jButton1)
     473                .addContainerGap(300, Short.MAX_VALUE))
    406474        );
    407475        jPanel1Layout.setVerticalGroup(
    408476            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    409             .addGap(0, 438, Short.MAX_VALUE)
    410         );
    411 
    412         resultsTabPanel.addTab("Results", jPanel1);
     477            .addGroup(jPanel1Layout.createSequentialGroup()
     478                .addContainerGap()
     479                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
     480                    .addComponent(jLabel8)
     481                    .addComponent(useMyTagsButton)
     482                    .addComponent(useTheirTagsButton)
     483                    .addComponent(jButton1))
     484                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
     485        );
     486
     487        resultsPanel.add(jPanel1);
     488
     489        tagMergerPlaceholderPanel.setPreferredSize(new java.awt.Dimension(661, 250));
     490
     491        javax.swing.GroupLayout tagMergerPlaceholderPanelLayout = new javax.swing.GroupLayout(tagMergerPlaceholderPanel);
     492        tagMergerPlaceholderPanel.setLayout(tagMergerPlaceholderPanelLayout);
     493        tagMergerPlaceholderPanelLayout.setHorizontalGroup(
     494            tagMergerPlaceholderPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
     495            .addGap(0, 661, Short.MAX_VALUE)
     496        );
     497        tagMergerPlaceholderPanelLayout.setVerticalGroup(
     498            tagMergerPlaceholderPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
     499            .addGap(0, 150, Short.MAX_VALUE)
     500        );
     501
     502        resultsPanel.add(tagMergerPlaceholderPanel);
     503
     504        resolveButton.setText("Resolve");
     505        resolveButton.addActionListener(new java.awt.event.ActionListener() {
     506            public void actionPerformed(java.awt.event.ActionEvent evt) {
     507                resolveButtonActionPerformed(evt);
     508            }
     509        });
     510        resultsPanel.add(resolveButton);
     511
     512        resultsTabPanel.addTab("Results", resultsPanel);
    413513
    414514        add(resultsTabPanel);
    415515    }// </editor-fold>//GEN-END:initComponents
    416 
    417     private void refAddRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refAddRadioActionPerformed
    418         // TODO add your handling code here:
    419     }//GEN-LAST:event_refAddRadioActionPerformed
    420 
    421     private void nonRefAddRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nonRefAddRadioActionPerformed
    422         // TODO add your handling code here:
    423     }//GEN-LAST:event_nonRefAddRadioActionPerformed
    424516
    425517    private void objectTabCancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_objectTabCancelButtonActionPerformed
     
    429521
    430522    private void criteriaTabConflateButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_criteriaTabConflateButtonActionPerformed
    431         dlg.setVisible(false);
     523
     524        // some initialization
     525        int n = mySelection.size();
     526        int m = theirSelection.size();
     527        int maxLen = Math.max(n, m);
     528        double cost[][] = new double[maxLen][maxLen];
     529
     530        // calculate cost matrix
     531        for (int i = 0; i < n; i++) {
     532            for (int j = 0; j < m; j++) {
     533                cost[i][j] = calcCost(mySelection.get(i), theirSelection.get(j));
     534            }
     535        }
     536
     537        // perform assignment using Hungarian algorithm
     538        assignment = new int[maxLen][2];
     539        assignment = HungarianAlgorithm.hgAlgorithm(cost, "min");
     540
     541        // create array of primitives based on indices from assignment
     542        pairs = new OsmPrimitive[maxLen][2];
     543        for (int i = 0; i < maxLen; i++) {
     544            if (assignment[i][0] < n)
     545                pairs[i][0] = mySelection.get(assignment[i][0]);
     546            else
     547                pairs[i][0] = null;
     548            if (assignment[i][1] < m)
     549                pairs[i][1] = theirSelection.get(assignment[i][1]);
     550            else
     551                pairs[i][1] = null;
     552
     553            if (pairs[i][0] != null && pairs[i][1] != null) {
     554                // TODO: do something!
     555                conflicts.add(pairs[i][0], pairs[i][1]);
     556            }
     557        }
     558
     559        // add conflation layer
     560        try {
     561            conflationLayer = new ConflationLayer(myLayer.data, conflicts);
     562            Main.main.addLayer(conflationLayer);
     563        } catch (Exception ex) {
     564            JOptionPane.showMessageDialog(Main.parent, ex.toString(),
     565                    "Error adding conflation layer", JOptionPane.ERROR_MESSAGE);
     566        }
     567        tableModel = new MatchTableModel();
     568        resultsTable.setModel(tableModel);
     569
     570        conflictResolver.populate(conflicts.get(0));
     571        // print list of matched pairsalong with distance
     572        // upon selection of one pair, highlight them and draw arrow
    432573    }//GEN-LAST:event_criteriaTabConflateButtonActionPerformed
    433574
     
    436577            resultsTabPanel.setSelectedComponent(criteriaTabPanel);
    437578    }//GEN-LAST:event_objectTabNextButtonActionPerformed
     579
     580    private void restoreMySetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_restoreMySetButtonActionPerformed
     581        if (myLayer != null && myDataSet != null && mySelection != null && !mySelection.isEmpty()) {
     582            Main.map.mapView.setActiveLayer(myLayer);
     583            myLayer.setVisible(true);
     584            myDataSet.setSelected(mySelection);
     585        }
     586    }//GEN-LAST:event_restoreMySetButtonActionPerformed
     587
     588    private void restoreTheirSetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_restoreTheirSetButtonActionPerformed
     589        if (theirLayer != null && theirDataSet != null && theirSelection != null && !theirSelection.isEmpty()) {
     590            Main.map.mapView.setActiveLayer(theirLayer);
     591            theirLayer.setVisible(true);
     592            theirDataSet.setSelected(theirSelection);
     593        }
     594    }//GEN-LAST:event_restoreTheirSetButtonActionPerformed
     595
     596    private void freezeMySetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_freezeMySetButtonActionPerformed
     597        myDataSet = Main.main.getCurrentDataSet();
     598        myLayer = Main.main.getEditLayer();
     599        if (myDataSet == null || myLayer == null) {
     600            JOptionPane.showMessageDialog(Main.parent, tr("No valid OSM data layer present."),
     601                    tr("Error freezing selection"), JOptionPane.ERROR_MESSAGE);
     602            return;
     603        }
     604        mySelection = new ArrayList<OsmPrimitive>(myDataSet.getSelected());
     605        if (mySelection.isEmpty()) {
     606            JOptionPane.showMessageDialog(Main.parent, tr("Nothing is selected, please try again."),
     607                    tr("Empty selection"), JOptionPane.ERROR_MESSAGE);
     608            return;
     609        }
     610
     611        int numNodes = 0;
     612        int numWays = 0;
     613        int numRelations = 0;
     614        for (OsmPrimitive p: mySelection) {
     615            switch(p.getType()) {
     616            case NODE: numNodes++; break;
     617            case WAY: numWays++; break;
     618            case RELATION: numRelations++; break;
     619            }
     620        }
     621
     622        myLayerLabel.setText(myLayer.getName());
     623        myNodeCountLabel.setText(Integer.toString(numNodes));
     624        myWayCountLabel.setText(Integer.toString(numWays));
     625        myRelationCountLabel.setText(Integer.toString(numRelations));
     626    }//GEN-LAST:event_freezeMySetButtonActionPerformed
     627
     628    private void freezeTheirSelectionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_freezeTheirSelectionButtonActionPerformed
     629        theirDataSet = Main.main.getCurrentDataSet();
     630        theirLayer = Main.main.getEditLayer();
     631        if (theirDataSet == null || theirLayer == null) {
     632            JOptionPane.showMessageDialog(Main.parent, tr("No valid OSM data layer present."),
     633                    tr("Error freezing selection"), JOptionPane.ERROR_MESSAGE);
     634            return;
     635        }
     636        theirSelection = new ArrayList<OsmPrimitive>(theirDataSet.getSelected());
     637        if (theirSelection.isEmpty()) {
     638            JOptionPane.showMessageDialog(Main.parent, tr("Nothing is selected, please try again."),
     639                    tr("Empty selection"), JOptionPane.ERROR_MESSAGE);
     640            return;
     641        }
     642
     643        int numNodes = 0;
     644        int numWays = 0;
     645        int numRelations = 0;
     646        for (OsmPrimitive p: mySelection) {
     647            switch(p.getType()) {
     648            case NODE: numNodes++; break;
     649            case WAY: numWays++; break;
     650            case RELATION: numRelations++; break;
     651            }
     652        }
     653
     654        theirLayerLabel.setText(theirLayer.getName());
     655        theirNodeCountLabel.setText(Integer.toString(numNodes));
     656        theirWayCountLabel.setText(Integer.toString(numWays));
     657        theirRelationCountLabel.setText(Integer.toString(numRelations));
     658    }//GEN-LAST:event_freezeTheirSelectionButtonActionPerformed
     659
     660    private void useMyTagsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useMyTagsButtonActionPerformed
     661        int[] rows = resultsTable.getSelectedRows();
     662    }//GEN-LAST:event_useMyTagsButtonActionPerformed
     663
     664    private void jCheckBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBox1ActionPerformed
     665        // TODO add your handling code here:
     666    }//GEN-LAST:event_jCheckBox1ActionPerformed
     667
     668    private void resolveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resolveButtonActionPerformed
     669        if (!conflictResolver.isResolvedCompletely()) {
     670            JOptionPane.showMessageDialog(Main.parent, tr("Unresolved differences remain, please fix remaining differences."),
     671                    tr("Conflict not resolved completely"), JOptionPane.ERROR_MESSAGE);
     672                    return;
     673        }
     674        Command cmd = conflictResolver.buildResolveCommand();
     675        Main.main.undoRedo.add(cmd);
     676    }//GEN-LAST:event_resolveButtonActionPerformed
    438677
    439678    static public class LayerListCellRenderer extends DefaultListCellRenderer {
     
    451690    }
    452691
    453     public OsmDataLayer getRefLayer() {
    454         return (OsmDataLayer) refLayerComboBox.getModel().getSelectedItem();
    455     }
    456 
    457     public OsmDataLayer getNonRefLayer() {
    458         return (OsmDataLayer) nonRefLayerComboBox.getModel().getSelectedItem();
    459     }
    460 
    461     public SearchSetting getRefSearchSetting() {
    462         SearchSetting s = new SearchSetting();
    463         s.text = refFilterTextField.getText();
    464         s.allElements = refAllObjectsCheckBox.isSelected();
    465         s.caseSensitive = refCaseSensitiveCheckBox.isSelected();
    466         s.regexSearch = refRegExCheckBox.isSelected();
    467         s.mode = refReplaceRadio.isSelected() ? SearchAction.SearchMode.replace
    468                 : (refAddRadio.isSelected() ? SearchAction.SearchMode.add
    469                 : (refRemoveRadio.isSelected() ? SearchAction.SearchMode.remove : SearchAction.SearchMode.in_selection));
    470         return s;
    471     }
    472 
    473     public SearchSetting getNonRefSearchSetting() {
    474         SearchSetting s = new SearchSetting();
    475         s.text = nonRefFilterTextField.getText();
    476         s.allElements = nonRefAllObjectsCheckBox.isSelected();
    477         s.caseSensitive = nonRefCaseSensitiveCheckBox.isSelected();
    478         s.regexSearch = nonRefRegExCheckBox.isSelected();
    479         s.mode = nonRefReplaceRadio.isSelected() ? SearchAction.SearchMode.replace
    480                 : (nonRefAddRadio.isSelected() ? SearchAction.SearchMode.add
    481                 : (nonRefRemoveRadio.isSelected() ? SearchAction.SearchMode.remove : SearchAction.SearchMode.in_selection));
    482         return s;
     692
     693    public static EastNorth getCenter(OsmPrimitive prim) {
     694            LatLon center = prim.getBBox().getTopLeft().getCenter(prim.getBBox().getBottomRight());
     695            return Main.map.mapView.getProjection().latlon2eastNorth(center);
     696    }
     697
     698    /**
     699     * Calculate the cost of a pair of <code>OsmPrimitive</code>'s. A
     700     * simple cost consisting of the Euclidean distance is used
     701     * now, later we can also use dissimilarity between tags.
     702     *
     703     * @param   refPrim      the reference <code>OsmPrimitive</code>.
     704     * @param   nonRefPrim   the non-reference <code>OsmPrimitive</code>.
     705     */
     706    public double calcCost(OsmPrimitive refPrim, OsmPrimitive nonRefPrim) {
     707        double dist;
     708        try {
     709            dist = getCenter(refPrim).distance(getCenter(nonRefPrim));
     710        } catch (Exception e) {
     711            dist = 1000; // FIXME: what number to use?
     712        }
     713
     714        // TODO: use other "distance" measures, i.e. matching tags
     715        return dist;
     716    }
     717
     718    class MatchTableModel extends AbstractTableModel {
     719
     720        private String[] columnNames = {"Mine", "Theirs", "Distance (m)", "Cost", "Tags"};
     721
     722        public int getColumnCount() {
     723            return columnNames.length;
     724        }
     725
     726        public int getRowCount() {
     727            return conflicts.size();
     728        }
     729
     730        @Override
     731        public String getColumnName(int col) {
     732            return columnNames[col];
     733        }
     734
     735        public Object getValueAt(int row, int col) {
     736            if (col == 0)
     737                return conflicts.get(row).getMy();
     738            if (col == 1)
     739                return conflicts.get(row).getTheir();
     740            if (col == 4) {
     741                HashSet<OsmPrimitive> set = new HashSet<OsmPrimitive>();
     742                set.add(conflicts.get(row).getMy());
     743                set.add(conflicts.get(row).getTheir());
     744                TagCollection tags = TagCollection.unionOfAllPrimitives(set);
     745                Set<String> keys = tags.getKeysWithMultipleValues();
     746                if (keys.isEmpty())
     747                    return "No conflicts!";
     748                else
     749                    return "Conflicts!";
     750
     751            }
     752            else
     753                return 0;
     754        }
     755
     756        @Override
     757        public Class getColumnClass(int c) {
     758            return getValueAt(0, c).getClass();
     759        }
     760    }
     761
     762    class ColorTableCellRenderer extends JLabel implements TableCellRenderer {
     763        private String columnName;
     764
     765        public ColorTableCellRenderer(String column) {
     766            this.columnName = column;
     767            setOpaque(true);
     768        }
     769
     770        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
     771            Object columnValue = table.getValueAt(row, table.getColumnModel().getColumnIndex(columnName));
     772
     773            if (value != null) {
     774                setText(value.toString());
     775            }
     776            if (isSelected) {
     777                setBackground(table.getSelectionBackground());
     778                setForeground(table.getSelectionForeground());
     779            } else {
     780                setBackground(table.getBackground());
     781                setForeground(table.getForeground());
     782                if (columnValue.equals("Conflicts!")) {
     783                    setBackground(java.awt.Color.red);
     784                }
     785                else {
     786                    setBackground(java.awt.Color.green);
     787                }
     788            }
     789            return this;
     790        }
     791    }
     792
     793    class MatchListSelectionHandler implements ListSelectionListener {
     794
     795        public void valueChanged(ListSelectionEvent e) {
     796            ListSelectionModel lsm = (ListSelectionModel) e.getSource();
     797
     798            int firstIndex = lsm.getMinSelectionIndex();
     799            int lastIndex = lsm.getMaxSelectionIndex();
     800            boolean isAdjusting = e.getValueIsAdjusting();
     801            if (isAdjusting)
     802                return;
     803
     804            // only one item selected, show tags and zoom/center map
     805            if (!lsm.isSelectionEmpty() && firstIndex == lastIndex) {
     806                Conflict<?> c = conflicts.get(firstIndex);
     807                conflictResolver.populate(c);
     808               
     809                ArrayList<OsmPrimitive> sel = new ArrayList<OsmPrimitive>();
     810                sel.add(c.getMy());
     811                sel.add(c.getTheir());
     812
     813                BoundingXYVisitor box = new BoundingXYVisitor();
     814                box.computeBoundingBox(sel);
     815                if (box.getBounds() == null) {
     816                    return;
     817                }
     818                box.enlargeBoundingBox();
     819                Main.map.mapView.recalculateCenterScale(box);
     820            }
     821
     822        }
     823    }
     824
     825    public final void refreshView() {
     826        // TODO: should tell what rows changed
     827        tableModel.fireTableDataChanged();
     828    }
     829
     830    public void onConflictsAdded(ConflictCollection conflicts) {
     831        refreshView();
     832    }
     833
     834    public void onConflictsRemoved(ConflictCollection conflicts) {
     835        System.err.println("1 conflict has been resolved.");
     836        refreshView();
    483837    }
    484838
     
    486840    private javax.swing.JButton criteriaTabConflateButton;
    487841    private javax.swing.JPanel criteriaTabPanel;
     842    private javax.swing.JButton freezeMySetButton;
     843    private javax.swing.JButton freezeTheirSelectionButton;
     844    private javax.swing.JButton jButton1;
     845    private javax.swing.JCheckBox jCheckBox1;
    488846    private javax.swing.JLabel jLabel1;
    489847    private javax.swing.JLabel jLabel2;
    490848    private javax.swing.JLabel jLabel3;
    491849    private javax.swing.JLabel jLabel4;
     850    private javax.swing.JLabel jLabel5;
     851    private javax.swing.JLabel jLabel6;
     852    private javax.swing.JLabel jLabel7;
     853    private javax.swing.JLabel jLabel8;
     854    private javax.swing.JLabel jLabel9;
    492855    private javax.swing.JPanel jPanel1;
    493     private javax.swing.JPanel jPanel4;
    494     private javax.swing.JPanel jPanel5;
    495     private javax.swing.JPanel jPanel7;
    496     private javax.swing.JPanel jPanel8;
    497     private javax.swing.JRadioButton nonRefAddRadio;
    498     private javax.swing.JCheckBox nonRefAllObjectsCheckBox;
    499     private javax.swing.JCheckBox nonRefCaseSensitiveCheckBox;
    500     private javax.swing.JTextField nonRefFilterTextField;
    501     private javax.swing.JRadioButton nonRefInSelectionRadio;
    502     private javax.swing.JComboBox nonRefLayerComboBox;
    503     private javax.swing.JCheckBox nonRefRegExCheckBox;
    504     private javax.swing.JRadioButton nonRefRemoveRadio;
    505     private javax.swing.JRadioButton nonRefReplaceRadio;
    506     private javax.swing.ButtonGroup nonRefSearchModeButtonGroup;
     856    private javax.swing.JPanel jPanel2;
     857    private javax.swing.JScrollPane jScrollPane1;
     858    private javax.swing.JLabel myLayerLabel;
     859    private javax.swing.JLabel myNodeCountLabel;
     860    private javax.swing.JLabel myRelationCountLabel;
     861    private javax.swing.JLabel myWayCountLabel;
    507862    private javax.swing.JPanel nonRefSetPanel;
    508863    private javax.swing.JButton objectTabCancelButton;
    509864    private javax.swing.JButton objectTabNextButton;
    510865    private javax.swing.JPanel objectTabPanel;
    511     private javax.swing.JRadioButton refAddRadio;
    512     private javax.swing.JCheckBox refAllObjectsCheckBox;
    513     private javax.swing.JCheckBox refCaseSensitiveCheckBox;
    514     private javax.swing.JTextField refFilterTextField;
    515     private javax.swing.JRadioButton refInSelectionRadio;
    516     private javax.swing.JComboBox refLayerComboBox;
    517     private javax.swing.JCheckBox refRegExCheckBox;
    518     private javax.swing.JRadioButton refRemoveRadio;
    519     private javax.swing.JRadioButton refReplaceRadio;
    520     private javax.swing.ButtonGroup refSearchModeButtonGroup;
    521866    private javax.swing.JPanel refSetPanel;
     867    private javax.swing.JButton resolveButton;
     868    private javax.swing.JButton restoreMySetButton;
     869    private javax.swing.JButton restoreTheirSetButton;
     870    private javax.swing.JPanel resultsPanel;
    522871    private javax.swing.JTabbedPane resultsTabPanel;
     872    private javax.swing.JTable resultsTable;
     873    private javax.swing.JPanel tagMergerPlaceholderPanel;
     874    private javax.swing.JLabel theirLayerLabel;
     875    private javax.swing.JLabel theirNodeCountLabel;
     876    private javax.swing.JLabel theirRelationCountLabel;
     877    private javax.swing.JLabel theirWayCountLabel;
     878    private javax.swing.JButton useMyTagsButton;
     879    private javax.swing.JButton useTheirTagsButton;
    523880    // End of variables declaration//GEN-END:variables
    524881
Note: See TracChangeset for help on using the changeset viewer.