Changeset 2563 in josm


Ignore:
Timestamp:
03.12.2009 19:02:25 (2 years ago)
Author:
Gubaer
Message:

fixed #3400: relation editor: improvement to highlight an element
fixed #3873: Feature request: download selected elements in relation editor
New: Dbl-Click in member table to set the map selection to this member
New: Ctrl-Dbl-Clik in member table to add the member to the the map selection
New: Download selected incomplete members only

Location:
trunk
Files:
7 added
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/OpenFileAction.java

    r2512 r2563  
    22package org.openstreetmap.josm.actions; 
    33 
     4import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 
    45import static org.openstreetmap.josm.tools.I18n.tr; 
    5 import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 
    66 
    77import java.awt.event.ActionEvent; 
     
    8686            for (File f : files) { 
    8787                if (cancelled) return; 
    88                 getProgressMonitor().subTask(tr("Opening file ''{0}'' ...", f.getAbsolutePath())); 
     88                getProgressMonitor().indeterminateSubTask(tr("Opening file ''{0}'' ...", f.getAbsolutePath())); 
    8989                try { 
    9090                    System.out.println("Open file: " + f.getAbsolutePath() + " (" + f.length() + " bytes)"); 
  • trunk/src/org/openstreetmap/josm/data/osm/DataSetMerger.java

    r2512 r2563  
    3838     * to relation members) after the first phase of merging 
    3939     */ 
    40     private Set<Long> childrenToMerge; 
     40    private Set<PrimitiveId> objectsWithChildrenToMerge; 
    4141    private Set<OsmPrimitive> deletedObjectsToUnlink; 
    4242 
     
    5757        conflicts = new ConflictCollection(); 
    5858        mergedMap = new HashMap<Long, Long>(); 
    59         childrenToMerge = new HashSet<Long>(); 
     59        objectsWithChildrenToMerge = new HashSet<PrimitiveId>(); 
    6060        deletedObjectsToUnlink = new HashSet<OsmPrimitive>(); 
    6161    } 
     
    7575     * @param source  the other primitive 
    7676     */ 
    77     protected <P extends OsmPrimitive> void mergePrimitive(P source) { 
     77    protected void mergePrimitive(OsmPrimitive source) { 
    7878        if (!source.isNew() ) { 
    7979            // try to merge onto a matching primitive with the same 
     
    112112                        target.setTimestamp(source.getTimestamp()); 
    113113                        target.setModified(source.isModified()); 
    114                         childrenToMerge.add(source.getUniqueId()); 
     114                        objectsWithChildrenToMerge.add(source.getPrimitiveId()); 
    115115                    } 
    116116                    return; 
     
    131131        targetDataSet.addPrimitive(target); 
    132132        mergedMap.put(source.getUniqueId(), target.getUniqueId()); 
    133         childrenToMerge.add(source.getUniqueId()); 
     133        objectsWithChildrenToMerge.add(source.getPrimitiveId()); 
    134134    } 
    135135 
     
    154154 
    155155    /** 
     156     * A way in the target dataset might be incomplete because at least of of its nodes is incomplete. 
     157     * The nodes might have become complete because a complete node was merged onto into in the 
     158     * merge operation. 
     159     *  
     160     * This method loops over all parent ways of such nodes and turns them into complete ways 
     161     * if necessary. 
     162     *  
     163     * @param other 
     164     */ 
     165    protected void fixIncompleteParentWays(Node other) { 
     166        Node myNode = (Node)getMergeTarget(other); 
     167        if (myNode == null) 
     168            throw new RuntimeException(tr("Missing merge target for node with id {0}", other.getUniqueId())); 
     169        if (myNode.incomplete || myNode.isDeleted() || !myNode.isVisible()) return; 
     170        wayloop: for (Way w: OsmPrimitive.getFilteredList(myNode.getReferrers(), Way.class)) { 
     171            if (w.isDeleted() || ! w.isVisible() || ! w.incomplete) { 
     172                continue; 
     173            } 
     174            for (Node n: w.getNodes()) { 
     175                if (n.incomplete) { 
     176                    continue wayloop; 
     177                } 
     178            } 
     179            // all nodes are complete - set the way complete too 
     180            w.incomplete = false; 
     181        } 
     182    } 
     183 
     184    /** 
    156185     * Postprocess the dataset and fix all merged references to point to the actual 
    157186     * data. 
     
    159188    public void fixReferences() { 
    160189        for (Way w : sourceDataSet.getWays()) { 
    161             if (!conflicts.hasConflictForTheir(w) && childrenToMerge.contains(w.getUniqueId())) { 
     190            if (!conflicts.hasConflictForTheir(w) && objectsWithChildrenToMerge.contains(w.getPrimitiveId())) { 
    162191                mergeNodeList(w); 
    163192                fixIncomplete(w); 
     
    165194        } 
    166195        for (Relation r : sourceDataSet.getRelations()) { 
    167             if (!conflicts.hasConflictForTheir(r) && childrenToMerge.contains(r.getUniqueId())) { 
     196            if (!conflicts.hasConflictForTheir(r) && objectsWithChildrenToMerge.contains(r.getPrimitiveId())) { 
    168197                mergeRelationMembers(r); 
    169198            } 
     
    175204            targetDataSet.unlinkReferencesToPrimitive(target); 
    176205        } 
     206        // objectsWithChildrenToMerge also includes complete nodes which have 
     207        // been merged into their incomplete equivalents. 
     208        // 
     209        for (PrimitiveId id: objectsWithChildrenToMerge) { 
     210            if (!id.getType().equals(OsmPrimitiveType.NODE)) { 
     211                continue; 
     212            } 
     213            Node n = (Node)sourceDataSet.getPrimitiveById(id); 
     214            if (!conflicts.hasConflictForTheir(n)) { 
     215                fixIncompleteParentWays(n); 
     216            } 
     217        } 
     218 
    177219    } 
    178220 
     
    269311            // 
    270312            target.mergeFrom(source); 
    271             childrenToMerge.add(source.getUniqueId()); 
     313            objectsWithChildrenToMerge.add(source.getPrimitiveId()); 
    272314        } else if (!target.incomplete && source.incomplete) { 
    273315            // target is complete and source is incomplete 
     
    282324            // otherwise too many conflicts when refreshing from the server 
    283325        } else if (target.isDeleted() != source.isDeleted()) { 
    284             // differences in deleted state have to be resolved manually 
     326            // differences in deleted state have to be resolved manually. This can 
     327            // happen if one layer is merged onto another layer 
    285328            // 
    286329            conflicts.add(target,source); 
     
    288331            // target not modified. We can assume that source is the most recent version. 
    289332            // clone it into target. But check first, whether source is deleted. if so, 
    290             // make sure that target is not referenced anymore in myDataSet. 
     333            // make sure that target is not referenced any more in myDataSet. 
    291334            // 
    292335            if (source.isDeleted()) { 
     
    294337            } 
    295338            target.mergeFrom(source); 
    296             childrenToMerge.add(source.getUniqueId()); 
     339            objectsWithChildrenToMerge.add(source.getPrimitiveId()); 
    297340        } else if (! target.isModified() && !source.isModified() && target.getVersion() == source.getVersion()) { 
    298341            // both not modified. Keep mine 
     
    302345            // 
    303346            target.mergeFrom(source); 
    304             childrenToMerge.add(source.getUniqueId()); 
     347            objectsWithChildrenToMerge.add(source.getPrimitiveId()); 
    305348        } else if (target.isModified() && ! source.isModified() && target.getVersion() == source.getVersion()) { 
    306349            // target is same as source but target is modified 
     
    318361            target.mergeFrom(source); 
    319362            target.setModified(true); 
    320             childrenToMerge.add(source.getUniqueId()); 
     363            objectsWithChildrenToMerge.add(source.getPrimitiveId()); 
    321364        } 
    322365        return true; 
  • trunk/src/org/openstreetmap/josm/gui/DefaultNameFormatter.java

    r2512 r2563  
    77import java.util.ArrayList; 
    88import java.util.Arrays; 
     9import java.util.Collections; 
    910import java.util.HashSet; 
    1011import java.util.List; 
     
    199200        return tr("Changeset {0}",changeset.getId()); 
    200201    } 
     202 
     203    /** 
     204     * Builds a default tooltip text for the primitive <code>primitive</code>. 
     205     *  
     206     * @param primitive the primitmive 
     207     * @return the tooltip text 
     208     */ 
     209    public String buildDefaultToolTip(OsmPrimitive primitive) { 
     210        StringBuilder sb = new StringBuilder(); 
     211        sb.append("<html>"); 
     212        sb.append("<strong>id</strong>=") 
     213        .append(primitive.getId()) 
     214        .append("<br>"); 
     215        ArrayList<String> keyList = new ArrayList<String>(primitive.keySet()); 
     216        Collections.sort(keyList); 
     217        for (int i = 0; i < keyList.size(); i++) { 
     218            if (i > 0) { 
     219                sb.append("<br>"); 
     220            } 
     221            String key = keyList.get(i); 
     222            sb.append("<strong>") 
     223            .append(key) 
     224            .append("</strong>") 
     225            .append("="); 
     226            String value = primitive.get(key); 
     227            while(value.length() != 0) { 
     228                sb.append(value.substring(0,Math.min(50, value.length()))); 
     229                if (value.length() > 50) { 
     230                    sb.append("<br>"); 
     231                    value = value.substring(50); 
     232                } else { 
     233                    value = ""; 
     234                } 
     235            } 
     236        } 
     237        sb.append("</html>"); 
     238        return sb.toString(); 
     239    } 
    201240} 
  • trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java

    r2514 r2563  
    4343import org.openstreetmap.josm.gui.OsmPrimitivRenderer; 
    4444import org.openstreetmap.josm.gui.SideButton; 
    45 import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor; 
     45import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationTask; 
    4646import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor; 
    4747import org.openstreetmap.josm.gui.layer.DataChangeListener; 
     
    248248                displaylist.setSelectedIndex(index); 
    249249            } 
    250             popupMenu.show(RelationListDialog.this, p.x, p.y-3); 
     250            popupMenu.show(displaylist, p.x, p.y-3); 
    251251        } 
    252252        @Override public void mousePressed(MouseEvent e) { 
     
    500500            if (relations.isEmpty()) 
    501501                return; 
    502             Main.worker.submit(new GenericRelationEditor.DownloadTask( 
     502            Main.worker.submit(new DownloadRelationTask( 
    503503                    model.getSelectedNonNewRelations(), 
    504                     Main.map.mapView.getEditLayer(), null)); 
     504                    Main.map.mapView.getEditLayer()) 
     505            ); 
    505506        } 
    506507    } 
  • trunk/src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java

    r2243 r2563  
    169169        BasicArrowButton arrowButton = new BasicArrowButton(SwingConstants.SOUTH, null, null, Color.BLACK, null); 
    170170        arrowButton.setBorder(BorderFactory.createEmptyBorder()); 
    171         //        selectionHistoryMenuButton.setContentAreaFilled(false); 
    172         //        selectionHistoryMenuButton.setOpaque(false); 
    173         //        selectionHistoryMenuButton.setBorderPainted(false); 
    174         //        selectionHistoryMenuButton.setBackground(null); 
    175171        parentButton.setLayout(new BorderLayout()); 
    176172        parentButton.add(arrowButton, BorderLayout.EAST); 
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java

    r2512 r2563  
    55 
    66import java.awt.BorderLayout; 
    7 import java.awt.Dialog; 
    87import java.awt.Dimension; 
    98import java.awt.FlowLayout; 
    109import java.awt.GridBagConstraints; 
    1110import java.awt.GridBagLayout; 
    12 import java.awt.Insets; 
    1311import java.awt.event.ActionEvent; 
    1412import java.awt.event.FocusAdapter; 
     
    1917import java.awt.event.WindowAdapter; 
    2018import java.awt.event.WindowEvent; 
    21 import java.io.IOException; 
     19import java.beans.PropertyChangeEvent; 
     20import java.beans.PropertyChangeListener; 
    2221import java.util.ArrayList; 
    2322import java.util.Collection; 
     
    3029import javax.swing.AbstractAction; 
    3130import javax.swing.BorderFactory; 
    32 import javax.swing.JButton; 
    3331import javax.swing.JComponent; 
    3432import javax.swing.JLabel; 
     
    3836import javax.swing.JSplitPane; 
    3937import javax.swing.JTabbedPane; 
    40 import javax.swing.JTable; 
     38import javax.swing.JToolBar; 
    4139import javax.swing.KeyStroke; 
    42 import javax.swing.SwingUtilities; 
    4340import javax.swing.event.ChangeEvent; 
    4441import javax.swing.event.ChangeListener; 
     
    5754import org.openstreetmap.josm.data.osm.DataSet; 
    5855import org.openstreetmap.josm.data.osm.OsmPrimitive; 
    59 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 
    6056import org.openstreetmap.josm.data.osm.Relation; 
    6157import org.openstreetmap.josm.data.osm.RelationMember; 
    6258import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil; 
    6359import org.openstreetmap.josm.gui.DefaultNameFormatter; 
    64 import org.openstreetmap.josm.gui.ExceptionDialogUtil; 
    6560import org.openstreetmap.josm.gui.HelpAwareOptionPane; 
    66 import org.openstreetmap.josm.gui.PleaseWaitRunnable; 
    6761import org.openstreetmap.josm.gui.SideButton; 
    6862import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec; 
     
    7064import org.openstreetmap.josm.gui.help.HelpUtil; 
    7165import org.openstreetmap.josm.gui.layer.OsmDataLayer; 
    72 import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor; 
    73 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 
    7466import org.openstreetmap.josm.gui.tagging.AutoCompletingTextField; 
    7567import org.openstreetmap.josm.gui.tagging.TagEditorPanel; 
    7668import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionCache; 
    7769import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList; 
    78 import org.openstreetmap.josm.io.OsmServerBackreferenceReader; 
    79 import org.openstreetmap.josm.io.OsmServerObjectReader; 
    80 import org.openstreetmap.josm.io.OsmTransferException; 
    8170import org.openstreetmap.josm.tools.ImageProvider; 
    8271import org.openstreetmap.josm.tools.Shortcut; 
    83 import org.xml.sax.SAXException; 
    8472 
    8573/** 
     
    125113        // 
    126114        memberTableModel = new MemberTableModel(getLayer()); 
     115        DataSet.selListeners.add(memberTableModel); 
     116        getLayer().data.addDataSetListener(memberTableModel); 
     117        getLayer().listenerDataChanged.add(memberTableModel); 
    127118        selectionTableModel = new SelectionTableModel(getLayer()); 
     119        DataSet.selListeners.add(selectionTableModel); 
    128120        referrerModel = new ReferringRelationsBrowserModel(relation); 
    129121 
     
    173165        ); 
    174166 
     167        getContentPane().add(buildToolBar(), BorderLayout.NORTH); 
    175168        getContentPane().add(tabbedPane, BorderLayout.CENTER); 
    176169        getContentPane().add(buildOkCancelButtonPanel(), BorderLayout.SOUTH); 
     
    189182        memberTableModel.setSelectedMembers(selectedMembers); 
    190183        HelpUtil.setHelpContext(getRootPane(),ht("/Dialog/RelationEditor")); 
     184    } 
     185 
     186    /** 
     187     * Creates the toolbar 
     188     *  
     189     * @return the toolbar 
     190     */ 
     191    protected JToolBar buildToolBar() { 
     192        JToolBar tb  = new JToolBar(); 
     193        tb.setFloatable(false); 
     194        tb.add(new ApplyAction()); 
     195        tb.add(new DuplicateRelationAction()); 
     196        DeleteCurrentRelationAction deleteAction = new DeleteCurrentRelationAction(); 
     197        addPropertyChangeListener(deleteAction); 
     198        tb.add(deleteAction); 
     199        return tb; 
    191200    } 
    192201 
     
    280289        pnl.add(scrollPane, gc); 
    281290 
     291        // --- role editing 
     292        JPanel p3 = new JPanel(new FlowLayout(FlowLayout.LEFT)); 
     293        p3.add(new JLabel(tr("Apply Role:"))); 
     294        tfRole = new AutoCompletingTextField(10); 
     295        tfRole.setToolTipText(tr("Enter a role and apply it to the selected relation members")); 
     296        tfRole.addFocusListener(new FocusAdapter() { 
     297            @Override 
     298            public void focusGained(FocusEvent e) { 
     299                tfRole.selectAll(); 
     300            } 
     301        }); 
     302        tfRole.setAutoCompletionList(new AutoCompletionList()); 
     303        tfRole.addFocusListener( 
     304                new FocusAdapter() { 
     305                    @Override 
     306                    public void focusGained(FocusEvent e) { 
     307                        AutoCompletionList list = tfRole.getAutoCompletionList(); 
     308                        AutoCompletionCache.getCacheForLayer(Main.main.getEditLayer()).populateWithMemberRoles(list); 
     309                    } 
     310                } 
     311        ); 
     312        p3.add(tfRole); 
     313        SetRoleAction setRoleAction = new SetRoleAction(); 
     314        memberTableModel.getSelectionModel().addListSelectionListener(setRoleAction); 
     315        tfRole.getDocument().addDocumentListener(setRoleAction); 
     316        tfRole.addActionListener(setRoleAction); 
     317        memberTableModel.getSelectionModel().addListSelectionListener( 
     318                new ListSelectionListener() { 
     319                    public void valueChanged(ListSelectionEvent e) { 
     320                        tfRole.setEnabled(memberTable.getSelectedRowCount() > 0); 
     321                    } 
     322                } 
     323        ); 
     324        tfRole.setEnabled(memberTable.getSelectedRowCount() > 0); 
     325 
     326        gc.gridx = 1; 
     327        gc.gridy = 2; 
     328        gc.fill = GridBagConstraints.BOTH; 
     329        gc.anchor = GridBagConstraints.CENTER; 
     330        gc.weightx = 1.0; 
     331        gc.weighty = 0.0; 
     332        pnl.add(p3, gc); 
     333 
    282334        JPanel pnl2 = new JPanel(); 
    283335        pnl2.setLayout(new GridBagLayout()); 
     
    326378        pnl3.setLayout(new BorderLayout()); 
    327379        pnl3.add(splitPane, BorderLayout.CENTER); 
    328         pnl3.add(buildButtonPanel(), BorderLayout.SOUTH); 
    329380        return pnl3; 
    330381    } 
     
    338389        JPanel pnl = new JPanel(); 
    339390        pnl.setLayout(new BorderLayout()); 
    340         JTable tbl = new JTable(selectionTableModel, new SelectionTableColumnModel(memberTableModel)); 
    341         tbl.setEnabled(false); 
     391        SelectionTable tbl = new SelectionTable(selectionTableModel, new SelectionTableColumnModel(memberTableModel)); 
     392        tbl.setMemberTableModel(memberTableModel); 
    342393        JScrollPane pane = new JScrollPane(tbl); 
    343394        pnl.add(pane, BorderLayout.CENTER); 
     
    371422     * @return 
    372423     */ 
    373     protected JPanel buildLeftButtonPanel() { 
    374         JPanel pnl = new JPanel(); 
    375         pnl.setLayout(new GridBagLayout()); 
    376  
    377         GridBagConstraints gc = new GridBagConstraints(); 
    378         gc.gridx = 0; 
    379         gc.gridy = 0; 
    380         gc.gridheight = 1; 
    381         gc.gridwidth = 1; 
    382         gc.insets = new Insets(0, 5, 0, 5); 
    383         gc.fill = GridBagConstraints.HORIZONTAL; 
    384         gc.anchor = GridBagConstraints.CENTER; 
    385         gc.weightx = 0.0; 
    386         gc.weighty = 0.0; 
    387  
    388         // ----- 
    389         gc.gridy = 0; 
     424    protected JToolBar buildLeftButtonPanel() { 
     425        JToolBar tb = new JToolBar(); 
     426        tb.setOrientation(JToolBar.VERTICAL); 
     427        tb.setFloatable(false); 
     428 
     429        // -- move up action 
    390430        MoveUpAction moveUpAction = new MoveUpAction(); 
    391431        memberTableModel.getSelectionModel().addListSelectionListener(moveUpAction); 
    392         pnl.add(new JButton(moveUpAction), gc); 
    393  
    394         // ----- 
    395         gc.gridy = 1; 
     432        tb.add(moveUpAction); 
     433 
     434        // -- move down action 
    396435        MoveDownAction moveDownAction = new MoveDownAction(); 
    397436        memberTableModel.getSelectionModel().addListSelectionListener(moveDownAction); 
    398         pnl.add(new JButton(moveDownAction), gc); 
     437        tb.add(moveDownAction); 
     438 
     439        tb.addSeparator(); 
    399440 
    400441        // -- edit action 
    401         gc.gridy = 2; 
    402442        EditAction editAction = new EditAction(); 
    403443        memberTableModel.getSelectionModel().addListSelectionListener(editAction); 
    404         pnl.add(new JButton(editAction),gc); 
    405  
    406         // ------ 
    407         gc.gridy = 3; 
     444        tb.add(editAction); 
     445 
     446        // -- delete action 
    408447        RemoveAction removeSelectedAction = new RemoveAction(); 
    409448        memberTable.getSelectionModel().addListSelectionListener(removeSelectedAction); 
    410         pnl.add(new JButton(removeSelectedAction), gc); 
    411  
    412         // ------ 
    413         gc.gridy = 4; 
    414         SelectPrimitivesForSelectedMembersAction selectAction = new SelectPrimitivesForSelectedMembersAction(); 
    415         memberTable.getSelectionModel().addListSelectionListener(selectAction); 
    416         pnl.add(new JButton(selectAction), gc); 
    417  
    418         // ------ 
    419         gc.gridy = 5; 
     449        tb.add(removeSelectedAction); 
     450 
     451        tb.addSeparator(); 
     452        // -- sort action 
    420453        SortAction sortAction = new SortAction(); 
    421         pnl.add(new JButton(sortAction), gc); 
    422  
    423         // ------ 
    424         // just grab the remaining space 
    425         gc.gridy = 6; 
    426         gc.weighty = 1.0; 
    427         gc.fill = GridBagConstraints.BOTH; 
    428         pnl.add(new JPanel(), gc); 
    429         return pnl; 
     454        tb.add(sortAction); 
     455 
     456        tb.addSeparator(); 
     457 
     458        // -- download action 
     459        DownloadIncompleteMembersAction downloadIncompleteMembersAction = new DownloadIncompleteMembersAction(); 
     460        memberTable.getModel().addTableModelListener(downloadIncompleteMembersAction); 
     461        tb.add(downloadIncompleteMembersAction); 
     462 
     463        // -- download selected action 
     464        DownloadSelectedIncompleteMembersAction downloadSelectedIncompleteMembersAction = new DownloadSelectedIncompleteMembersAction(); 
     465        memberTable.getModel().addTableModelListener(downloadSelectedIncompleteMembersAction); 
     466        memberTable.getSelectionModel().addListSelectionListener(downloadSelectedIncompleteMembersAction); 
     467        tb.add(downloadSelectedIncompleteMembersAction); 
     468 
     469        return tb; 
    430470    } 
    431471 
     
    435475     * @return 
    436476     */ 
    437     protected JPanel buildSelectionControlButtonPanel() { 
    438         JPanel pnl = new JPanel(); 
    439         pnl.setLayout(new GridBagLayout()); 
    440  
    441         GridBagConstraints gc = new GridBagConstraints(); 
    442         gc.gridx = 0; 
    443         gc.gridy = 0; 
    444         gc.gridheight = 1; 
    445         gc.gridwidth = 1; 
    446         gc.insets = new Insets(0, 5, 0, 5); 
    447         gc.fill = GridBagConstraints.HORIZONTAL; 
    448         gc.anchor = GridBagConstraints.CENTER; 
    449         gc.weightx = 0.0; 
    450         gc.weighty = 0.0; 
     477    protected JToolBar buildSelectionControlButtonPanel() { 
     478        JToolBar tb = new JToolBar(JToolBar.VERTICAL); 
     479        tb.setFloatable(false); 
     480 
     481 
     482        // -- add at end action 
    451483        AddSelectedAtEndAction addSelectedAtEndAction = new AddSelectedAtEndAction(); 
    452484        selectionTableModel.addTableModelListener(addSelectedAtEndAction); 
    453         pnl.add(new JButton(addSelectedAtEndAction), gc); 
    454  
    455         // ----- 
    456         gc.gridy = 1; 
     485        tb.add(addSelectedAtEndAction); 
     486 
     487        // -- select members action 
    457488        SelectedMembersForSelectionAction selectMembersForSelectionAction = new SelectedMembersForSelectionAction(); 
    458489        selectionTableModel.addTableModelListener(selectMembersForSelectionAction); 
    459490        memberTableModel.addTableModelListener(selectMembersForSelectionAction); 
    460         pnl.add(new JButton(selectMembersForSelectionAction), gc); 
    461  
    462         // ----- 
    463         gc.gridy = 2; 
     491        tb.add(selectMembersForSelectionAction); 
     492 
     493        tb.addSeparator(); 
     494 
     495        // -- remove selected action 
    464496        RemoveSelectedAction removeSelectedAction = new RemoveSelectedAction(); 
    465497        selectionTableModel.addTableModelListener(removeSelectedAction); 
    466         pnl.add(new JButton(removeSelectedAction), gc); 
    467  
    468         // ------ 
    469         // just grab the remaining space 
    470         gc.gridy = 3; 
    471         gc.weighty = 1.0; 
    472         gc.fill = GridBagConstraints.BOTH; 
    473         pnl.add(new JPanel(), gc); 
    474  
    475         // ----- 
    476         gc.gridy = 4; 
    477         gc.weighty = 0.0; 
     498        tb.add(removeSelectedAction); 
     499 
     500        // -- select action 
     501        SelectPrimitivesForSelectedMembersAction selectAction = new SelectPrimitivesForSelectedMembersAction(); 
     502        memberTable.getSelectionModel().addListSelectionListener(selectAction); 
     503        tb.add(selectAction); 
     504 
     505        tb.addSeparator(); 
     506 
     507        // -- add at start action 
    478508        AddSelectedAtStartAction addSelectionAction = new AddSelectedAtStartAction(); 
    479509        selectionTableModel.addTableModelListener(addSelectionAction); 
    480         pnl.add(new JButton(addSelectionAction), gc); 
    481  
    482         // ----- 
    483         gc.gridy = 5; 
     510        tb.add(addSelectionAction); 
     511 
     512        // -- add before selected action 
    484513        AddSelectedBeforeSelection addSelectedBeforeSelectionAction = new AddSelectedBeforeSelection(); 
    485514        selectionTableModel.addTableModelListener(addSelectedBeforeSelectionAction); 
    486515        memberTableModel.getSelectionModel().addListSelectionListener(addSelectedBeforeSelectionAction); 
    487         pnl.add(new JButton(addSelectedBeforeSelectionAction), gc); 
    488  
    489         // ----- 
    490         gc.gridy = 6; 
     516        tb.add(addSelectedBeforeSelectionAction); 
     517 
     518        // -- add after selected action 
    491519        AddSelectedAfterSelection addSelectedAfterSelectionAction = new AddSelectedAfterSelection(); 
    492520        selectionTableModel.addTableModelListener(addSelectedAfterSelectionAction); 
    493521        memberTableModel.getSelectionModel().addListSelectionListener(addSelectedAfterSelectionAction); 
    494         pnl.add(new JButton(addSelectedAfterSelectionAction), gc); 
    495  
    496         return pnl; 
    497     } 
    498  
    499     /** 
    500      * Creates the buttons for the basic editing layout 
    501      * @return {@see JPanel} with basic buttons 
    502      */ 
    503     protected JPanel buildButtonPanel() { 
    504         JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); 
    505  
    506         // --- download members 
    507         buttonPanel.add(new SideButton(new DownlaodAction())); 
    508  
    509         // --- role editing 
    510         buttonPanel.add(new JLabel(tr("Role:"))); 
    511         tfRole = new AutoCompletingTextField(10); 
    512         tfRole.addFocusListener(new FocusAdapter() { 
    513             @Override 
    514             public void focusGained(FocusEvent e) { 
    515                 tfRole.selectAll(); 
    516             } 
    517         }); 
    518         tfRole.setAutoCompletionList(new AutoCompletionList()); 
    519         tfRole.addFocusListener( 
    520                 new FocusAdapter() { 
    521                     @Override 
    522                     public void focusGained(FocusEvent e) { 
    523                         AutoCompletionList list = tfRole.getAutoCompletionList(); 
    524                         AutoCompletionCache.getCacheForLayer(Main.main.getEditLayer()).populateWithMemberRoles(list); 
    525                     } 
    526                 } 
    527         ); 
    528  
    529         buttonPanel.add(tfRole); 
    530         SetRoleAction setRoleAction = new SetRoleAction(); 
    531         memberTableModel.getSelectionModel().addListSelectionListener(setRoleAction); 
    532         buttonPanel.add(new SideButton(setRoleAction)); 
    533         tfRole.getDocument().addDocumentListener(setRoleAction); 
    534         tfRole.addActionListener(setRoleAction); 
    535  
    536         // --- copy relation action 
    537         buttonPanel.add(new SideButton(new DuplicateRelationAction())); 
    538  
    539         // --- apply relation action 
    540         buttonPanel.add(new SideButton(new ApplyAction())); 
    541  
    542         // --- delete relation action 
    543         buttonPanel.add(new SideButton(new DeleteCurrentRelationAction())); 
    544         return buttonPanel; 
     522        tb.add(addSelectedAfterSelectionAction); 
     523 
     524        return tb; 
    545525    } 
    546526 
     
    548528    protected Dimension findMaxDialogSize() { 
    549529        // FIXME: Make it remember dialog size 
    550         return new Dimension(700, 500); 
    551     } 
    552  
    553     @Override 
    554     public void dispose() { 
    555         selectionTableModel.unregister(); 
    556         DataSet.selListeners.remove(memberTableModel); 
    557         super.dispose(); 
     530        return new Dimension(700, 650); 
    558531    } 
    559532 
     
    561534    public void setVisible(boolean visible) { 
    562535        if (visible) { 
    563             tagEditorPanel.initAutoCompletion(Main.main.getEditLayer()); 
     536            tagEditorPanel.initAutoCompletion(getLayer()); 
    564537        } 
    565538        super.setVisible(visible); 
    566539        if (!visible) { 
     540            // make sure all registered listeners are unregistered 
     541            // 
     542            selectionTableModel.unregister(); 
     543            DataSet.selListeners.remove(memberTableModel); 
     544            DataSet.selListeners.remove(selectionTableModel); 
     545            getLayer().data.removeDataSetListener(memberTableModel); 
     546            getLayer().listenerDataChanged.remove(memberTableModel); 
    567547            dispose(); 
    568548        } 
     
    888868    } 
    889869 
    890     class SortAction extends AbstractAction { 
     870    class SortAction extends AbstractAction implements ListSelectionListener { 
    891871        public SortAction() { 
    892872            putValue(SHORT_DESCRIPTION, tr("Sort the relation members")); 
    893873            putValue(SMALL_ICON, ImageProvider.get("dialogs", "sort")); 
    894             // putValue(NAME, tr("Sort")); 
     874            putValue(NAME, tr("Sort")); 
    895875            Shortcut.registerShortcut("relationeditor:sort", tr("Relation Editor: Sort"), KeyEvent.VK_T, 
    896876                    Shortcut.GROUP_MNEMONIC); 
    897             //setEnabled(false); 
     877            updateEnabledState(); 
    898878        } 
    899879 
    900880        public void actionPerformed(ActionEvent e) { 
    901881            memberTableModel.sort(); 
     882        } 
     883 
     884        protected void updateEnabledState() { 
     885            setEnabled(memberTable.getSelectedRowCount() > 0); 
     886        } 
     887 
     888        public void valueChanged(ListSelectionEvent e) { 
     889            updateEnabledState(); 
    902890        } 
    903891    } 
     
    960948    } 
    961949 
    962     class DeleteCurrentRelationAction extends AbstractAction { 
     950    class DeleteCurrentRelationAction extends AbstractAction implements PropertyChangeListener{ 
    963951        public DeleteCurrentRelationAction() { 
    964952            putValue(SHORT_DESCRIPTION, tr("Delete the currently edited relation")); 
     
    983971 
    984972        protected void updateEnabledState() { 
    985             setEnabled(getRelation() != null); 
     973            setEnabled(getRelationSnapshot() != null); 
     974        } 
     975 
     976        public void propertyChange(PropertyChangeEvent evt) { 
     977            if (evt.getPropertyName().equals(RELATION_SNAPSHOT_PROP)) { 
     978                updateEnabledState(); 
     979            } 
    986980        } 
    987981    } 
     
    11871181    } 
    11881182 
    1189     class DownlaodAction extends AbstractAction { 
    1190         public DownlaodAction() { 
    1191             putValue(SHORT_DESCRIPTION, tr("Download all incomplete ways and nodes in relation")); 
    1192             putValue(SMALL_ICON, ImageProvider.get("dialogs", "downloadincomplete")); 
     1183    class DownloadIncompleteMembersAction extends AbstractAction implements TableModelListener { 
     1184        public DownloadIncompleteMembersAction() { 
     1185            putValue(SHORT_DESCRIPTION, tr("Download all incomplete members")); 
     1186            putValue(SMALL_ICON, ImageProvider.get("dialogs/relation", "downloadincomplete")); 
    11931187            putValue(NAME, tr("Download Members")); 
    11941188            Shortcut.registerShortcut("relationeditor:downloadincomplete", tr("Relation Editor: Download Members"), 
     
    12001194            if (!isEnabled()) 
    12011195                return; 
    1202             Main.worker.submit(new DownloadTask( 
    1203                     Collections.singletonList(getRelation()), 
     1196            Main.worker.submit(new DownloadRelationMemberTask( 
     1197                    getRelation(), 
     1198                    memberTableModel.getIncompleteMemberPrimitives(), 
    12041199                    getLayer(), 
    12051200                    memberTableModel, 
     
    12091204 
    12101205        protected void updateEnabledState() { 
    1211             setEnabled(getRelation() != null && !getRelation().isNew()); 
     1206            setEnabled( 
     1207                    getRelation() != null 
     1208                    && !getRelation().isNew() 
     1209                    && memberTableModel.hasIncompleteMembers() 
     1210            ); 
     1211        } 
     1212 
     1213        public void tableChanged(TableModelEvent e) { 
     1214            updateEnabledState(); 
     1215        } 
     1216    } 
     1217 
     1218    class DownloadSelectedIncompleteMembersAction extends AbstractAction implements ListSelectionListener, TableModelListener{ 
     1219        public DownloadSelectedIncompleteMembersAction() { 
     1220            putValue(SHORT_DESCRIPTION, tr("Download selected incomplete members")); 
     1221            putValue(SMALL_ICON, ImageProvider.get("dialogs/relation", "downloadincompleteselected")); 
     1222            putValue(NAME, tr("Download Members")); 
     1223            Shortcut.registerShortcut("relationeditor:downloadincomplete", tr("Relation Editor: Download Members"), 
     1224                    KeyEvent.VK_K, Shortcut.GROUP_MNEMONIC); 
     1225            updateEnabledState(); 
     1226        } 
     1227 
     1228        public void actionPerformed(ActionEvent e) { 
     1229            if (!isEnabled()) 
     1230                return; 
     1231            Main.worker.submit(new DownloadRelationMemberTask( 
     1232                    getRelation(), 
     1233                    memberTableModel.getSelectedIncompleteMemberPrimitives(), 
     1234                    getLayer(), 
     1235                    memberTableModel, 
     1236                    GenericRelationEditor.this) 
     1237            ); 
     1238        } 
     1239 
     1240        protected void updateEnabledState() { 
     1241            setEnabled( 
     1242                    getRelation() != null 
     1243                    && !getRelation().isNew() 
     1244                    && memberTableModel.hasIncompleteSelectedMembers() 
     1245            ); 
     1246        } 
     1247 
     1248        public void valueChanged(ListSelectionEvent e) { 
     1249            updateEnabledState(); 
     1250        } 
     1251 
     1252        public void tableChanged(TableModelEvent e) { 
     1253            updateEnabledState(); 
    12121254        } 
    12131255    } 
     
    13661408        } 
    13671409    } 
    1368  
    1369     /** 
    1370      * The asynchronous task for downloading relation members. 
    1371      * 
    1372      */ 
    1373     public static class DownloadTask extends PleaseWaitRunnable { 
    1374         private boolean cancelled; 
    1375         private Exception lastException; 
    1376         private List<Relation> relations; 
    1377         private OsmDataLayer curLayer; 
    1378         private MemberTableModel memberTableModel; 
    1379         private OsmServerObjectReader objectReader; 
    1380         private OsmServerBackreferenceReader parentReader; 
    1381  
    1382         public DownloadTask(List<Relation> relations, OsmDataLayer curLayer, MemberTableModel memberTableModel, Dialog parent) { 
    1383             super(tr("Download relation members"), new PleaseWaitProgressMonitor(parent), false /* don't ignore exception */); 
    1384             this.relations = relations; 
    1385             this.curLayer = curLayer; 
    1386             this.memberTableModel = memberTableModel; 
    1387         } 
    1388  
    1389         public DownloadTask(List<Relation> relations, OsmDataLayer curLayer, MemberTableModel memberTableModel) { 
    1390             super(tr("Download relation members"), new PleaseWaitProgressMonitor(), false /* don't ignore exception */); 
    1391             this.relations = relations; 
    1392             this.curLayer = curLayer; 
    1393             this.memberTableModel = memberTableModel; 
    1394         } 
    1395  
    1396         @Override 
    1397         protected void cancel() { 
    1398             cancelled = true; 
    1399             synchronized(this) { 
    1400                 if (objectReader != null) { 
    1401                     objectReader.cancel(); 
    1402                 } else if (parentReader != null) { 
    1403                     parentReader.cancel(); 
    1404                 } 
    1405             } 
    1406         } 
    1407  
    1408         @Override 
    1409         protected void finish() { 
    1410             Main.map.repaint(); 
    1411             if (cancelled) 
    1412                 return; 
    1413             if (memberTableModel != null) { 
    1414                 memberTableModel.fireTableDataChanged(); 
    1415             } 
    1416             if (lastException != null) { 
    1417                 ExceptionDialogUtil.explainException(lastException); 
    1418             } 
    1419         } 
    1420  
    1421         @Override 
    1422         protected void realRun() throws SAXException, IOException, OsmTransferException { 
    1423             try { 
    1424                 for (Relation relation : relations) { 
    1425                     // download the relation 
    1426                     // 
    1427                     progressMonitor.indeterminateSubTask(tr("Downloading relation ''{0}''", relation.getDisplayName(DefaultNameFormatter.getInstance()))); 
    1428                     synchronized(this) { 
    1429                         if (cancelled) return; 
    1430                         objectReader = new OsmServerObjectReader(relation.getId(), OsmPrimitiveType.RELATION, true /* full download */); 
    1431                     } 
    1432                     final DataSet dataSet = objectReader.parseOsm(progressMonitor 
    1433                             .createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)); 
    1434                     if (dataSet == null) 
    1435                         return; 
    1436                     synchronized (this) { 
    1437                         if (cancelled) return; 
    1438                         objectReader = null; 
    1439                     } 
    1440  
    1441                     // download referring objects of the downloaded member objects 
    1442                     // 
    1443                     // asked for in #3999, but uncommented for the time being. Could be used 
    1444                     // later, perhaps if user explicity requests so (for instance by checking 
    1445                     // a checkbox) 
    1446                     //                    for (OsmPrimitive p: relation.getMemberPrimitives()) { 
    1447                     //                        synchronized(this) { 
    1448                     //                            if (cancelled) return; 
    1449                     //                            parentReader = new OsmServerBackreferenceReader(p); 
    1450                     //                        } 
    1451                     //                        DataSet parents = parentReader.parseOsm(progressMonitor.createSubTaskMonitor(1, false)); 
    1452                     //                        synchronized(this) { 
    1453                     //                            if (cancelled) return; 
    1454                     //                            parentReader = null; 
    1455                     //                        } 
    1456                     //                        DataSetMerger merger = new DataSetMerger(dataSet, parents); 
    1457                     //                        merger.merge(); 
    1458                     //                    } 
    1459                     //                    if (cancelled) return; 
    1460  
    1461                     // has to run on the EDT because mergeFrom may trigger events 
    1462                     // which update the UI 
    1463                     // 
    1464                     SwingUtilities.invokeAndWait( 
    1465                             new Runnable() { 
    1466                                 public void run() { 
    1467                                     curLayer.mergeFrom(dataSet); 
    1468                                     curLayer.fireDataChange(); 
    1469                                     curLayer.onPostDownloadFromServer(); 
    1470                                 } 
    1471                             } 
    1472                     ); 
    1473                 } 
    1474             } catch (Exception e) { 
    1475                 if (cancelled) { 
    1476                     System.out.println(tr("Warning: ignoring exception because task is cancelled. Exception: {0}", e 
    1477                             .toString())); 
    1478                     return; 
    1479                 } 
    1480                 lastException = e; 
    1481             } 
    1482         } 
    1483     } 
    14841410} 
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTable.java

    r2512 r2563  
    1818import javax.swing.KeyStroke; 
    1919import javax.swing.ListSelectionModel; 
     20import javax.swing.SwingUtilities; 
    2021import javax.swing.event.ListSelectionEvent; 
    2122import javax.swing.event.ListSelectionListener; 
     
    7172 
    7273        addMouseListener(new PopupListener()); 
     74        addMouseListener(new DblClickHandler()); 
    7375    } 
    7476 
     
    241243        return (MemberTableModel) getModel(); 
    242244    } 
     245 
     246    class DblClickHandler extends MouseAdapter { 
     247        protected void setSelection(MouseEvent e) { 
     248            int row = rowAtPoint(e.getPoint()); 
     249            if (row < 0) return; 
     250            OsmPrimitive primitive = getMemberTableModel().getReferredPrimitive(row); 
     251            getMemberTableModel().getLayer().data.setSelected(primitive.getPrimitiveId()); 
     252        } 
     253 
     254        protected void addSelection(MouseEvent e) { 
     255            int row = rowAtPoint(e.getPoint()); 
     256            if (row < 0) return; 
     257            OsmPrimitive primitive = getMemberTableModel().getReferredPrimitive(row); 
     258            getMemberTableModel().getSelectionModel().addSelectionInterval(row, row); 
     259            getMemberTableModel().getLayer().data.addSelected(primitive.getPrimitiveId()); 
     260 
     261        } 
     262 
     263        @Override 
     264        public void mouseClicked(MouseEvent e) { 
     265            if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() > 1) { 
     266                if (e.isControlDown()) { 
     267                    addSelection(e); 
     268                } else { 
     269                    setSelection(e); 
     270                } 
     271            } 
     272        } 
     273    } 
    243274} 
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableCellRenderer.java

    r2512 r2563  
    44import java.awt.Color; 
    55import java.awt.Component; 
    6 import java.util.ArrayList; 
    7 import java.util.Collections; 
    86 
    97import javax.swing.JLabel; 
    108import javax.swing.JTable; 
     9import javax.swing.UIManager; 
    1110import javax.swing.table.TableCellRenderer; 
    1211 
     
    1817 */ 
    1918public abstract class MemberTableCellRenderer extends JLabel implements TableCellRenderer { 
    20     public final static Color BGCOLOR_SELECTED = new Color(143, 170, 255); 
    2119    public final static Color BGCOLOR_EMPTY_ROW = new Color(234, 234, 234); 
     20    public final static Color BGCOLOR_IN_JOSM_SELECTION = new Color(235,255,177); 
    2221 
    2322    public final static Color BGCOLOR_NOT_IN_OPPOSITE = new Color(255, 197, 197); 
    24     public final static Color BGCOLOR_DOUBLE_ENTRY = new Color(255, 234, 213); 
     23    public final static Color BGCOLOR_DOUBLE_ENTRY = new Color(254,226,214); 
    2524 
    2625    /** 
     
    3231    } 
    3332 
    34     public String buildToolTipText(OsmPrimitive primitive) { 
    35         StringBuilder sb = new StringBuilder(); 
    36         sb.append("<html>"); 
    37         sb.append("<strong>id</strong>=").append(primitive.getId()).append("<br>"); 
    38         ArrayList<String> keyList = new ArrayList<String>(primitive.keySet()); 
    39         Collections.sort(keyList); 
    40         for (int i = 0; i < keyList.size(); i++) { 
    41             if (i > 0) { 
    42                 sb.append("<br>"); 
    43             } 
    44             String key = keyList.get(i); 
    45             sb.append("<strong>").append(key).append("</strong>").append("="); 
    46             String value = primitive.get(key); 
    47             while (value.length() != 0) { 
    48                 sb.append(value.substring(0, Math.min(50, value.length()))); 
    49                 if (value.length() > 50) { 
    50                     sb.append("<br>"); 
    51                     value = value.substring(50); 
    52                 } else { 
    53                     value = ""; 
    54                 } 
    55             } 
    56         } 
    57         sb.append("</html>"); 
    58         return sb.toString(); 
    59     } 
    60  
    6133    /** 
    6234     * reset the renderer 
    6335     */ 
    6436    protected void reset() { 
    65         setBackground(Color.WHITE); 
    66         setForeground(Color.BLACK); 
     37        setBackground(UIManager.getColor("Table.background")); 
     38        setForeground(UIManager.getColor("Table.foreground")); 
    6739        setBorder(null); 
    6840        setIcon(null); 
     
    7143 
    7244    protected void renderBackground(MemberTableModel model, OsmPrimitive primitive, boolean isSelected) { 
    73         Color bgc = Color.WHITE; 
     45        Color bgc = UIManager.getColor("Table.background"); 
    7446        if (isSelected) { 
    75             bgc = BGCOLOR_SELECTED; 
     47            bgc = UIManager.getColor("Table.selectionBackground"); 
     48        } else if (primitive != null && model.isInJosmSelection(primitive)) { 
     49            bgc = BGCOLOR_IN_JOSM_SELECTION; 
    7650        } else if (primitive != null && model.getNumMembersWithPrimitive(primitive) > 1) { 
    7751            bgc = BGCOLOR_DOUBLE_ENTRY; 
     
    8155 
    8256    protected void renderForeground(boolean isSelected) { 
    83         Color fgc = Color.BLACK; 
     57        Color fgc; 
     58        if (isSelected) { 
     59            fgc = UIManager.getColor("Table.selectionForeground"); 
     60        } else { 
     61            fgc = UIManager.getColor("Table.foreground"); 
     62        } 
    8463        setForeground(fgc); 
    8564    } 
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableMemberCellRenderer.java

    r2512 r2563  
    33 
    44import java.awt.Component; 
    5 import java.util.HashMap; 
    65 
    7 import javax.swing.ImageIcon; 
    86import javax.swing.JTable; 
    97 
    108import org.openstreetmap.josm.data.osm.OsmPrimitive; 
    11 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 
    129import org.openstreetmap.josm.gui.DefaultNameFormatter; 
    1310import org.openstreetmap.josm.tools.ImageProvider; 
    1411 
    1512public class MemberTableMemberCellRenderer extends MemberTableCellRenderer { 
    16     private HashMap<OsmPrimitiveType, ImageIcon> icons; 
    1713 
    1814    public MemberTableMemberCellRenderer() { 
    1915        super(); 
    20         loadIcons(); 
    21     } 
    22  
    23     /** 
    24      * Load the image icon for an OSM primitive of type node 
    25      * 
    26      * @return the icon; null, if not found 
    27      */ 
    28     protected void loadIcons() { 
    29         icons = new HashMap<OsmPrimitiveType, ImageIcon>(); 
    30         icons.put(OsmPrimitiveType.NODE, ImageProvider.get("data", "node")); 
    31         icons.put(OsmPrimitiveType.WAY, ImageProvider.get("data", "way")); 
    32         icons.put(OsmPrimitiveType.RELATION, ImageProvider.get("data", "relation")); 
    3316    } 
    3417 
    3518    protected void renderPrimitive(OsmPrimitive primitive) { 
    36         setIcon(icons.get(OsmPrimitiveType.from(primitive))); 
     19        setIcon(ImageProvider.get(primitive.getPrimitiveId().getType())); 
    3720        setText(primitive.getDisplayName(DefaultNameFormatter.getInstance())); 
    38         setToolTipText(buildToolTipText(primitive)); 
     21        setToolTipText(DefaultNameFormatter.getInstance().buildDefaultToolTip(primitive)); 
    3922    } 
    4023 
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java

    r2512 r2563  
    2626 
    2727import org.openstreetmap.josm.Main; 
     28import org.openstreetmap.josm.data.SelectionChangedListener; 
    2829import org.openstreetmap.josm.data.coor.EastNorth; 
     30import org.openstreetmap.josm.data.osm.DataSetListener; 
    2931import org.openstreetmap.josm.data.osm.Node; 
    3032import org.openstreetmap.josm.data.osm.OsmPrimitive; 
     
    3335import org.openstreetmap.josm.data.osm.Way; 
    3436import org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction; 
     37import org.openstreetmap.josm.gui.layer.DataChangeListener; 
    3538import org.openstreetmap.josm.gui.layer.OsmDataLayer; 
    3639 
    37 public class MemberTableModel extends AbstractTableModel implements TableModelListener { 
     40public class MemberTableModel extends AbstractTableModel implements TableModelListener, SelectionChangedListener, DataChangeListener, DataSetListener{ 
    3841 
    3942    /** 
     
    5659        addTableModelListener(this); 
    5760    } 
     61 
     62    public OsmDataLayer getLayer() { 
     63        return layer; 
     64    } 
     65 
     66    /* --------------------------------------------------------------------------- */ 
     67    /* Interface SelectionChangedListener                                          */ 
     68    /* --------------------------------------------------------------------------- */ 
     69    public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) { 
     70        if (Main.main.getEditLayer() != this.layer) return; 
     71        // just trigger a repaint 
     72        Collection<RelationMember> sel = getSelectedMembers(); 
     73        fireTableDataChanged(); 
     74        setSelectedMembers(sel); 
     75    } 
     76 
     77    /* --------------------------------------------------------------------------- */ 
     78    /* Interface DataChangeListener                                                */ 
     79    /* --------------------------------------------------------------------------- */ 
     80    public void dataChanged(OsmDataLayer l) { 
     81        if (l != this.layer) return; 
     82        // just trigger a repaint 
     83        Collection<RelationMember> sel = getSelectedMembers(); 
     84        fireTableDataChanged(); 
     85        setSelectedMembers(sel); 
     86    } 
     87    /* --------------------------------------------------------------------------- */ 
     88    /* Interface DataSetListener                                                   */ 
     89    /* --------------------------------------------------------------------------- */ 
     90    public void dataChanged() { 
     91        // just trigger a repaint - the display name of the relation members may 
     92        // have changed 
     93        Collection<RelationMember> sel = getSelectedMembers(); 
     94        fireTableDataChanged(); 
     95        setSelectedMembers(sel); 
     96    } 
     97 
     98    public void nodeMoved(Node node) {/* ignore */} 
     99    public void primtivesAdded(Collection<? extends OsmPrimitive> added) {/* ignore */} 
     100 
     101    public void primtivesRemoved(Collection<? extends OsmPrimitive> removed) { 
     102        // ignore - the relation in the editor might become out of sync with the relation 
     103        // in the dataset. We will deal with it when the relation editor is closed or 
     104        // when the changes in the editor are applied. 
     105    } 
     106 
     107    public void relationMembersChanged(Relation r) { 
     108        // ignore - the relation in the editor might become out of sync with the relation 
     109        // in the dataset. We will deal with it when the relation editor is closed or 
     110        // when the changes in the editor are applied. 
     111    } 
     112 
     113    public void tagsChanged(OsmPrimitive prim) { 
     114        // just refresh the respective table cells 
     115        // 
     116        Collection<RelationMember> sel = getSelectedMembers(); 
     117        for (int i=0; i < members.size();i++) { 
     118            if (members.get(i).getMember() == prim) { 
     119                fireTableCellUpdated(i, 1 /* the column with the primitive name */); 
     120            } 
     121        } 
     122        setSelectedMembers(sel); 
     123    } 
     124 
     125    public void wayNodesChanged(Way way) {/* ignore */} 
     126    /* --------------------------------------------------------------------------- */ 
    58127 
    59128    public void addMemberModelListener(IMemberModelListener listener) { 
     
    242311    } 
    243312 
     313    /** 
     314     * Replies the set of incomplete primitives 
     315     *  
     316     * @return the set of incomplete primitives 
     317     */ 
     318    public Set<OsmPrimitive> getIncompleteMemberPrimitives() { 
     319        Set<OsmPrimitive> ret = new HashSet<OsmPrimitive>(); 
     320        for (RelationMember member : members) { 
     321            if (member.getMember().incomplete) { 
     322                ret.add(member.getMember()); 
     323            } 
     324        } 
     325        return ret; 
     326    } 
     327 
     328    /** 
     329     * Replies the set of selected incomplete primitives 
     330     *  
     331     * @return the set of selected incomplete primitives 
     332     */ 
     333    public Set<OsmPrimitive> getSelectedIncompleteMemberPrimitives() { 
     334        Set<OsmPrimitive> ret = new HashSet<OsmPrimitive>(); 
     335        for (RelationMember member : getSelectedMembers()) { 
     336            if (member.getMember().incomplete) { 
     337                ret.add(member.getMember()); 
     338            } 
     339        } 
     340        return ret; 
     341    } 
     342 
     343    /** 
     344     * Replies true if at least one the relation members is incomplete 
     345     *  
     346     * @return true if at least one the relation members is incomplete 
     347     */ 
    244348    public boolean hasIncompleteMembers() { 
    245349        for (RelationMember member : members) { 
     350            if (member.getMember().incomplete) 
     351                return true; 
     352        } 
     353        return false; 
     354    } 
     355 
     356    /** 
     357     * Replies true if at least one of the selected members is incomplete 
     358     *  
     359     * @return true if at least one of the selected members is incomplete 
     360     */ 
     361    public boolean hasIncompleteSelectedMembers() { 
     362        for (RelationMember member : getSelectedMembers()) { 
    246363            if (member.getMember().incomplete) 
    247364                return true; 
     
    408525 
    409526    /** 
    410      * Replies true, if the selected {@see OsmPrimitive}s in the layer belonging 
    411      * to this model are in sync with the selected referers in this model. 
    412      * 
    413      * @return 
    414      */ 
    415     public boolean selectionsAreInSync() { 
    416         HashSet<OsmPrimitive> s1 = new HashSet<OsmPrimitive>(getSelectedChildPrimitives()); 
    417         if (s1.size() != layer.data.getSelected().size()) return false; 
    418         s1.removeAll(layer.data.getSelected()); 
    419         return s1.isEmpty(); 
    420     } 
    421     /** 
    422527     * Selects the members in the collection selectedMembers 
    423528     * 
     
    425530     */ 
    426531    public void setSelectedMembers(Collection<RelationMember> selectedMembers) { 
    427         if (selectedMembers == null || selectedMembers.isEmpty()) 
     532        if (selectedMembers == null || selectedMembers.isEmpty()) { 
     533            getSelectionModel().clearSelection(); 
    428534            return; 
     535        } 
    429536 
    430537        // lookup the indices for the respective members 
    431538        // 
    432         ArrayList<Integer> selectedIndices = new ArrayList<Integer>(); 
     539        Set<Integer> selectedIndices = new HashSet<Integer>(); 
    433540        for (RelationMember member : selectedMembers) { 
    434             for (int idx = 0; idx < members.size(); idx ++) { 
    435                 if (members.get(idx).equals(member)) { 
    436                     if (!selectedIndices.contains(idx)) { 
    437                         selectedIndices.add(idx); 
    438                     } 
    439                 } 
     541            int idx = members.indexOf(member); 
     542            if ( idx >= 0) { 
     543                selectedIndices.add(idx); 
    440544            } 
    441545        } 
     
    443547        // select the members 
    444548        // 
    445         Collections.sort(selectedIndices); 
    446549        getSelectionModel().setValueIsAdjusting(true); 
    447550        getSelectionModel().clearSelection(); 
     
    450553        } 
    451554        getSelectionModel().setValueIsAdjusting(false); 
    452  
    453555        // make the first selected member visible 
    454556        // 
    455557        if (selectedIndices.size() > 0) { 
    456             fireMakeMemberVisible(selectedIndices.get(0)); 
     558            fireMakeMemberVisible(Collections.min(selectedIndices)); 
    457559        } 
    458560    } 
     
    523625            fireMakeMemberVisible(getSelectedIndices().get(0)); 
    524626        } 
     627    } 
     628 
     629    /** 
     630     * Replies true if <code>primitive</code> is currently selected in the layer this 
     631     * model is attached to 
     632     *  
     633     * @param primitive the primitive 
     634     * @return true if <code>primitive</code> is currently selected in the layer this 
     635     * model is attached to, false otherwise 
     636     */ 
     637    public boolean isInJosmSelection(OsmPrimitive primitive) { 
     638        return layer.data.isSelected(primitive); 
    525639    } 
    526640 
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java

    r2512 r2563  
    44import static org.openstreetmap.josm.tools.I18n.tr; 
    55 
     6import java.beans.PropertyChangeListener; 
     7import java.beans.PropertyChangeSupport; 
    68import java.lang.reflect.Constructor; 
    79import java.lang.reflect.Method; 
     
    1618 
    1719public abstract class RelationEditor extends ExtendedDialog { 
     20    /** the property name for the current relation. 
     21     * @see #setRelation(Relation) 
     22     * @see #getRelation() 
     23     */ 
     24    static public final String RELATION_PROP = RelationEditor.class.getName() + ".relation"; 
     25 
     26    /** the property name for the current relation snapshot 
     27     * @see #getRelationSnapshot() 
     28     */ 
     29    static public final String RELATION_SNAPSHOT_PROP = RelationEditor.class.getName() + ".relationSnapshot"; 
    1830 
    1931    /** the list of registered relation editor classes */ 
     
    6274     * then an instance of that class will be used. 
    6375     * 
     76     * @param layer the data layer the relation is a member of 
    6477     * @param r the relation to be edited 
     78     * @param selectedMembers a collection of relation members which shall be selected when the 
     79     * editor is first launched 
    6580     * @return an instance of RelationEditor suitable for editing that kind of relation 
    6681     */ 
     
    139154     */ 
    140155    protected void setRelation(Relation relation) { 
    141         this.relationSnapshot = (relation == null) ? null : new Relation(relation); 
     156        setRelationSnapshot((relation == null) ? null : new Relation(relation)); 
     157        Relation oldValue = this.relation; 
    142158        this.relation = relation; 
     159        if (this.relation != oldValue) { 
     160            support.firePropertyChange(RELATION_PROP, oldValue, this.relation); 
     161        } 
    143162        updateTitle(); 
    144163    } 
     
    164183    } 
    165184 
     185    protected void setRelationSnapshot(Relation snapshot) { 
     186        Relation oldValue = relationSnapshot; 
     187        relationSnapshot = snapshot; 
     188        if (relationSnapshot != oldValue) { 
     189            support.firePropertyChange(RELATION_SNAPSHOT_PROP, oldValue, relationSnapshot); 
     190        } 
     191    } 
     192 
    166193    /** 
    167194     * Replies true if the currently edited relation has been changed elsewhere. 
     
    175202        return ! relation.hasEqualSemanticAttributes(relationSnapshot); 
    176203    } 
     204 
     205 
     206    /* ----------------------------------------------------------------------- */ 
     207    /* property change support                                                 */ 
     208    /* ----------------------------------------------------------------------- */ 
     209    final private PropertyChangeSupport support = new PropertyChangeSupport(this); 
     210 
     211    @Override 
     212    public void addPropertyChangeListener(PropertyChangeListener listener) { 
     213        this.support.addPropertyChangeListener(listener); 
     214    } 
     215 
     216    @Override 
     217    public void removePropertyChangeListener(PropertyChangeListener listener) { 
     218        this.support.removePropertyChangeListener(listener); 
     219    } 
    177220} 
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/SelectionTableCellRenderer.java

    r2512 r2563  
    44import java.awt.Color; 
    55import java.awt.Component; 
    6 import java.util.ArrayList; 
    7 import java.util.Collections; 
    8 import java.util.HashMap; 
    96 
    10 import javax.swing.ImageIcon; 
    117import javax.swing.JLabel; 
    128import javax.swing.JTable; 
     9import javax.swing.UIManager; 
    1310import javax.swing.table.TableCellRenderer; 
    1411 
    1512import org.openstreetmap.josm.data.osm.OsmPrimitive; 
    16 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 
    1713import org.openstreetmap.josm.gui.DefaultNameFormatter; 
    1814import org.openstreetmap.josm.tools.ImageProvider; 
    1915 
    2016/** 
    21  * This is the {@see TableCellRenderer} used in the tables of {@see RelationMemberMerger}. 
     17 * This is the {@see TableCellRenderer} used in {@see SelectionTable}. 
    2218 * 
    2319 */ 
    2420public  class SelectionTableCellRenderer extends JLabel implements TableCellRenderer { 
    25     public final static Color BGCOLOR_SELECTED = new Color(143,170,255); 
    26     public final static Color BGCOLOR_DOUBLE_ENTRY = new Color(255,234,213); 
     21    public final static Color BGCOLOR_DOUBLE_ENTRY = new Color(254,226,214); 
     22    public final static Color BGCOLOR_SINGLE_ENTRY = new Color(235,255,177); 
    2723 
    28     private HashMap<OsmPrimitiveType, ImageIcon>  icons; 
    2924    /** 
    3025     * reference to the member table model; required, in order to check whether a 
     
    3530 
    3631    /** 
    37      * Load the image icon for an OSM primitive of type node 
    38      * 
    39      * @return the icon; null, if not found 
    40      */ 
    41     protected void loadIcons() { 
    42         icons = new HashMap<OsmPrimitiveType, ImageIcon>(); 
    43         icons.put(OsmPrimitiveType.NODE,ImageProvider.get("data", "node")); 
    44         icons.put(OsmPrimitiveType.WAY, ImageProvider.get("data", "way")); 
    45         icons.put(OsmPrimitiveType.RELATION, ImageProvider.get("data", "relation")); 
    46     } 
    47  
    48     /** 
    4932     * constructor 
    5033     */ 
     
    5235        setIcon(null); 
    5336        setOpaque(true); 
    54         loadIcons(); 
    55     } 
    56  
    57     public String buildToolTipText(OsmPrimitive primitive) { 
    58         StringBuilder sb = new StringBuilder(); 
    59         sb.append("<html>"); 
    60         sb.append("<strong>id</strong>=") 
    61         .append(primitive.getId()) 
    62         .append("<br>"); 
    63         ArrayList<String> keyList = new ArrayList<String>(primitive.keySet()); 
    64         Collections.sort(keyList); 
    65         for (int i = 0; i < keyList.size(); i++) { 
    66             if (i > 0) { 
    67                 sb.append("<br>"); 
    68             } 
    69             String key = keyList.get(i); 
    70             sb.append("<strong>") 
    71             .append(key) 
    72             .append("</strong>") 
    73             .append("="); 
    74             String value = primitive.get(key); 
    75             while(value.length() != 0) { 
    76                 sb.append(value.substring(0,Math.min(50, value.length()))); 
    77                 if (value.length() > 50) { 
    78                     sb.append("<br>"); 
    79                     value = value.substring(50); 
    80                 } else { 
    81                     value = ""; 
    82                 } 
    83             } 
    84         } 
    85         sb.append("</html>"); 
    86         return sb.toString(); 
    8737    } 
    8838 
     
    9141     */ 
    9242    protected void reset() { 
    93         setBackground(Color.WHITE); 
    94         setForeground(Color.BLACK); 
     43        setBackground(UIManager.getColor("Table.background")); 
     44        setForeground(UIManager.getColor("Table.foreground")); 
    9545        setBorder(null); 
    9646        setIcon(null); 
     
    9949 
    10050    protected void renderBackground(OsmPrimitive primitive, boolean isSelected) { 
    101         Color bgc = Color.WHITE; 
    102         if (isSelected) { 
    103             bgc = BGCOLOR_SELECTED; 
    104         } else if (primitive != null && model != null && model.getNumMembersWithPrimitive(primitive) > 0) { 
     51        Color bgc = UIManager.getColor("Table.background"); 
     52        if (primitive != null && model != null && model.getNumMembersWithPrimitive(primitive) == 1) { 
     53            bgc = BGCOLOR_SINGLE_ENTRY; 
     54        } else if (primitive != null && model != null && model.getNumMembersWithPrimitive(primitive) > 1) { 
    10555            bgc = BGCOLOR_DOUBLE_ENTRY; 
    10656        } 
     
    10858    } 
    10959 
    110     protected void renderForeground(boolean isSelected) { 
    111         Color fgc = Color.BLACK; 
    112         setForeground(fgc); 
    113     } 
    11460 
    11561    protected void renderPrimitive(OsmPrimitive primitive) { 
    116         setIcon(icons.get(OsmPrimitiveType.from(primitive))); 
     62        setIcon(ImageProvider.get(primitive.getPrimitiveId().getType())); 
    11763        setText(primitive.getDisplayName(DefaultNameFormatter.getInstance())); 
    118         setToolTipText(buildToolTipText(primitive)); 
     64        setToolTipText(DefaultNameFormatter.getInstance().buildDefaultToolTip(primitive)); 
    11965    } 
    12066 
     
    12369 
    12470        reset(); 
    125         renderForeground(isSelected); 
    12671        renderBackground((OsmPrimitive)value, isSelected); 
    12772        renderPrimitive((OsmPrimitive)value); 
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/SelectionTableModel.java

    r2512 r2563  
    3434        this.layer = layer; 
    3535        cache = new ArrayList<OsmPrimitive>(); 
    36         DataSet.selListeners.add(this); 
    3736        Layer.listeners.add(this); 
    3837        populateSelectedPrimitives(layer); 
     
    103102        selectionChanged(layer.data.getSelected()); 
    104103    } 
     104 
     105    /** 
     106     * Replies the primitive at row <code>row</code> in this model 
     107     *  
     108     * @param row the row 
     109     * @return  the primitive at row <code>row</code> in this model 
     110     */ 
     111    public OsmPrimitive getPrimitive(int row) { 
     112        return cache.get(row); 
     113    } 
    105114} 
  • trunk/src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java

    r2512 r2563  
    33 
    44import static org.openstreetmap.josm.tools.I18n.tr; 
     5import static org.openstreetmap.josm.tools.I18n.trn; 
    56 
    67import java.io.InputStream; 
     
    308309        progressMonitor.subTask(tr("Downloading OSM data...")); 
    309310        try { 
    310  
    311             merge( 
    312                     OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)) 
    313             ); 
     311            DataSet loaded = OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)); 
     312            rememberNodesOfIncompleteWaysToLoad(loaded); 
     313            merge(loaded); 
    314314        } catch(Exception e) { 
    315315            throw new OsmTransferException(e); 
     
    333333        progressMonitor.subTask(tr("Downloading OSM data...")); 
    334334        try { 
    335             merge( 
    336                     OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)) 
    337             ); 
     335            DataSet loaded = OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)); 
     336            rememberNodesOfIncompleteWaysToLoad(loaded); 
     337            merge(loaded); 
    338338        } catch(Exception e) { 
    339339            throw new OsmTransferException(e); 
     
    376376    } 
    377377 
     378    protected void rememberNodesOfIncompleteWaysToLoad(DataSet from) { 
     379        for (Way w: from.getWays()) { 
     380            if (w.incomplete) { 
     381                for (Node n: w.getNodes()) { 
     382                    if (n.incomplete) { 
     383                        nodes.add(n.getId()); 
     384                    } 
     385                } 
     386            } 
     387        } 
     388    } 
     389 
    378390    /** 
    379391     * merges the dataset <code>from</code> to {@see #outputDataSet}. 
     
    401413        case RELATION:  msg = tr("Fetching a package of relations from ''{0}''", OsmApi.getOsmApi().getBaseUrl()); break; 
    402414        } 
    403         progressMonitor.setCustomText(msg); 
     415        progressMonitor.indeterminateSubTask(msg); 
    404416        Set<Long> toFetch = new HashSet<Long>(ids); 
    405417        toFetch.addAll(ids); 
     
    428440     * found on  the server (the server response code was 404) 
    429441     * 
    430      * Invoke {@see #getSkippedWay()} to get a list of ways which this reader could not build from 
    431      * the fetched data because the ways refer to nodes which don't exist on the server. 
    432      * 
    433442     * @return the parsed data 
    434443     * @exception OsmTransferException thrown if an error occurs while communicating with the API server 
    435444     * @see #getMissingPrimitives() 
    436      * @see #getSkippedWays() 
    437      * 
    438  
     445     * 
    439446     */ 
    440447    @Override 
    441448    public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException { 
    442         progressMonitor.beginTask(""); 
     449        int n = nodes.size() + ways.size() + relations.size(); 
     450        progressMonitor.beginTask(trn("Downloading {0} object from ''{1}''", "Downloading {0} objects from ''{1}''", n, n, OsmApi.getOsmApi().getBaseUrl())); 
    443451        try { 
    444452            missingPrimitives = new HashSet<Long>(); 
    445453            if (isCanceled())return null; 
     454            fetchPrimitives(ways,OsmPrimitiveType.WAY, progressMonitor); 
     455            if (isCanceled())return null; 
    446456            fetchPrimitives(nodes,OsmPrimitiveType.NODE, progressMonitor); 
    447             if (isCanceled())return null; 
    448             fetchPrimitives(ways,OsmPrimitiveType.WAY, progressMonitor); 
    449457            if (isCanceled())return null; 
    450458            fetchPrimitives(relations,OsmPrimitiveType.RELATION, progressMonitor); 
  • trunk/src/org/openstreetmap/josm/io/OsmReader.java

    r2512 r2563  
    1212import java.util.List; 
    1313import java.util.Map; 
     14import java.util.logging.Level; 
    1415import java.util.logging.Logger; 
    1516 
     
    443444            w.setNodes(wayNodes); 
    444445            if (incomplete) { 
    445                 logger.warning(tr("Marked way {0} with {1} nodes incomplete because at least one node was missing in the " + 
    446                         "loaded data and is therefore incomplete too.", externalWayId, w.getNodesCount())); 
     446                if (logger.isLoggable(Level.FINE)) { 
     447                    logger.fine(tr("Marked way {0} with {1} nodes incomplete because at least one node was missing in the " + 
     448                            "loaded data and is therefore incomplete too.", externalWayId, w.getNodesCount())); 
     449                } 
    447450                w.incomplete = true; 
    448451                ds.addPrimitive(w); 
  • trunk/src/org/openstreetmap/josm/io/OsmServerObjectReader.java

    r2484 r2563  
    99import org.openstreetmap.josm.data.osm.DataSet; 
    1010import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 
     11import org.openstreetmap.josm.data.osm.PrimitiveId; 
     12import org.openstreetmap.josm.data.osm.SimplePrimitiveId; 
     13import org.openstreetmap.josm.gui.progress.NullProgressMonitor; 
    1114import org.openstreetmap.josm.gui.progress.ProgressMonitor; 
    1215import org.xml.sax.SAXException; 
    1316 
     17/** 
     18 * OsmServerObjectReader reads an individual object from the OSM server. 
     19 *  
     20 * It can either download the object including or not including its immediate children. 
     21 * The former case is called a "full download". 
     22 *  
     23 */ 
    1424public class OsmServerObjectReader extends OsmServerReader { 
     25    /** the id of the object to download */ 
     26    private PrimitiveId id; 
     27    /** true if a full download is required, i.e. a download including the immediate children */ 
     28    private boolean full; 
    1529 
    16     long id; 
    17     OsmPrimitiveType type; 
    18     boolean full; 
    19  
    20     public OsmServerObjectReader(long id, OsmPrimitiveType type, boolean full) { 
    21         this.id = id; 
    22         this.type = type; 
     30    /** 
     31     * Creates a new server object reader for a given id and a primitive type. 
     32     *  
     33     * @param id the object id. > 0 required. 
     34     * @param type the type. Must not be null. 
     35     * @param full true, if a full download is requested (i.e. a download including 
     36     * immediate children); false, otherwise 
     37     * @throws IllegalArgumentException thrown if id <= 0 
     38     * @throws IllegalArgumentException thrown if type is null 
     39     */ 
     40    public OsmServerObjectReader(long id, OsmPrimitiveType type, boolean full) throws IllegalArgumentException { 
     41        if (id <= 0) 
     42            throw new IllegalArgumentException(tr("Expected value > 0 for parameter ''{0}'', got {1}", "id", id)); 
     43        if (type == null) 
     44            throw new IllegalArgumentException(tr("Parameter ''{0}'' must not be null", "type")); 
     45        this.id = new SimplePrimitiveId(id, type); 
    2346        this.full = full; 
    2447    } 
     48 
    2549    /** 
    26      * Method to download single objects from OSM server. ways, relations, nodes 
    27      * @return the data requested 
     50     * Creates a new server object reader for an object with the given <code>id</code> 
     51     *  
     52     * @param id the object id. Must not be null. Unique id > 0 required. 
     53     * @param full true, if a full download is requested (i.e. a download including 
     54     * immediate children); false, otherwise 
     55     * @throws IllegalArgumentException thrown if id is null 
     56     * @throws IllegalArgumentException thrown if id.getUniqueId() <= 0 
     57     */ 
     58    public OsmServerObjectReader(PrimitiveId id, boolean full) { 
     59        if (id == null) 
     60            throw new IllegalArgumentException(tr("Parameter ''{0}'' must not be null", "id")); 
     61        if (id.getUniqueId() <= 0) 
     62            throw new IllegalArgumentException(tr("Expected value > 0 for parameter ''{0}'', got {1}", "id.getUniqueId()", id.getUniqueId())); 
     63        this.id = id; 
     64        this.full = full; 
     65    } 
     66 
     67    /** 
     68     * Downloads and parses the data. 
     69     *  
     70     * @param progressMonitor the progress monitor. Set to {@see NullProgressMonitor#INSTANCE} if 
     71     * null 
     72     * @return the downloaded data 
    2873     * @throws SAXException 
    2974     * @throws IOException 
     
    3176    @Override 
    3277    public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException { 
     78        if (progressMonitor == null) { 
     79            progressMonitor = NullProgressMonitor.INSTANCE; 
     80        } 
    3381        progressMonitor.beginTask("", 1); 
    3482        InputStream in = null; 
     
    3684            progressMonitor.indeterminateSubTask(tr("Downloading OSM data...")); 
    3785            StringBuffer sb = new StringBuffer(); 
    38             sb.append(type.getAPIName()); 
     86            sb.append(id.getType().getAPIName()); 
    3987            sb.append("/"); 
    40             sb.append(id); 
    41             if (full && ! type.equals(OsmPrimitiveType.NODE)) { 
     88            sb.append(id.getUniqueId()); 
     89            if (full && ! id.getType().equals(OsmPrimitiveType.NODE)) { 
    4290                sb.append("/full"); 
    4391            } 
     
    59107                try { 
    60108                    in.close(); 
    61                 } catch(Exception e) {} 
     109                } catch(Exception e) {/* ignore this exception */} 
    62110            } 
    63111            activeConnection = null; 
    64112        } 
    65113    } 
    66  
    67114} 
  • trunk/test/unit/org/openstreetmap/josm/data/osm/DataSetMergerTest.java

    r2498 r2563  
    33 
    44import static org.junit.Assert.assertEquals; 
     5import static org.junit.Assert.assertFalse; 
    56import static org.junit.Assert.assertNotNull; 
    67import static org.junit.Assert.assertTrue; 
     
    991992    @Test 
    992993    public void newIncompleteWay() { 
    993         DataSet their = new DataSet(); 
    994         their.setVersion("0.6"); 
     994        DataSet source = new DataSet(); 
     995        source.setVersion("0.6"); 
    995996 
    996997        Node n1 = new Node(1); 
    997         their.addPrimitive(n1); 
     998        source.addPrimitive(n1); 
    998999 
    9991000        Node n2 = new Node(2); 
    1000         their.addPrimitive(n2); 
     1001        source.addPrimitive(n2); 
    10011002 
    10021003        Way w3 = new Way(3); 
    10031004        w3.setNodes(Arrays.asList(n1,n2)); 
    1004         their.addPrimitive(w3); 
    1005  
    1006         DataSet my = new DataSet(); 
    1007         their.setVersion("0.6"); 
    1008  
    1009         DataSetMerger visitor = new DataSetMerger(my,their); 
    1010         visitor.merge(); 
    1011  
    1012         assertEquals(0,visitor.getConflicts().size()); 
    1013  
    1014         OsmPrimitive p= my.getPrimitiveById(1, OsmPrimitiveType.NODE); 
     1005        source.addPrimitive(w3); 
     1006        assertTrue(w3.incomplete); 
     1007 
     1008        DataSet target = new DataSet(); 
     1009        target.setVersion("0.6"); 
     1010 
     1011        DataSetMerger visitor = new DataSetMerger(target,source); 
     1012        visitor.merge(); 
     1013 
     1014        assertEquals(0,visitor.getConflicts().size()); 
     1015 
     1016        OsmPrimitive p= target.getPrimitiveById(1, OsmPrimitiveType.NODE); 
    10151017        assertNotNull(p); 
    10161018        assertTrue(p.incomplete); 
    1017         p= my.getPrimitiveById(2, OsmPrimitiveType.NODE); 
     1019        p= target.getPrimitiveById(2, OsmPrimitiveType.NODE); 
    10181020        assertNotNull(p); 
    10191021        assertTrue(p.incomplete); 
    1020         p= my.getPrimitiveById(3, OsmPrimitiveType.WAY); 
     1022        p= target.getPrimitiveById(3, OsmPrimitiveType.WAY); 
    10211023        assertNotNull(p); 
    10221024        assertTrue(p.incomplete); 
    10231025 
    1024         Way w = (Way)my.getPrimitiveById(3, OsmPrimitiveType.WAY); 
     1026        Way w = (Way)target.getPrimitiveById(3, OsmPrimitiveType.WAY); 
    10251027        assertNotNull(w); 
    10261028        assertTrue(p.incomplete); 
     
    10541056 
    10551057        DataSet my = new DataSet(); 
    1056         their.setVersion("0.6"); 
     1058        my.setVersion("0.6"); 
    10571059 
    10581060        Node n4 = new Node(new LatLon(0,0)); 
     
    10921094    } 
    10931095 
     1096    /** 
     1097     * merge to complete nodes onto an incomplete way with the same two nodes, but incomplete. 
     1098     * => both the nodes and the way should be complete in the target dataset after merging 
     1099     */ 
     1100    @Test 
     1101    public void twoCompleteNodesOntoAnIncompleteWay() { 
     1102 
     1103        // -- source dataset 
     1104        DataSet source = new DataSet(); 
     1105        source.setVersion("0.6"); 
     1106 
     1107        // an complete node 
     1108        Node n1 = new Node(1); 
     1109        n1.setCoor(new LatLon(1,1)); 
     1110        n1.incomplete = false; 
     1111        source.addPrimitive(n1); 
     1112 
     1113        // another complete node 
     1114        Node n2 = new Node(2); 
     1115        n2.setCoor(new LatLon(2,2)); 
     1116        n2.incomplete = false; 
     1117        source.addPrimitive(n2); 
     1118 
     1119        // --- target daset 
     1120        DataSet target = new DataSet(); 
     1121        target.setVersion("0.6"); 
     1122 
     1123        Node n4 = new Node(1); 
     1124        target.addPrimitive(n4); 
     1125 
     1126        Node n5 = new Node(2); 
     1127        target.addPrimitive(n5); 
     1128 
     1129        Way w6 = new Way(3); 
     1130        w6.incomplete = false; 
     1131        w6.addNode(n4); 
     1132        w6.addNode(n5); 
     1133        w6.incomplete = true; 
     1134        target.addPrimitive(w6); 
     1135 
     1136        //-- merge it 
     1137        DataSetMerger visitor = new DataSetMerger(target,source); 
     1138        visitor.merge(); 
     1139 
     1140        // -- test it 
     1141        assertEquals(0,visitor.getConflicts().size()); 
     1142 
     1143        Node n = (Node)target.getPrimitiveById(1, OsmPrimitiveType.NODE); 
     1144        assertNotNull(n); 
     1145        assertFalse(n.incomplete); 
     1146 
     1147        n = (Node)target.getPrimitiveById(2, OsmPrimitiveType.NODE); 
     1148        assertNotNull(n); 
     1149        assertFalse(n.incomplete); 
     1150 
     1151        Way w = (Way)target.getPrimitiveById(3, OsmPrimitiveType.WAY); 
     1152        assertNotNull(w); 
     1153        assertFalse(w.incomplete); 
     1154        assertEquals(2, w.getNodesCount()); 
     1155        assertEquals(1, w.getNode(0).getId()); 
     1156        assertEquals(2, w.getNode(1).getId()); 
     1157    } 
    10941158} 
Note: See TracChangeset for help on using the changeset viewer.