Changeset 1856 in josm


Ignore:
Timestamp:
2009-07-26T17:03:00+02:00 (15 years ago)
Author:
Gubaer
Message:

improved deleting relations

Location:
trunk/src/org/openstreetmap/josm
Files:
1 added
12 edited

Legend:

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

    r1821 r1856  
    1313import org.openstreetmap.josm.command.Command;
    1414import org.openstreetmap.josm.command.DeleteCommand;
     15import org.openstreetmap.josm.data.osm.DataSet;
    1516import org.openstreetmap.josm.data.osm.OsmPrimitive;
     17import org.openstreetmap.josm.data.osm.Relation;
    1618import org.openstreetmap.josm.data.osm.WaySegment;
    1719import org.openstreetmap.josm.gui.MapFrame;
     20import org.openstreetmap.josm.gui.dialogs.relation.RelationDialogManager;
    1821import org.openstreetmap.josm.gui.layer.Layer;
    1922import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     
    7982        Command c;
    8083        if (ctrl) {
    81             c = DeleteCommand.deleteWithReferences(getCurrentDataSet().getSelected());
     84            c = DeleteCommand.deleteWithReferences(getEditLayer(),getCurrentDataSet().getSelected());
    8285        } else {
    83             c = DeleteCommand.delete(getCurrentDataSet().getSelected(), !alt);
     86            c = DeleteCommand.delete(getEditLayer(),getCurrentDataSet().getSelected(), !alt);
    8487        }
    8588        if (c != null) {
     
    110113            if (ws != null) {
    111114                if (shift) {
    112                     c = DeleteCommand.deleteWaySegment(ws);
     115                    c = DeleteCommand.deleteWaySegment(getEditLayer(),ws);
    113116                } else if (ctrl) {
    114                     c = DeleteCommand.deleteWithReferences(Collections.singleton((OsmPrimitive)ws.way));
     117                    c = DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton((OsmPrimitive)ws.way));
    115118                } else {
    116                     c = DeleteCommand.delete(Collections.singleton((OsmPrimitive)ws.way), !alt);
     119                    c = DeleteCommand.delete(getEditLayer(),Collections.singleton((OsmPrimitive)ws.way), !alt);
    117120                }
    118121            }
    119122        } else if (ctrl) {
    120             c = DeleteCommand.deleteWithReferences(Collections.singleton(sel));
     123            c = DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton(sel));
    121124        } else {
    122             c = DeleteCommand.delete(Collections.singleton(sel), !alt);
     125            c = DeleteCommand.delete(getEditLayer(),Collections.singleton(sel), !alt);
    123126        }
    124127        if (c != null) {
     
    142145        setEnabled(Main.map != null && Main.map.mapView != null && Main.map.mapView.isActiveLayerDrawable());
    143146    }
     147
     148    /**
     149     * Deletes the relation in the context of the given layer. Also notifies
     150     * {@see RelationDialogManager} and {@see OsmDataLayer#fireDataChange()} events.
     151     *
     152     * @param layer the layer in whose context the relation is deleted. Must not be null.
     153     * @param toDelete  the relation to be deleted. Must  not be null.
     154     * @exception IllegalArgumentException thrown if layer is null
     155     * @exception IllegalArgumentException thrown if toDelete is nul
     156     */
     157    public static void deleteRelation(OsmDataLayer layer, Relation toDelete) {
     158        if (layer == null)
     159            throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "layer"));
     160        if (toDelete == null)
     161            throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "toDelete"));
     162        if (toDelete == null)
     163            return;
     164        Command cmd = DeleteCommand.delete(layer, Collections.singleton(toDelete));
     165        if (cmd != null) {
     166            // cmd can be null if the user cancels dialogs DialogCommand displays
     167            //
     168            Main.main.undoRedo.add(cmd);
     169            RelationDialogManager.getRelationDialogManager().close(layer, toDelete);
     170            layer.fireDataChange();
     171        }
     172    }
    144173}
  • trunk/src/org/openstreetmap/josm/command/Command.java

    r1814 r1856  
    5353        this.layer = Main.map.mapView.getEditLayer();
    5454    }
     55
     56    /**
     57     * Creates a new command in the context of a specific data layer
     58     *
     59     * @param layer the data layer
     60     */
     61    public Command(OsmDataLayer layer) {
     62        this.layer = layer;
     63    }
     64
    5565    /**
    5666     * Executes the command on the dataset. This implementation will remember all
  • trunk/src/org/openstreetmap/josm/command/DeleteCommand.java

    r1838 r1856  
    3434import org.openstreetmap.josm.gui.ExtendedDialog;
    3535import org.openstreetmap.josm.gui.PrimitiveNameFormatter;
     36import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    3637import org.openstreetmap.josm.tools.ImageProvider;
    3738
     
    6364    }
    6465
    65     @Override public boolean executeCommand() {
     66    /**
     67     * Constructor for a single data item. Use the collection constructor to delete multiple
     68     * objects.
     69     *
     70     * @param layer the layer context for deleting this primitive
     71     * @param data the primitive to delete
     72     */
     73    public DeleteCommand(OsmDataLayer layer, OsmPrimitive data) {
     74        super(layer);
     75        this.toDelete = Collections.singleton(data);
     76    }
     77
     78    /**
     79     * Constructor for a collection of data to be deleted in the context of
     80     * a specific layer
     81     *
     82     * @param layer the layer context for deleting these primitives
     83     * @param data the primitives to delete
     84     */
     85    public DeleteCommand(OsmDataLayer layer, Collection<? extends OsmPrimitive> data) {
     86        super(layer);
     87        this.toDelete = data;
     88    }
     89
     90    @Override
     91    public boolean executeCommand() {
    6692        super.executeCommand();
    6793        for (OsmPrimitive osm : toDelete) {
     
    7197    }
    7298
    73     @Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
     99    @Override
     100    public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
    74101            Collection<OsmPrimitive> added) {
    75102        deleted.addAll(toDelete);
    76103    }
    77104
    78     @Override public MutableTreeNode description() {
     105    @Override
     106    public MutableTreeNode description() {
    79107        if (toDelete.size() == 1) {
    80108            OsmPrimitive primitive = toDelete.iterator().next();
    81             return new DefaultMutableTreeNode(
    82                     new JLabel(
    83                             tr("Delete {1} {0}",
    84                                     new PrimitiveNameFormatter().getName(primitive),
    85                                     OsmPrimitiveType.from(primitive).getLocalizedDisplayNameSingular()
    86                             ),
    87                             ImageProvider.get(OsmPrimitiveType.from(primitive)),
    88                             JLabel.HORIZONTAL));
     109            return new DefaultMutableTreeNode(new JLabel(tr("Delete {1} {0}", new PrimitiveNameFormatter()
     110            .getName(primitive), OsmPrimitiveType.from(primitive).getLocalizedDisplayNameSingular()),
     111            ImageProvider.get(OsmPrimitiveType.from(primitive)), JLabel.HORIZONTAL));
    89112        }
    90113
     
    106129                cname, cnamem, toDelete.size())), ImageProvider.get("data", apiname), JLabel.HORIZONTAL));
    107130        for (OsmPrimitive osm : toDelete) {
    108             root.add(new DefaultMutableTreeNode(
    109                     new JLabel(
    110                             new PrimitiveNameFormatter().getName(osm),
    111                             ImageProvider.get(OsmPrimitiveType.from(osm)),
    112                             JLabel.HORIZONTAL)
    113             )
    114             );
     131            root.add(new DefaultMutableTreeNode(new JLabel(new PrimitiveNameFormatter().getName(osm), ImageProvider
     132                    .get(OsmPrimitiveType.from(osm)), JLabel.HORIZONTAL)));
    115133        }
    116134        return root;
     
    119137    /**
    120138     * Delete the primitives and everything they reference.
    121      *
     139     * 
    122140     * If a node is deleted, the node and all ways and relations the node is part of are deleted as
    123141     * well.
    124      *
     142     * 
    125143     * If a way is deleted, all relations the way is member of are also deleted.
    126      *
     144     * 
    127145     * If a way is deleted, only the way and no nodes are deleted.
    128      *
     146     * 
    129147     * @param selection The list of all object to be deleted.
    130148     * @return command A command to perform the deletions, or null of there is nothing to delete.
    131149     */
    132     public static Command deleteWithReferences(Collection<? extends OsmPrimitive> selection) {
    133         CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.main.getCurrentDataSet());
     150    public static Command deleteWithReferences(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection) {
     151        CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data);
    134152        for (OsmPrimitive osm : selection) {
    135153            osm.visit(v);
     
    138156        if (v.data.isEmpty())
    139157            return null;
    140         if (!checkAndConfirmOutlyingDeletes(v.data))
     158        if (!checkAndConfirmOutlyingDeletes(layer,v.data))
    141159            return null;
    142         return new DeleteCommand(v.data);
     160        return new DeleteCommand(layer,v.data);
    143161    }
    144162
     
    153171        }
    154172        if (role.length() > 0)
    155             return new ExtendedDialog(
    156                     Main.parent,
    157                     tr("Conflicting relation"),
    158                     tr("Selection \"{0}\" is used by relation \"{1}\" with role {2}.\nDelete from relation?",
    159                             formatter.getName(osm), formatter.getName(ref), role),
    160                             new String[] {tr("Delete from relation"), tr("Cancel")},
    161                             new String[] {"dialogs/delete.png", "cancel.png"}).getValue();
     173            return new ExtendedDialog(Main.parent, tr("Conflicting relation"), tr(
     174                    "Selection \"{0}\" is used by relation \"{1}\" with role {2}.\nDelete from relation?", formatter
     175                    .getName(osm), formatter.getName(ref), role), new String[] { tr("Delete from relation"),
     176                tr("Cancel") }, new String[] { "dialogs/delete.png", "cancel.png" }).getValue();
    162177        else
    163             return new ExtendedDialog(Main.parent,
    164                     tr("Conflicting relation"),
    165                     tr("Selection \"{0}\" is used by relation \"{1}\".\nDelete from relation?",
    166                             formatter.getName(osm), formatter.getName(ref)),
    167                             new String[] {tr("Delete from relation"), tr("Cancel")},
    168                             new String[] {"dialogs/delete.png", "cancel.png"}).getValue();
    169     }
    170 
    171     public static Command delete(Collection<? extends OsmPrimitive> selection) {
    172         return delete(selection, true);
     178            return new ExtendedDialog(Main.parent, tr("Conflicting relation"), tr(
     179                    "Selection \"{0}\" is used by relation \"{1}\".\nDelete from relation?", formatter.getName(osm),
     180                    formatter.getName(ref)), new String[] { tr("Delete from relation"), tr("Cancel") }, new String[] {
     181                "dialogs/delete.png", "cancel.png" }).getValue();
     182    }
     183
     184    public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection) {
     185        return delete(layer, selection, true);
     186    }
     187
     188    /**
     189     * Replies the collection of nodes referred to by primitives in <code>primitivesToDelete</code> which
     190     * can be deleted too. A node can be deleted if
     191     * <ul>
     192     *    <li>it is untagged (see {@see Node#isTagged()}</li>
     193     *    <li>it is not referred to by other primitives outside of  <code>primitivesToDelete</code></li>
     194     * <ul>
     195     * @param layer  the layer in whose context primitives are deleted
     196     * @param primitivesToDelete  the primitives to delete
     197     * @return the collection of nodes referred to by primitives in <code>primitivesToDelete</code> which
     198     * can be deleted too
     199     */
     200    protected static Collection<Node> computeNodesToDelete(OsmDataLayer layer, Collection<OsmPrimitive> primitivesToDelete) {
     201        Collection<Node> nodesToDelete = new HashSet<Node>();
     202        for (OsmPrimitive osm : primitivesToDelete) {
     203            if (! (osm instanceof Way) ) {
     204                continue;
     205            }
     206            for (Node n : ((Way) osm).nodes) {
     207                if (n.isTagged()) {
     208                    continue;
     209                }
     210                CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data, false);
     211                n.visit(v);
     212                v.data.removeAll(primitivesToDelete);
     213                if (v.data.isEmpty()) {
     214                    nodesToDelete.add(n);
     215                }
     216            }
     217        }
     218        return nodesToDelete;
    173219    }
    174220
    175221    /**
    176222     * Try to delete all given primitives.
    177      *
     223     * 
    178224     * If a node is used by a way, it's removed from that way. If a node or a way is used by a
    179225     * relation, inform the user and do not delete.
    180      *
     226     * 
    181227     * If this would cause ways with less than 2 nodes to be created, delete these ways instead. If
    182228     * they are part of a relation, inform the user and do not delete.
    183      *
     229     *
     230     * @param layer the {@see OsmDataLayer} in whose context a primitive the primitives are deleted
    184231     * @param selection The objects to delete.
    185232     * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well
    186      * @return command A command to perform the deletions, or null of there is nothing to delete.
    187      */
    188     public static Command delete(Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay) {
     233     * @return command a command to perform the deletions, or null if there is nothing to delete.
     234     */
     235    public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay) {
    189236        if (selection.isEmpty())
    190237            return null;
    191238
    192         Collection<OsmPrimitive> del = new HashSet<OsmPrimitive>(selection);
     239        Collection<OsmPrimitive> primitivesToDelete = new HashSet<OsmPrimitive>(selection);
    193240        Collection<Way> waysToBeChanged = new HashSet<Way>();
    194241        HashMap<OsmPrimitive, Collection<OsmPrimitive>> relationsToBeChanged = new HashMap<OsmPrimitive, Collection<OsmPrimitive>>();
    195242
    196243        if (alsoDeleteNodesInWay) {
    197             // Delete untagged nodes that are to be unreferenced.
    198             Collection<OsmPrimitive> delNodes = new HashSet<OsmPrimitive>();
    199             for (OsmPrimitive osm : del) {
    200                 if (osm instanceof Way) {
    201                     for (Node n : ((Way) osm).nodes) {
    202                         if (!n.isTagged()) {
    203                             CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.main.getCurrentDataSet(), false);
    204                             n.visit(v);
    205                             v.data.removeAll(del);
    206                             if (v.data.isEmpty()) {
    207                                 delNodes.add(n);
    208                             }
    209                         }
    210                     }
    211                 }
    212             }
    213             del.addAll(delNodes);
    214         }
    215 
    216         if (!checkAndConfirmOutlyingDeletes(del))
     244            // delete untagged nodes only referenced by primitives in primitivesToDelete,
     245            // too
     246            Collection<Node> nodesToDelete = computeNodesToDelete(layer, primitivesToDelete);
     247            primitivesToDelete.addAll(nodesToDelete);
     248        }
     249
     250        if (!checkAndConfirmOutlyingDeletes(layer,primitivesToDelete))
    217251            return null;
    218252
    219         for (OsmPrimitive osm : del) {
    220             CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.main.getCurrentDataSet(), false);
     253        for (OsmPrimitive osm : primitivesToDelete) {
     254            CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data, false);
    221255            osm.visit(v);
    222256            for (OsmPrimitive ref : v.data) {
    223                 if (del.contains(ref)) {
     257                if (primitivesToDelete.contains(ref)) {
    224258                    continue;
    225259                }
     
    244278        for (Way w : waysToBeChanged) {
    245279            Way wnew = new Way(w);
    246             wnew.removeNodes(del);
     280            wnew.removeNodes(primitivesToDelete);
    247281            if (wnew.nodes.size() < 2) {
    248                 del.add(w);
    249 
    250                 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.main.getCurrentDataSet(), false);
     282                primitivesToDelete.add(w);
     283
     284                CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data, false);
    251285                w.visit(v);
    252286                for (OsmPrimitive ref : v.data) {
    253                     if (del.contains(ref)) {
     287                    if (primitivesToDelete.contains(ref)) {
    254288                        continue;
    255289                    }
     
    296330        // deleted way is saved (or sent to the API) with a dangling reference to a node
    297331        // Example:
    298         //  <node id='2' action='delete' visible='true' version='1' ... />
    299         //  <node id='1' action='delete' visible='true' version='1' ... />
    300         //  <!-- missing node with id -1 because new deleted nodes are not persisted -->
    301         //   <way id='3' action='delete' visible='true' version='1'>
    302         //     <nd ref='1' />
    303         //     <nd ref='-1' /> <!-- heres the problem -->
    304         //     <nd ref='2' />
    305         //   </way>
    306         for (OsmPrimitive primitive : del) {
    307             if (! (primitive instanceof Way)) {
     332        // <node id='2' action='delete' visible='true' version='1' ... />
     333        // <node id='1' action='delete' visible='true' version='1' ... />
     334        // <!-- missing node with id -1 because new deleted nodes are not persisted -->
     335        // <way id='3' action='delete' visible='true' version='1'>
     336        // <nd ref='1' />
     337        // <nd ref='-1' /> <!-- heres the problem -->
     338        // <nd ref='2' />
     339        // </way>
     340        for (OsmPrimitive primitive : primitivesToDelete) {
     341            if (!(primitive instanceof Way)) {
    308342                continue;
    309343            }
    310             Way w = (Way)primitive;
     344            Way w = (Way) primitive;
    311345            if (w.id == 0) { // new ways with id == 0 are fine,
    312                 continue;    // process existing ways only
     346                continue; // process existing ways only
    313347            }
    314348            Way wnew = new Way(w);
     
    317351            // nodes ...
    318352            for (Node n : wnew.nodes) {
    319                 if (n.id == 0 && del.contains(n)) {
     353                if (n.id == 0 && primitivesToDelete.contains(n)) {
    320354                    nodesToStrip.add(n);
    321355                }
     
    325359            wnew.nodes.removeAll(nodesToStrip);
    326360            if (!nodesToStrip.isEmpty()) {
    327                 cmds.add(new ChangeCommand(w,wnew));
    328             }
    329         }
    330 
    331         if (!del.isEmpty()) {
    332             cmds.add(new DeleteCommand(del));
     361                cmds.add(new ChangeCommand(w, wnew));
     362            }
     363        }
     364
     365        if (!primitivesToDelete.isEmpty()) {
     366            cmds.add(new DeleteCommand(layer,primitivesToDelete));
    333367        }
    334368
     
    336370    }
    337371
    338     public static Command deleteWaySegment(WaySegment ws) {
     372    public static Command deleteWaySegment(OsmDataLayer layer, WaySegment ws) {
    339373        List<Node> n1 = new ArrayList<Node>(), n2 = new ArrayList<Node>();
    340374
     
    343377
    344378        if (n1.size() < 2 && n2.size() < 2)
    345             return new DeleteCommand(Collections.singleton(ws.way));
     379            return new DeleteCommand(layer, Collections.singleton(ws.way));
    346380
    347381        Way wnew = new Way(ws.way);
     
    372406
    373407    /**
    374      * Check whether user is about to delete data outside of the download area.
    375      * Request confirmation if he is.
    376      */
    377     private static boolean checkAndConfirmOutlyingDeletes(Collection<OsmPrimitive> del) {
    378         Area a = Main.main.getCurrentDataSet().getDataSourceArea();
     408     * Check whether user is about to delete data outside of the download area. Request confirmation
     409     * if he is.
     410     *
     411     * @param layer the layer in whose context data is deleted
     412     * @param primitivesToDelete the primitives to delete
     413     * @return true, if deleting outlying primitives is OK; false, otherwise
     414     */
     415    private static boolean checkAndConfirmOutlyingDeletes(OsmDataLayer layer, Collection<OsmPrimitive> primitivesToDelete) {
     416        Area a = layer.data.getDataSourceArea();
    379417        if (a != null) {
    380             for (OsmPrimitive osm : del) {
     418            for (OsmPrimitive osm : primitivesToDelete) {
    381419                if (osm instanceof Node && osm.id != 0) {
    382420                    Node n = (Node) osm;
     
    385423                        msg.add(new JLabel(
    386424                                "<html>" +
    387                                 // leave message in one tr() as there is a grammatical connection.
    388                                 tr("You are about to delete nodes outside of the area you have downloaded." +
    389                                         "<br>" +
    390                                         "This can cause problems because other objects (that you don't see) might use them." +
    391                                         "<br>" +
    392                                 "Do you really want to delete?") + "</html>"));
     425                                // leave message in one tr() as there is a grammatical
     426                                // connection.
     427                                tr("You are about to delete nodes outside of the area you have downloaded."
     428                                        + "<br>"
     429                                        + "This can cause problems because other objects (that you don't see) might use them."
     430                                        + "<br>" + "Do you really want to delete?") + "</html>"));
    393431                        return ConditionalOptionPaneUtil.showConfirmationDialog(
    394432                                "delete_outside_nodes",
  • trunk/src/org/openstreetmap/josm/data/osm/DataSet.java

    r1814 r1856  
    33
    44import java.awt.geom.Area;
     5import java.util.ArrayList;
    56import java.util.Arrays;
    67import java.util.Collection;
     
    422423    }
    423424
    424 
     425    /**
     426     * Replies a list of parent relations which refer to the relation
     427     * <code>child</code>. Replies an empty list if child is null.
     428     *
     429     * @param child the child relation
     430     * @return a list of parent relations which refer to the relation
     431     * <code>child</code>
     432     */
     433    public List<Relation> getParentRelations(Relation child) {
     434        ArrayList<Relation> parents = new ArrayList<Relation>();
     435        if (child == null)
     436            return parents;
     437        for (Relation parent : relations) {
     438            if (parent == child) {
     439                continue;
     440            }
     441            for (RelationMember member: parent.members) {
     442                if (member.refersTo(child)) {
     443                    parents.add(parent);
     444                    break;
     445                }
     446            }
     447        }
     448        return parents;
     449    }
    425450}
  • trunk/src/org/openstreetmap/josm/data/osm/RelationMember.java

    r1790 r1856  
    3636    }
    3737
     38    /**
     39     * Replies true, if this relation member refers to the primitive
     40     *
     41     * @param primitive  the primitive to check
     42     * @return true, if this relation member refers to the primitive
     43     */
     44    public boolean refersTo(OsmPrimitive primitive) {
     45        if (primitive == null) return false;
     46        if (member == null) return false;
     47        return member == primitive;
     48    }
     49
    3850    @Override
    3951    public int hashCode() {
  • trunk/src/org/openstreetmap/josm/gui/ExtendedDialog.java

    r1811 r1856  
    6565        bTexts = buttonTexts;
    6666        setupDialog(lbl, buttonIcons);
     67        setAlwaysOnTop(true);
    6768        setVisible(true);
    6869    }
     
    195196        rootPane.getActionMap().put("ESCAPE", actionListener);
    196197    }
     198
     199    @Override
     200    public void setVisible(boolean visible) {
     201        super.setVisible(visible);
     202        if (visible) {
     203            toFront();
     204        }
     205    }
    197206}
  • trunk/src/org/openstreetmap/josm/gui/PleaseWaitDialog.java

    r1811 r1856  
    4747            public void componentShown(ComponentEvent e) {}
    4848            public void componentResized(ComponentEvent ev) {
    49                int w = getWidth();
    50                if(w > 200)
    51                    Main.pref.putInteger("progressdialog.size",w);
     49                int w = getWidth();
     50                if(w > 200) {
     51                    Main.pref.putInteger("progressdialog.size",w);
     52                }
    5253            }
    5354        });
     55        // make sure this dialog is always on top of the main JOSM window
     56        // and all the other windows (relation editors, detached dialogs, etc.)
     57        //
     58        setAlwaysOnTop(true);
    5459    }
    5560
     
    8489        setSize(Main.pref.getInteger("progressdialog.size", 600), 120);
    8590    }
     91
     92    @Override
     93    public void setVisible(boolean visible) {
     94        super.setVisible(visible);
     95        if (visible) {
     96            // make sure this dialog is always on top of the main JOSM window
     97            // and all the other windows (relation editors, detached dialogs, etc.)
     98            //
     99            toFront();
     100        }
     101    }
    86102}
  • trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java

    r1847 r1856  
    1111import java.awt.event.MouseAdapter;
    1212import java.awt.event.MouseEvent;
     13import java.util.ArrayList;
    1314import java.util.Collections;
     15import java.util.List;
    1416
    1517import javax.swing.AbstractAction;
    1618import javax.swing.DefaultListModel;
    1719import javax.swing.JList;
     20import javax.swing.JOptionPane;
    1821import javax.swing.JPanel;
    1922import javax.swing.JScrollPane;
     
    2326
    2427import org.openstreetmap.josm.Main;
     28import org.openstreetmap.josm.command.ChangeCommand;
     29import org.openstreetmap.josm.command.Command;
    2530import org.openstreetmap.josm.command.DeleteCommand;
     31import org.openstreetmap.josm.command.SequenceCommand;
    2632import org.openstreetmap.josm.data.osm.DataSet;
    2733import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2834import org.openstreetmap.josm.data.osm.Relation;
     35import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
     36import org.openstreetmap.josm.gui.OptionPaneUtil;
    2937import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
     38import org.openstreetmap.josm.gui.PrimitiveNameFormatter;
    3039import org.openstreetmap.josm.gui.SideButton;
     40import org.openstreetmap.josm.gui.dialogs.relation.ParentRelationLoadingTask;
     41import org.openstreetmap.josm.gui.dialogs.relation.RelationDialogManager;
    3142import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
    3243import org.openstreetmap.josm.gui.layer.DataChangeListener;
     
    3445import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    3546import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
     47import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
    3648import org.openstreetmap.josm.tools.GBC;
    3749import org.openstreetmap.josm.tools.ImageProvider;
    3850import org.openstreetmap.josm.tools.Shortcut;
     51
     52import com.sun.corba.se.spi.legacy.connection.GetEndPointInfoAgainException;
    3953
    4054/**
     
    4660 */
    4761public class RelationListDialog extends ToggleDialog implements LayerChangeListener, DataChangeListener {
     62    static private final PrimitiveNameFormatter NAME_FORMATTER = new PrimitiveNameFormatter();
    4863
    4964    /**
     
    270285     */
    271286    class DeleteAction extends AbstractAction implements ListSelectionListener, Runnable {
     287        class AbortException extends Exception {}
     288
    272289        public DeleteAction() {
    273290            putValue(SHORT_DESCRIPTION,tr("Delete the selected relation"));
     
    282299            if (toDelete == null)
    283300                return;
    284             Main.main.undoRedo.add(
    285                     new DeleteCommand(Collections.singleton(toDelete)));
     301            org.openstreetmap.josm.actions.mapmode.DeleteAction.deleteRelation(
     302                    Main.main.getEditLayer(),
     303                    toDelete
     304            );
    286305        }
    287306
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java

    r1855 r1856  
    2424import java.util.Collection;
    2525import java.util.Collections;
    26 import java.util.HashSet;
    2726import java.util.Iterator;
    2827import java.util.List;
     
    3332import javax.swing.JButton;
    3433import javax.swing.JComponent;
    35 import javax.swing.JDialog;
    3634import javax.swing.JLabel;
    3735import javax.swing.JOptionPane;
     
    5452
    5553import org.openstreetmap.josm.Main;
     54import org.openstreetmap.josm.actions.DeleteAction;
    5655import org.openstreetmap.josm.command.AddCommand;
    5756import org.openstreetmap.josm.command.ChangeCommand;
     
    492491        pnl.add(new JButton(moveDownAction), gc);
    493492
     493        // -- edit action
     494        gc.gridy = 2;
     495        EditAction editAction = new EditAction();
     496        memberTableModel.getSelectionModel().addListSelectionListener(editAction);
     497        pnl.add(new JButton(editAction),gc);
     498
    494499        // ------
    495         gc.gridy = 2;
     500        gc.gridy = 3;
    496501        RemoveAction removeSelectedAction = new RemoveAction();
    497502        memberTable.getSelectionModel().addListSelectionListener(removeSelectedAction);
     
    499504
    500505        // ------
    501         gc.gridy = 3;
     506        gc.gridy = 4;
    502507        SortAction sortAction = new SortAction();
    503508        pnl.add(new JButton(sortAction), gc);
     
    505510        // ------
    506511        // just grab the remaining space
    507         gc.gridy = 4;
     512        gc.gridy = 5;
    508513        gc.weighty = 1.0;
    509514        gc.fill = GridBagConstraints.BOTH;
     
    578583    protected JPanel buildButtonPanel() {
    579584        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
     585
     586        // --- download members
    580587        buttonPanel.add(new SideButton(new DownlaodAction()));
     588
     589        // --- role editing
    581590        buttonPanel.add(new JLabel(tr("Role:")));
    582591        tfRole = new JTextField(10);
     
    596605        buttonPanel.add(new SideButton(new DuplicateRelationAction()));
    597606
    598         // -- edit action
    599         EditAction editAction = new EditAction();
    600         memberTableModel.getSelectionModel().addListSelectionListener(editAction);
    601         buttonPanel.add(new SideButton(editAction));
     607        // --- delete relation action
     608        buttonPanel.add(new SideButton(new DeleteCurrentRelationAction()));
    602609        return buttonPanel;
    603610    }
     
    866873    class RemoveSelectedAction extends AbstractAction implements TableModelListener {
    867874        public RemoveSelectedAction() {
    868             putValue(SHORT_DESCRIPTION, tr("Remove all currently selected objects from relation"));
     875            putValue(SHORT_DESCRIPTION, tr("Remove all members referring to one of the selected primitives"));
    869876            putValue(SMALL_ICON, ImageProvider.get("dialogs", "removeselected"));
    870877            // putValue(NAME, tr("Remove Selected"));
     
    951958    class RemoveAction extends AbstractAction implements ListSelectionListener {
    952959        public RemoveAction() {
    953             putValue(SHORT_DESCRIPTION, tr("Remove the member in the current table row from this relation"));
     960            putValue(SHORT_DESCRIPTION, tr("Remove the currently selected members from this relation"));
    954961            putValue(SMALL_ICON, ImageProvider.get("dialogs", "remove"));
    955962            // putValue(NAME, tr("Remove"));
     
    965972        public void valueChanged(ListSelectionEvent e) {
    966973            setEnabled(memberTableModel.canRemove(memberTable.getSelectedRows()));
     974        }
     975    }
     976
     977    class DeleteCurrentRelationAction extends AbstractAction {
     978        public DeleteCurrentRelationAction() {
     979            putValue(SHORT_DESCRIPTION, tr("Delete the currently edited relation"));
     980            putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
     981            putValue(NAME, tr("Delete"));
     982            updateEnabledState();
     983        }
     984
     985        public void run() {
     986            Relation toDelete = getRelation();
     987            if (toDelete == null)
     988                return;
     989            org.openstreetmap.josm.actions.mapmode.DeleteAction.deleteRelation(
     990                    getLayer(),
     991                    toDelete
     992            );
     993        }
     994
     995        public void actionPerformed(ActionEvent e) {
     996            run();
     997        }
     998
     999        protected void updateEnabledState() {
     1000            setEnabled(getRelation() != null);
    9671001        }
    9681002    }
     
    12111245            putValue(SHORT_DESCRIPTION, tr("Edit the relation the currently selected relation member refers to"));
    12121246            putValue(SMALL_ICON, ImageProvider.get("dialogs", "edit"));
    1213             putValue(NAME, tr("Edit"));
     1247            //putValue(NAME, tr("Edit"));
    12141248            refreshEnabled();
    12151249        }
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/ReferringRelationsBrowser.java

    r1847 r1856  
    118118        public void actionPerformed(ActionEvent e) {
    119119            boolean full = cbReadFull.isSelected();
    120             ReloadTask task = new ReloadTask(full, relationEditor);
     120            final ParentRelationLoadingTask task = new ParentRelationLoadingTask(
     121                    model.getRelation(),
     122                    getLayer(),
     123                    full,
     124                    new PleaseWaitProgressMonitor()
     125            );
     126            task.setContinuation(
     127                    new Runnable() {
     128                        public void run() {
     129                            if (task.isCancelled() || task.hasError())
     130                                return;
     131                            model.populate(task.getParents());
     132                        }
     133                    }
     134            );
    121135            Main.worker.submit(task);
    122136        }
     
    177191        }
    178192    }
    179 
    180     /**
    181      * Asynchronous task for loading the parent relations
    182      *
    183      */
    184     class ReloadTask extends PleaseWaitRunnable {
    185         private boolean cancelled;
    186         private Exception lastException;
    187         private DataSet referrers;
    188         private boolean full;
    189 
    190         public ReloadTask(boolean full, Dialog parent) {
    191             super(tr("Download referring relations"), new PleaseWaitProgressMonitor(parent), false /* don't ignore exception */);
    192             referrers = null;
    193         }
    194         @Override
    195         protected void cancel() {
    196             cancelled = true;
    197             OsmApi.getOsmApi().cancel();
    198         }
    199 
    200         protected void showLastException() {
    201             String msg = lastException.getMessage();
    202             if (msg == null) {
    203                 msg = lastException.toString();
    204             }
    205             OptionPaneUtil.showMessageDialog(
    206                     Main.parent,
    207                     msg,
    208                     tr("Error"),
    209                     JOptionPane.ERROR_MESSAGE
    210             );
    211         }
    212 
    213         @Override
    214         protected void finish() {
    215             if (cancelled) return;
    216             if (lastException != null) {
    217                 showLastException();
    218                 return;
    219             }
    220             final ArrayList<Relation> parents = new ArrayList<Relation>();
    221             for (Relation parent : referrers.relations) {
    222                 parents.add((Relation)getLayer().data.getPrimitiveById(parent.id));
    223             }
    224             SwingUtilities.invokeLater(
    225                     new Runnable() {
    226                         public void run() {
    227                             model.populate(parents);
    228                         }
    229                     }
    230             );
    231         }
    232 
    233         @Override
    234         protected void realRun() throws SAXException, IOException, OsmTransferException {
    235             try {
    236                 progressMonitor.indeterminateSubTask(null);
    237                 OsmServerBackreferenceReader reader = new OsmServerBackreferenceReader(model.getRelation(), full);
    238                 referrers = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false));
    239                 if (referrers != null) {
    240                     final MergeVisitor visitor = new MergeVisitor(getLayer().data, referrers);
    241                     visitor.merge();
    242 
    243                     // copy the merged layer's data source info
    244                     for (DataSource src : referrers.dataSources) {
    245                         getLayer().data.dataSources.add(src);
    246                     }
    247                     // FIXME: this is necessary because there are  dialogs listening
    248                     // for DataChangeEvents which manipulate Swing components on this
    249                     // thread.
    250                     //
    251                     SwingUtilities.invokeLater(
    252                             new Runnable() {
    253                                 public void run() {
    254                                     getLayer().fireDataChange();
    255                                 }
    256                             }
    257                     );
    258 
    259                     if (visitor.getConflicts().isEmpty())
    260                         return;
    261                     getLayer().getConflicts().add(visitor.getConflicts());
    262                     OptionPaneUtil.showMessageDialog(
    263                             Main.parent,
    264                             tr("There were {0} conflicts during import.",
    265                                     visitor.getConflicts().size()),
    266                                     tr("Warning"),
    267                                     JOptionPane.WARNING_MESSAGE
    268                     );
    269                 }
    270             } catch(Exception e) {
    271                 if (cancelled) {
    272                     System.out.println(tr("Warning: ignoring exception because task is cancelled. Exception: {0}", e.toString()));
    273                     return;
    274                 }
    275                 lastException = e;
    276             }
    277         }
    278     }
    279193}
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/ReferringRelationsBrowserModel.java

    r1836 r1856  
    33
    44import java.util.ArrayList;
     5import java.util.List;
    56
    67import javax.swing.AbstractListModel;
     
    5556    }
    5657
    57     public void populate(ArrayList<Relation> parents) {
     58    public void populate(List<Relation> parents) {
    5859        referrers.clear();
    5960        if (parents != null) {
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationDialogManager.java

    r1828 r1856  
    119119        openDialogs.put(context, editor);
    120120        editor.addWindowListener(this);
     121    }
     122
     123    /**
     124     * Closes the editor open for a specific layer and a specific relation.
     125     *
     126     * @param layer  the layer
     127     * @param relation the relation
     128     */
     129    public void close(OsmDataLayer layer, Relation relation) {
     130        DialogContext context = new DialogContext(layer, relation);
     131        RelationEditor editor = openDialogs.get(context);
     132        if (editor != null) {
     133            editor.setVisible(false);
     134        }
    121135    }
    122136
Note: See TracChangeset for help on using the changeset viewer.