Changeset 2487 in josm for trunk/src/org


Ignore:
Timestamp:
2009-11-21T13:24:49+01:00 (14 years ago)
Author:
Gubaer
Message:

Fixed event handling in RelationListDialog. Fixed registering/unregistering for data set events.
Synchronized model manipulation. Update of RelationListDialog due to data set events should now
always run in the EDT.
This should fix a couple of NPEs recently reported in trac.

Location:
trunk/src/org/openstreetmap/josm/gui/dialogs
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java

    r2485 r2487  
    1212import java.awt.event.MouseEvent;
    1313import java.util.ArrayList;
    14 import java.util.Arrays;
    1514import java.util.Collection;
    1615import java.util.Collections;
     
    1817import java.util.HashSet;
    1918import java.util.List;
     19import java.util.Set;
    2020
    2121import javax.swing.AbstractAction;
     
    3333
    3434import org.openstreetmap.josm.Main;
    35 import org.openstreetmap.josm.data.osm.DataSet;
    3635import org.openstreetmap.josm.data.osm.DataSetListener;
    3736import org.openstreetmap.josm.data.osm.NameFormatter;
     
    7675    private RelationDialogPopupMenu popupMenu;
    7776
    78 
    7977    /**
    8078     * constructor
     
    129127
    130128        add(buttonPanel, BorderLayout.SOUTH);
     129
     130        // activate DEL in the list of relations
    131131        displaylist.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE,0), "deleteRelation");
    132132        displaylist.getActionMap().put("deleteRelation", deleteAction);
     
    138138        Layer.listeners.add(this);
    139139        Layer.listeners.add(newAction);
    140         for (OsmDataLayer layer:Main.map.mapView.getLayersOfType(OsmDataLayer.class)) {
    141             layer.data.addDataSetListener(this);
     140        // Register as a data set listener for the current edit layer only.
     141        // See also activeLayerChanged
     142        if (Main.main.getEditLayer() != null) {
     143            Main.main.getEditLayer().data.addDataSetListener(this);
    142144        }
    143145    }
     
    146148        Layer.listeners.remove(this);
    147149        Layer.listeners.remove(newAction);
     150        Layer.listeners.add(newAction);
     151        // unregistering from *all* data layer is somewhat overkill but it
     152        // doesn't harm either.
    148153        for (OsmDataLayer layer:Main.map.mapView.getLayersOfType(OsmDataLayer.class)) {
    149154            layer.data.removeDataSetListener(this);
     
    151156    }
    152157
    153 
    154     protected int getNumRelations() {
    155         if (Main.main.getCurrentDataSet() == null) return 0;
    156         return Main.main.getCurrentDataSet().getRelations().size();
    157     }
    158 
    159     /**
    160      * Replies the list of complete, non-deleted relations in the dataset <code>ds</code>,
    161      * sorted by display name.
     158    /**
     159     * Initializes the relation list dialog from a layer. If <code>layer</code> is null
     160     * or if it isn't an {@see OsmDataLayer} the dialog is reset to an empty dialog.
     161     * Otherwise it is initialized with the list of non-deleted and visible relations
     162     * in the layer's dataset.
    162163     *
    163      * @param ds the dataset
    164      * @return the list of relations
    165      */
    166     protected ArrayList<Relation> getDisplayedRelationsInSortOrder(DataSet ds) {
    167         ArrayList<Relation> relations = new ArrayList<Relation>(ds.getRelations().size());
    168         for (Relation r : ds.getRelations()) {
    169             if (!r.isUsable() || !r.isVisible()) {
    170                 continue;
    171             }
    172             relations.add(r);
    173         }
    174 
    175         Collections.sort(
    176                 relations,
    177                 new Comparator<Relation>() {
    178                     NameFormatter formatter = DefaultNameFormatter.getInstance();
    179 
    180                     public int compare(Relation r1, Relation r2) {
    181                         return r1.getDisplayName(formatter).compareTo(r2.getDisplayName(formatter));
    182                     }
    183                 }
    184         );
    185         return relations;
    186     }
    187 
    188     public void updateList() {
    189         if (Main.main.getCurrentDataSet() == null) {
     164     * @param layer the layer. May be null.
     165     */
     166    protected void initFromLayer(Layer layer) {
     167        if (layer == null || ! (layer instanceof OsmDataLayer)) {
    190168            model.setRelations(null);
    191169            return;
    192170        }
    193         Relation[] selected = getAllSelected();
    194 
    195         model.setRelations(getDisplayedRelationsInSortOrder(Main.main.getCurrentDataSet()));
     171        OsmDataLayer l = (OsmDataLayer)layer;
     172        model.setRelations(l.data.getRelations());
    196173        if(model.getSize() > 0) {
    197174            setTitle(tr("Relations: {0}", model.getSize()));
     
    199176            setTitle(tr("Relations"));
    200177        }
    201         selectRelations(selected);
    202     }
    203 
    204     public void activeLayerChange(Layer a, Layer b) {
    205         updateList();
    206     }
    207 
    208     public void layerRemoved(Layer a) {
    209         if (a instanceof OsmDataLayer) {
    210             ((OsmDataLayer)a).data.removeDataSetListener(this);
    211         }
    212         updateList();
    213     }
    214 
    215     public void layerAdded(Layer a) {
    216         if (a instanceof OsmDataLayer) {
    217             ((OsmDataLayer)a).data.addDataSetListener(this);
    218         }
    219     }
    220 
    221     /**
    222      * Returns the currently selected relation, or null.
    223      *
    224      * @return the currently selected relation, or null
    225      */
    226     public Relation getCurrentRelation() {
    227         return (Relation) displaylist.getSelectedValue();
    228178    }
    229179
     
    257207
    258208    /**
    259      * @return All selected relations in the list, possibly empty List
    260      */
    261     private Relation[] getAllSelected() {
    262         return Arrays.asList(displaylist.getSelectedValues()).toArray(new Relation[0]);
    263     }
    264 
    265     /**
    266209     * Selects the relation <code>relation</code> in the list of relations.
    267210     *
     
    269212     */
    270213    public void selectRelation(Relation relation) {
    271         selectRelations(new Relation[] {relation});
    272     }
    273 
    274     /**
    275      * Selects the relations <code>relations</code> in the list of relations.
    276      *
    277      * @param relations  the relations (may be empty)
    278      */
    279     public void selectRelations(Relation[] relations) {
    280         List<Integer> sel = new ArrayList<Integer>();
    281         for (Relation r : relations) {
    282             if (r == null) {
    283                 continue;
    284             }
    285             int idx = model.getIndexOfRelation(r);
    286             if (idx != -1) {
    287                 sel.add(idx);
    288             }
    289         }
    290         if (sel.isEmpty()) {
    291             displaylist.clearSelection();
    292             return;
     214        if (relation == null) {
     215            model.setSelectedRelations(null);
    293216        } else {
    294             int fst = Collections.min(sel);
    295             displaylist.scrollRectToVisible(displaylist.getCellBounds(fst, fst));
    296         }
    297 
    298         int[] aSel = new int[sel.size()];       //FIXME: how to cast Integer[] -> int[] ?
    299         for (int i=0; i<sel.size(); ++i) {
    300             aSel[i] = sel.get(i);
    301         }
    302 
    303         displaylist.setSelectedIndices(aSel);
     217            model.setSelectedRelations(Collections.singletonList(relation));
     218        }
    304219    }
    305220
     
    425340
    426341    /**
    427      * The edit action
     342     * The action for creating a new relation
    428343     *
    429344     */
     
    437352
    438353        public void run() {
    439             RelationEditor.getEditor(Main.map.mapView.getEditLayer(),null, null).setVisible(true);
     354            RelationEditor.getEditor(Main.main.getEditLayer(),null, null).setVisible(true);
    440355        }
    441356
     
    557472    }
    558473
    559 
     474    /**
     475     * The action for downloading members of all selected relations
     476     *
     477     */
    560478    class DownloadMembersAction extends AbstractAction implements ListSelectionListener{
    561479
     
    586504    }
    587505
     506    /**
     507     * The list model for the list of relations displayed in the relation list
     508     * dialog.
     509     *
     510     */
    588511    private static  class RelationListModel extends AbstractListModel {
    589512        private ArrayList<Relation> relations;
     
    598521        }
    599522
    600         public void setRelations(ArrayList<Relation> relations) {
    601             this.relations = relations;
     523        public synchronized void setRelations(Collection<Relation> relations) {
     524            if (relations == null) {
     525                this.relations = null;
     526            } else {
     527                this.relations = new ArrayList<Relation>(relations.size());
     528                for (Relation r: relations) {
     529                    if (! r.isDeleted() && r.isVisible() && !r.incomplete) {
     530                        this.relations.add(r);
     531                    }
     532                }
     533            }
     534            sort();
    602535            fireIntervalAdded(this, 0, getSize());
    603         }
    604 
    605         public void addRelations(Collection<? extends OsmPrimitive> addedPrimitives) {
     536            selectionModel.clearSelection();
     537        }
     538
     539        public synchronized void sort() {
     540            if (relations == null) return;
     541            Collections.sort(
     542                    relations,
     543                    new Comparator<Relation>() {
     544                        NameFormatter formatter = DefaultNameFormatter.getInstance();
     545
     546                        public int compare(Relation r1, Relation r2) {
     547                            return r1.getDisplayName(formatter).compareTo(r2.getDisplayName(formatter));
     548                        }
     549                    }
     550            );
     551        }
     552
     553        /**
     554         * Add all relations in <code>addedPrimitives</code> to the model for the
     555         * relation list dialog
     556         *
     557         * @param addedPrimitives the collection of added primitives. May include nodes,
     558         * ways, and relations.
     559         */
     560        public synchronized void addRelations(Collection<? extends OsmPrimitive> addedPrimitives) {
    606561            if (addedPrimitives == null || addedPrimitives.isEmpty()) return;
    607562            boolean added = false;
     
    617572            }
    618573            if (added) {
     574                List<Relation> sel = getSelectedRelations();
     575                sort();
    619576                fireIntervalAdded(this, 0, getSize());
     577                setSelectedRelations(sel);
     578            }
     579        }
     580
     581        /**
     582         * Removes all relations in <code>removedPrimitives</code> from the model
     583         *
     584         * @param removedPrimitives the removed primitives. May include nodes, ways,
     585         *   and relations
     586         */
     587        public synchronized void removeRelations(Collection<? extends OsmPrimitive> removedPrimitives) {
     588            if (removedPrimitives == null) return;
     589            // extract the removed relations
     590            //
     591            Set<Relation> removedRelations = new HashSet<Relation>();
     592            for (OsmPrimitive p: removedPrimitives) {
     593                if (! (p instanceof Relation)) {
     594                    continue;
     595                }
     596                removedRelations.add((Relation)p);
     597            }
     598            if (removedRelations.isEmpty())
     599                return;
     600            int size = relations.size();
     601            relations.removeAll(removedRelations);
     602            if (size != relations.size()) {
     603                List<Relation> sel = getSelectedRelations();
     604                sort();
     605                fireContentsChanged(this, 0, getSize());
     606                setSelectedRelations(sel);
    620607            }
    621608        }
     
    672659            return ret;
    673660        }
     661
     662        /**
     663         * Sets the selected relations.
     664         *
     665         * @return sel the list of selected relations
     666         */
     667        public synchronized void setSelectedRelations(List<Relation> sel) {
     668            selectionModel.clearSelection();
     669            if (sel == null || sel.isEmpty())
     670                return;
     671            for (Relation r: sel) {
     672                int i = relations.indexOf(r);
     673                if (i<0) {
     674                    continue;
     675                }
     676                selectionModel.addSelectionInterval(i,i);
     677            }
     678        }
    674679    }
    675680
    676681    class RelationDialogPopupMenu extends JPopupMenu {
    677 
    678682        protected void build() {
    679683            // -- download members action
     
    695699    }
    696700
    697     public void nodeMoved(Node node) { }
    698 
    699     public void wayNodesChanged(Way way) { }
    700 
    701     public void primtivesAdded(Collection<? extends OsmPrimitive> added) {
    702         model.addRelations(added);
    703     }
    704 
    705     public void primtivesRemoved(Collection<? extends OsmPrimitive> removed) {
    706         updateList();
    707     }
    708 
    709     public void relationMembersChanged(Relation r) {
    710         // trigger a repaint of the relation list
    711         displaylist.repaint();
     701    /* ---------------------------------------------------------------------------------- */
     702    /* LayerChangeListener                                                                */
     703    /* ---------------------------------------------------------------------------------- */
     704    public void activeLayerChange(Layer a, Layer b) {
     705        initFromLayer(b);
     706        if (a != null && a instanceof OsmDataLayer) {
     707            ((OsmDataLayer)a).data.removeDataSetListener(this);
     708        }
     709        if (b != null && b instanceof OsmDataLayer) {
     710            ((OsmDataLayer)b).data.addDataSetListener(this);
     711        }
     712
     713    }
     714    public void layerRemoved(Layer a) {/* irrelevant in this context */}
     715    public void layerAdded(Layer a) {/* irrelevant in this context */}
     716
     717
     718    /* ---------------------------------------------------------------------------------- */
     719    /* DataSetListener                                                                    */
     720    /* ---------------------------------------------------------------------------------- */
     721
     722    public void nodeMoved(Node node) {/* irrelevant in this context */}
     723
     724    public void wayNodesChanged(Way way) {/* irrelevant in this context */}
     725
     726    public void primtivesAdded(final Collection<? extends OsmPrimitive> added) {
     727        Runnable task = new Runnable() {
     728            public void run() {
     729                model.addRelations(added);
     730            }
     731        };
     732        if (SwingUtilities.isEventDispatchThread()) {
     733            task.run();
     734        } else {
     735            SwingUtilities.invokeLater(task);
     736        }
     737    }
     738
     739    public void primtivesRemoved(final Collection<? extends OsmPrimitive> removed) {
     740        Runnable task = new Runnable() {
     741            public void run() {
     742                model.removeRelations(removed);
     743            }
     744        };
     745        if (SwingUtilities.isEventDispatchThread()) {
     746            task.run();
     747        } else {
     748            SwingUtilities.invokeLater(task);
     749        }
     750    }
     751
     752    public void relationMembersChanged(final Relation r) {
     753        Runnable task = new Runnable() {
     754            public void run() {
     755                List<Relation> sel = model.getSelectedRelations();
     756                model.sort();
     757                model.setSelectedRelations(sel);
     758                displaylist.repaint();
     759            }
     760        };
     761        if (SwingUtilities.isEventDispatchThread()) {
     762            task.run();
     763        } else {
     764            SwingUtilities.invokeLater(task);
     765        }
    712766    }
    713767
    714768    public void tagsChanged(OsmPrimitive prim) {
    715         if (prim instanceof Relation) {
    716             // trigger a repaint of the relation list
    717             displaylist.repaint();
     769        if (prim == null || ! (prim instanceof Relation))
     770            return;
     771        Runnable task = new Runnable() {
     772            public void run() {
     773                // trigger a sort of the relation list because the display name may
     774                // have changed
     775                //
     776                List<Relation> sel = model.getSelectedRelations();
     777                model.sort();
     778                model.setSelectedRelations(sel);
     779                displaylist.repaint();
     780            }
     781        };
     782        if (SwingUtilities.isEventDispatchThread()) {
     783            task.run();
     784        } else {
     785            SwingUtilities.invokeLater(task);
    718786        }
    719787    }
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableColumnModel.java

    r1916 r2487  
    1616        col.setHeaderValue(tr("Role"));
    1717        col.setResizable(true);
     18        col.setPreferredWidth(100);
    1819        col.setCellRenderer(new MemberTableRoleCellRenderer());
    1920        col.setCellEditor(new MemberRoleCellEditor());
     
    2425        col.setHeaderValue(tr("Refers to"));
    2526        col.setResizable(true);
     27        col.setPreferredWidth(300);
    2628        // col.setCellRenderer(new OsmPrimitivRenderer());
    2729        col.setCellRenderer(new MemberTableMemberCellRenderer());
     
    3032        // column 2 -
    3133        col = new TableColumn(2);
    32         col.setHeaderValue(tr("Linked"));
    33         col.setResizable(true);
     34        col.setHeaderValue("");
     35        col.setResizable(false);
     36        col.setPreferredWidth(20);
    3437        col.setCellRenderer(new MemberTableLinkedCellRenderer());
    3538        addColumn(col);
Note: See TracChangeset for help on using the changeset viewer.