source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java @ 4070

Last change on this file since 4070 was 4070, checked in by jttt, 8 years ago

Fix #6275 Sort relations numerically

  • Property svn:eol-style set to native
File size: 29.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.BorderLayout;
8import java.awt.Point;
9import java.awt.event.ActionEvent;
10import java.awt.event.KeyEvent;
11import java.awt.event.MouseAdapter;
12import java.awt.event.MouseEvent;
13import java.util.ArrayList;
14import java.util.Collection;
15import java.util.Collections;
16import java.util.Comparator;
17import java.util.HashSet;
18import java.util.Iterator;
19import java.util.List;
20import java.util.Set;
21
22import javax.swing.AbstractAction;
23import javax.swing.AbstractListModel;
24import javax.swing.DefaultListSelectionModel;
25import javax.swing.JList;
26import javax.swing.JPanel;
27import javax.swing.JPopupMenu;
28import javax.swing.JScrollPane;
29import javax.swing.KeyStroke;
30import javax.swing.ListSelectionModel;
31import javax.swing.SwingUtilities;
32import javax.swing.event.ListSelectionEvent;
33import javax.swing.event.ListSelectionListener;
34
35import org.openstreetmap.josm.Main;
36import org.openstreetmap.josm.data.osm.OsmPrimitive;
37import org.openstreetmap.josm.data.osm.Relation;
38import org.openstreetmap.josm.data.osm.RelationMember;
39import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
40import org.openstreetmap.josm.data.osm.event.DataChangedEvent;
41import org.openstreetmap.josm.data.osm.event.DataSetListener;
42import org.openstreetmap.josm.data.osm.event.DatasetEventManager;
43import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode;
44import org.openstreetmap.josm.data.osm.event.NodeMovedEvent;
45import org.openstreetmap.josm.data.osm.event.PrimitivesAddedEvent;
46import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent;
47import org.openstreetmap.josm.data.osm.event.RelationMembersChangedEvent;
48import org.openstreetmap.josm.data.osm.event.TagsChangedEvent;
49import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent;
50import org.openstreetmap.josm.gui.DefaultNameFormatter;
51import org.openstreetmap.josm.gui.MapView;
52import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
53import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
54import org.openstreetmap.josm.gui.SideButton;
55import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask;
56import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationTask;
57import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
58import org.openstreetmap.josm.gui.layer.Layer;
59import org.openstreetmap.josm.gui.layer.OsmDataLayer;
60import org.openstreetmap.josm.tools.ImageProvider;
61import org.openstreetmap.josm.tools.Shortcut;
62
63/**
64 * A dialog showing all known relations, with buttons to add, edit, and
65 * delete them.
66 *
67 * We don't have such dialogs for nodes, segments, and ways, because those
68 * objects are visible on the map and can be selected there. Relations are not.
69 */
70public class RelationListDialog extends ToggleDialog implements DataSetListener {
71    //private static final Logger logger = Logger.getLogger(RelationListDialog.class.getName());
72
73    /** The display list. */
74    private JList displaylist;
75    /** the list model used */
76    private RelationListModel model;
77
78    /** the edit action */
79    private EditAction editAction;
80    /** the delete action */
81    private DeleteAction deleteAction;
82    private NewAction newAction;
83    /** the popup menu */
84    private RelationDialogPopupMenu popupMenu;
85
86    /**
87     * constructor
88     */
89    public RelationListDialog() {
90        super(tr("Relations"), "relationlist", tr("Open a list of all relations."),
91                Shortcut.registerShortcut("subwindow:relations", tr("Toggle: {0}", tr("Relations")), KeyEvent.VK_R,
92                        Shortcut.GROUP_LAYER, Shortcut.SHIFT_DEFAULT), 150);
93
94        // create the list of relations
95        //
96        DefaultListSelectionModel selectionModel = new DefaultListSelectionModel();
97        model = new RelationListModel(selectionModel);
98        displaylist = new JList(model);
99        displaylist.setSelectionModel(selectionModel);
100        displaylist.setCellRenderer(new OsmPrimitivRenderer() {
101            /**
102             * Don't show the default tooltip in the relation list.
103             */
104            @Override
105            protected String getComponentToolTipText(OsmPrimitive value) {
106                return null;
107            }
108        });
109        displaylist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
110        displaylist.addMouseListener(new MouseEventHandler());
111        add(new JScrollPane(displaylist), BorderLayout.CENTER);
112
113        // create the panel with buttons
114        //
115        JPanel tp = getButtonPanel(5);
116        // the new action
117        //
118        newAction = new NewAction();
119        tp.add(new SideButton(newAction, false));
120
121        // the edit action
122        //
123        editAction = new EditAction();
124        displaylist.addListSelectionListener(editAction);
125        tp.add(new SideButton(editAction, false));
126
127        // the duplicate action
128        //
129        DuplicateAction duplicateAction = new DuplicateAction();
130        displaylist.addListSelectionListener(duplicateAction);
131        tp.add(new SideButton(duplicateAction, false));
132
133        // the delete action
134        //
135        deleteAction = new DeleteAction();
136        displaylist.addListSelectionListener(deleteAction);
137        tp.add(new SideButton(deleteAction, false));
138
139        // the select action
140        //
141        SelectAction selectAction = new SelectAction();
142        displaylist.addListSelectionListener(selectAction);
143        tp.add(new SideButton(selectAction, false));
144
145        add(tp, BorderLayout.SOUTH);
146
147        // activate DEL in the list of relations
148        displaylist.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE,0), "deleteRelation");
149        displaylist.getActionMap().put("deleteRelation", deleteAction);
150
151        popupMenu = new RelationDialogPopupMenu();
152    }
153
154    @Override public void showNotify() {
155        MapView.addLayerChangeListener(newAction);
156        newAction.updateEnabledState();
157        DatasetEventManager.getInstance().addDatasetListener(this, FireMode.IN_EDT);
158        dataChanged(null);
159    }
160
161    @Override public void hideNotify() {
162        MapView.removeLayerChangeListener(newAction);
163        DatasetEventManager.getInstance().removeDatasetListener(this);
164    }
165
166    /**
167     * Initializes the relation list dialog from a layer. If <code>layer</code> is null
168     * or if it isn't an {@see OsmDataLayer} the dialog is reset to an empty dialog.
169     * Otherwise it is initialized with the list of non-deleted and visible relations
170     * in the layer's dataset.
171     *
172     * @param layer the layer. May be null.
173     */
174    protected void initFromLayer(Layer layer) {
175        if (layer == null || ! (layer instanceof OsmDataLayer)) {
176            model.setRelations(null);
177            return;
178        }
179        OsmDataLayer l = (OsmDataLayer)layer;
180        model.setRelations(l.data.getRelations());
181        model.updateTitle();
182    }
183
184    /**
185     * Adds a selection listener to the relation list.
186     *
187     * @param listener the listener to add
188     */
189    public void addListSelectionListener(ListSelectionListener listener) {
190        displaylist.addListSelectionListener(listener);
191    }
192
193    /**
194     * Removes a selection listener from the relation list.
195     *
196     * @param listener the listener to remove
197     */
198    public void removeListSelectionListener(ListSelectionListener listener) {
199        displaylist.removeListSelectionListener(listener);
200    }
201
202    /**
203     * @return The selected relation in the list
204     */
205    private Relation getSelected() {
206        if(model.getSize() == 1) {
207            displaylist.setSelectedIndex(0);
208        }
209        return (Relation) displaylist.getSelectedValue();
210    }
211
212    /**
213     * Selects the relation <code>relation</code> in the list of relations.
214     *
215     * @param relation  the relation
216     */
217    public void selectRelation(Relation relation) {
218        if (relation == null) {
219            model.setSelectedRelations(null);
220        } else {
221            model.setSelectedRelations(Collections.singletonList(relation));
222            Integer i = model.getRelationIndex(relation);
223            if (i != null) { // Not all relations have to be in the list (for example when the relation list is hidden, it's not updated with new relations)
224                displaylist.scrollRectToVisible(displaylist.getCellBounds(i, i));
225            }
226        }
227    }
228
229    class MouseEventHandler extends MouseAdapter {
230        protected void setCurrentRelationAsSelection() {
231            Main.main.getCurrentDataSet().setSelected((Relation)displaylist.getSelectedValue());
232        }
233
234        protected void editCurrentRelation() {
235            new EditAction().launchEditor(getSelected());
236        }
237
238        @Override public void mouseClicked(MouseEvent e) {
239            if (Main.main.getEditLayer() == null) return;
240            if (e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e)) {
241                if (e.isControlDown()) {
242                    editCurrentRelation();
243                } else {
244                    setCurrentRelationAsSelection();
245                }
246            }
247        }
248        private void openPopup(MouseEvent e) {
249            Point p = e.getPoint();
250            int index = displaylist.locationToIndex(p);
251            if (index < 0) return;
252            if (!displaylist.getCellBounds(index, index).contains(e.getPoint()))
253                return;
254            if (! displaylist.isSelectedIndex(index)) {
255                displaylist.setSelectedIndex(index);
256            }
257            popupMenu.show(displaylist, p.x, p.y-3);
258        }
259        @Override public void mousePressed(MouseEvent e) {
260            if (Main.main.getEditLayer() == null) return;
261            if (e.isPopupTrigger()) {
262                openPopup(e);
263            }
264        }
265        @Override public void mouseReleased(MouseEvent e) {
266            if (Main.main.getEditLayer() == null) return;
267            if (e.isPopupTrigger()) {
268                openPopup(e);
269            }
270        }
271    }
272
273    /**
274     * The edit action
275     *
276     */
277    class EditAction extends AbstractAction implements ListSelectionListener{
278        public EditAction() {
279            putValue(SHORT_DESCRIPTION,tr( "Open an editor for the selected relation"));
280            //putValue(NAME, tr("Edit"));
281            putValue(SMALL_ICON, ImageProvider.get("dialogs", "edit"));
282            setEnabled(false);
283        }
284        protected Collection<RelationMember> getMembersForCurrentSelection(Relation r) {
285            Collection<RelationMember> members = new HashSet<RelationMember>();
286            Collection<OsmPrimitive> selection = Main.map.mapView.getEditLayer().data.getSelected();
287            for (RelationMember member: r.getMembers()) {
288                if (selection.contains(member.getMember())) {
289                    members.add(member);
290                }
291            }
292            return members;
293        }
294
295        public void launchEditor(Relation toEdit) {
296            if (toEdit == null)
297                return;
298            RelationEditor.getEditor(Main.map.mapView.getEditLayer(),toEdit, getMembersForCurrentSelection(toEdit)).setVisible(true);
299        }
300
301        public void actionPerformed(ActionEvent e) {
302            if (!isEnabled())
303                return;
304            launchEditor(getSelected());
305        }
306
307        public void valueChanged(ListSelectionEvent e) {
308            setEnabled(displaylist.getSelectedIndices() != null && displaylist.getSelectedIndices().length == 1);
309        }
310    }
311
312    /**
313     * The delete action
314     *
315     */
316    class DeleteAction extends AbstractAction implements ListSelectionListener {
317        class AbortException extends Exception {}
318
319        public DeleteAction() {
320            putValue(SHORT_DESCRIPTION,tr("Delete the selected relation"));
321            //putValue(NAME, tr("Delete"));
322            putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
323            setEnabled(false);
324        }
325
326        protected void deleteRelation(Relation toDelete) {
327            if (toDelete == null)
328                return;
329            org.openstreetmap.josm.actions.mapmode.DeleteAction.deleteRelation(
330                    Main.main.getEditLayer(),
331                    toDelete
332            );
333        }
334
335        public void actionPerformed(ActionEvent e) {
336            if (!isEnabled()) return;
337            int [] idx  = displaylist.getSelectedIndices();
338            ArrayList<Relation> toDelete = new ArrayList<Relation>(idx.length);
339            for (int i: idx) {
340                toDelete.add(model.getRelation(i));
341            }
342            for (Relation r: toDelete) {
343                deleteRelation(r);
344            }
345        }
346
347        public void valueChanged(ListSelectionEvent e) {
348            setEnabled(displaylist.getSelectedIndices() != null && displaylist.getSelectedIndices().length > 0);
349        }
350    }
351
352    /**
353     * The action for creating a new relation
354     *
355     */
356    static class NewAction extends AbstractAction implements LayerChangeListener{
357        public NewAction() {
358            putValue(SHORT_DESCRIPTION,tr("Create a new relation"));
359            //putValue(NAME, tr("New"));
360            putValue(SMALL_ICON, ImageProvider.get("dialogs", "addrelation"));
361            updateEnabledState();
362        }
363
364        public void run() {
365            RelationEditor.getEditor(Main.main.getEditLayer(),null, null).setVisible(true);
366        }
367
368        public void actionPerformed(ActionEvent e) {
369            run();
370        }
371
372        protected void updateEnabledState() {
373            setEnabled(Main.main != null && Main.main.getEditLayer() != null);
374        }
375
376        public void activeLayerChange(Layer oldLayer, Layer newLayer) {
377            updateEnabledState();
378        }
379
380        public void layerAdded(Layer newLayer) {
381            updateEnabledState();
382        }
383
384        public void layerRemoved(Layer oldLayer) {
385            updateEnabledState();
386        }
387    }
388
389    /**
390     * Creates a new relation with a copy of the current editor state
391     *
392     */
393    class DuplicateAction extends AbstractAction implements ListSelectionListener {
394        public DuplicateAction() {
395            putValue(SHORT_DESCRIPTION, tr("Create a copy of this relation and open it in another editor window"));
396            putValue(SMALL_ICON, ImageProvider.get("duplicate"));
397            //putValue(NAME, tr("Duplicate"));
398            updateEnabledState();
399        }
400
401        public void launchEditorForDuplicate(Relation original) {
402            Relation copy = new Relation(original, true);
403            copy.setModified(true);
404            RelationEditor editor = RelationEditor.getEditor(
405                    Main.main.getEditLayer(),
406                    copy,
407                    null /* no selected members */
408            );
409            editor.setVisible(true);
410        }
411
412        public void actionPerformed(ActionEvent e) {
413            if (!isEnabled())
414                return;
415            launchEditorForDuplicate(getSelected());
416        }
417
418        protected void updateEnabledState() {
419            setEnabled(displaylist.getSelectedIndices() != null && displaylist.getSelectedIndices().length == 1);
420        }
421
422        public void valueChanged(ListSelectionEvent e) {
423            updateEnabledState();
424        }
425    }
426
427    /**
428     * Sets the current selection to the list of relations selected in this dialog
429     *
430     */
431    class SelectAction extends AbstractAction implements ListSelectionListener{
432        public SelectAction() {
433            putValue(SHORT_DESCRIPTION,tr("Set the current selection to the list of selected relations"));
434            putValue(SMALL_ICON, ImageProvider.get("dialogs", "select"));
435            setEnabled(false);
436        }
437
438        public void actionPerformed(ActionEvent e) {
439            if (!isEnabled()) return;
440            int [] idx = displaylist.getSelectedIndices();
441            if (idx == null || idx.length == 0) return;
442            ArrayList<OsmPrimitive> selection = new ArrayList<OsmPrimitive>(idx.length);
443            for (int i: idx) {
444                selection.add(model.getRelation(i));
445            }
446            Main.map.mapView.getEditLayer().data.setSelected(selection);
447        }
448
449        public void valueChanged(ListSelectionEvent e) {
450            setEnabled(displaylist.getSelectedIndices() != null && displaylist.getSelectedIndices().length > 0);
451        }
452    }
453
454    /**
455     * Sets the current selection to the list of relations selected in this dialog
456     *
457     */
458    class SelectMembersAction extends AbstractAction implements ListSelectionListener{
459        public SelectMembersAction() {
460            putValue(SHORT_DESCRIPTION,tr("Select the members of all selected relations"));
461            putValue(SMALL_ICON, ImageProvider.get("selectall"));
462            putValue(NAME, tr("Select members"));
463            updateEnabledState();
464        }
465
466        public void actionPerformed(ActionEvent e) {
467            if (!isEnabled()) return;
468            List<Relation> relations = model.getSelectedRelations();
469            HashSet<OsmPrimitive> members = new HashSet<OsmPrimitive>();
470            for(Relation r: relations) {
471                members.addAll(r.getMemberPrimitives());
472            }
473            Main.map.mapView.getEditLayer().data.setSelected(members);
474        }
475
476        protected void updateEnabledState() {
477            setEnabled(displaylist.getSelectedIndices() != null && displaylist.getSelectedIndices().length > 0);
478        }
479
480        public void valueChanged(ListSelectionEvent e) {
481            updateEnabledState();
482        }
483    }
484
485    /**
486     * The action for downloading members of all selected relations
487     *
488     */
489    class DownloadMembersAction extends AbstractAction implements ListSelectionListener{
490
491        public DownloadMembersAction() {
492            putValue(SHORT_DESCRIPTION,tr("Download all members of the selected relations"));
493            putValue(NAME, tr("Download members"));
494            putValue(SMALL_ICON, ImageProvider.get("dialogs", "downloadincomplete"));
495            putValue("help", ht("/Dialog/RelationList#DownloadMembers"));
496            updateEnabledState();
497        }
498
499        protected void updateEnabledState() {
500            setEnabled(! model.getSelectedNonNewRelations().isEmpty());
501        }
502
503        public void valueChanged(ListSelectionEvent e) {
504            updateEnabledState();
505        }
506
507        public void actionPerformed(ActionEvent e) {
508            List<Relation> relations = model.getSelectedNonNewRelations();
509            if (relations.isEmpty())
510                return;
511            Main.worker.submit(new DownloadRelationTask(
512                    model.getSelectedNonNewRelations(),
513                    Main.map.mapView.getEditLayer())
514            );
515        }
516    }
517
518    /**
519     * Action for downloading incomplete members of selected relations
520     *
521     */
522    class DownloadSelectedIncompleteMembersAction extends AbstractAction implements ListSelectionListener{
523        public DownloadSelectedIncompleteMembersAction() {
524            putValue(SHORT_DESCRIPTION, tr("Download incomplete members of selected relations"));
525            putValue(SMALL_ICON, ImageProvider.get("dialogs/relation", "downloadincompleteselected"));
526            putValue(NAME, tr("Download incomplete members"));
527            updateEnabledState();
528        }
529
530        public Set<OsmPrimitive> buildSetOfIncompleteMembers(List<Relation> rels) {
531            Set<OsmPrimitive> ret = new HashSet<OsmPrimitive>();
532            for(Relation r: rels) {
533                ret.addAll(r.getIncompleteMembers());
534            }
535            return ret;
536        }
537
538        public void actionPerformed(ActionEvent e) {
539            if (!isEnabled())
540                return;
541            List<Relation> rels = model.getSelectedRelationsWithIncompleteMembers();
542            if (rels.isEmpty()) return;
543            Main.worker.submit(new DownloadRelationMemberTask(
544                    rels,
545                    buildSetOfIncompleteMembers(rels),
546                    Main.map.mapView.getEditLayer()
547            ));
548        }
549
550        protected void updateEnabledState() {
551            setEnabled(!model.getSelectedRelationsWithIncompleteMembers().isEmpty());
552        }
553
554        public void valueChanged(ListSelectionEvent e) {
555            updateEnabledState();
556        }
557    }
558
559    /**
560     * The list model for the list of relations displayed in the relation list
561     * dialog.
562     *
563     */
564    private class RelationListModel extends AbstractListModel {
565        private final ArrayList<Relation> relations = new ArrayList<Relation>();
566        private DefaultListSelectionModel selectionModel;
567
568        public RelationListModel(DefaultListSelectionModel selectionModel) {
569            this.selectionModel = selectionModel;
570        }
571
572        public Relation getRelation(int idx) {
573            return relations.get(idx);
574        }
575
576        public void sort() {
577            Collections.sort(
578                    relations,
579                    DefaultNameFormatter.getInstance().getRelationComparator()
580            );
581        }
582
583        private boolean isValid(Relation r) {
584            return !r.isDeleted() && r.isVisible() && !r.isIncomplete();
585        }
586
587        public void setRelations(Collection<Relation> relations) {
588            List<Relation> sel =  getSelectedRelations();
589            this.relations.clear();
590            if (relations == null) {
591                selectionModel.clearSelection();
592                fireContentsChanged(this,0,getSize());
593                return;
594
595            }
596            for (Relation r: relations) {
597                if (isValid(r)) {
598                    this.relations.add(r);
599                }
600            }
601            sort();
602            fireIntervalAdded(this, 0, getSize());
603            setSelectedRelations(sel);
604        }
605
606        /**
607         * Add all relations in <code>addedPrimitives</code> to the model for the
608         * relation list dialog
609         *
610         * @param addedPrimitives the collection of added primitives. May include nodes,
611         * ways, and relations.
612         */
613        public void addRelations(Collection<? extends OsmPrimitive> addedPrimitives) {
614            boolean added = false;
615            for (OsmPrimitive p: addedPrimitives) {
616                if (! (p instanceof Relation)) {
617                    continue;
618                }
619
620                Relation r = (Relation)p;
621                if (relations.contains(r)) {
622                    continue;
623                }
624                if (isValid(r)) {
625                    relations.add(r);
626                    added = true;
627                }
628            }
629            if (added) {
630                List<Relation> sel = getSelectedRelations();
631                sort();
632                fireIntervalAdded(this, 0, getSize());
633                setSelectedRelations(sel);
634            }
635        }
636
637        /**
638         * Removes all relations in <code>removedPrimitives</code> from the model
639         *
640         * @param removedPrimitives the removed primitives. May include nodes, ways,
641         *   and relations
642         */
643        public void removeRelations(Collection<? extends OsmPrimitive> removedPrimitives) {
644            if (removedPrimitives == null) return;
645            // extract the removed relations
646            //
647            Set<Relation> removedRelations = new HashSet<Relation>();
648            for (OsmPrimitive p: removedPrimitives) {
649                if (! (p instanceof Relation)) {
650                    continue;
651                }
652                removedRelations.add((Relation)p);
653            }
654            if (removedRelations.isEmpty())
655                return;
656            int size = relations.size();
657            relations.removeAll(removedRelations);
658            if (size != relations.size()) {
659                List<Relation> sel = getSelectedRelations();
660                sort();
661                fireContentsChanged(this, 0, getSize());
662                setSelectedRelations(sel);
663            }
664        }
665
666        /**
667         * Replies the list of selected relations with incomplete members
668         *
669         * @return the list of selected relations with incomplete members
670         */
671        public List<Relation> getSelectedRelationsWithIncompleteMembers() {
672            List<Relation> ret = getSelectedNonNewRelations();
673            Iterator<Relation> it = ret.iterator();
674            while(it.hasNext()) {
675                Relation r = it.next();
676                if (!r.hasIncompleteMembers()) {
677                    it.remove();
678                }
679            }
680            return ret;
681        }
682
683        public Object getElementAt(int index) {
684            return relations.get(index);
685        }
686
687        public int getSize() {
688            return relations.size();
689        }
690
691        /**
692         * Replies the list of selected, non-new relations. Empty list,
693         * if there are no selected, non-new relations.
694         *
695         * @return the list of selected, non-new relations.
696         */
697        public List<Relation> getSelectedNonNewRelations() {
698            ArrayList<Relation> ret = new ArrayList<Relation>();
699            for (int i=0; i<getSize();i++) {
700                if (!selectionModel.isSelectedIndex(i)) {
701                    continue;
702                }
703                if (relations.get(i).isNew()) {
704                    continue;
705                }
706                ret.add(relations.get(i));
707            }
708            return ret;
709        }
710
711        /**
712         * Replies the list of selected relations. Empty list,
713         * if there are no selected relations.
714         *
715         * @return the list of selected, non-new relations.
716         */
717        public List<Relation> getSelectedRelations() {
718            ArrayList<Relation> ret = new ArrayList<Relation>();
719            for (int i=0; i<getSize();i++) {
720                if (!selectionModel.isSelectedIndex(i)) {
721                    continue;
722                }
723                ret.add(relations.get(i));
724            }
725            return ret;
726        }
727
728        /**
729         * Sets the selected relations.
730         *
731         * @return sel the list of selected relations
732         */
733        public void setSelectedRelations(List<Relation> sel) {
734            selectionModel.clearSelection();
735            if (sel == null || sel.isEmpty())
736                return;
737            for (Relation r: sel) {
738                int i = relations.indexOf(r);
739                if (i<0) {
740                    continue;
741                }
742                selectionModel.addSelectionInterval(i,i);
743            }
744        }
745
746        /**
747         * Returns the index of the relation
748         *
749         * @return index of relation (null if it cannot be found)
750         */
751        public Integer getRelationIndex(Relation rel) {
752            int i = relations.indexOf(rel);
753            if (i<0)
754                return null;
755            return i;
756        }
757
758        public void updateTitle() {
759            if (getSize() > 0) {
760                RelationListDialog.this.setTitle(tr("Relations: {0}", getSize()));
761            } else {
762                RelationListDialog.this.setTitle(tr("Relations"));
763            }
764        }
765    }
766
767    class RelationDialogPopupMenu extends JPopupMenu {
768        protected void build() {
769            // -- download members action
770            //
771            DownloadMembersAction downloadMembersAction = new DownloadMembersAction();
772            displaylist.addListSelectionListener(downloadMembersAction);
773            add(downloadMembersAction);
774
775            // -- download incomplete members action
776            //
777            DownloadSelectedIncompleteMembersAction downloadSelectedIncompleteMembers = new DownloadSelectedIncompleteMembersAction();
778            displaylist.addListSelectionListener(downloadSelectedIncompleteMembers);
779            add(downloadSelectedIncompleteMembers);
780
781            addSeparator();
782
783            // -- select members action
784            //
785            SelectMembersAction selectMembersAction = new SelectMembersAction();
786            displaylist.addListSelectionListener(selectMembersAction);
787            add(selectMembersAction);
788        }
789
790        public RelationDialogPopupMenu() {
791            build();
792        }
793    }
794
795    /* ---------------------------------------------------------------------------------- */
796    /* DataSetListener                                                                    */
797    /* ---------------------------------------------------------------------------------- */
798
799    public void nodeMoved(NodeMovedEvent event) {/* irrelevant in this context */}
800
801    public void wayNodesChanged(WayNodesChangedEvent event) {/* irrelevant in this context */}
802
803    public void primtivesAdded(final PrimitivesAddedEvent event) {
804        model.addRelations(event.getPrimitives());
805        model.updateTitle();
806    }
807
808    public void primtivesRemoved(final PrimitivesRemovedEvent event) {
809        model.removeRelations(event.getPrimitives());
810        model.updateTitle();
811    }
812
813    public void relationMembersChanged(final RelationMembersChangedEvent event) {
814        List<Relation> sel = model.getSelectedRelations();
815        model.sort();
816        model.setSelectedRelations(sel);
817        displaylist.repaint();
818    }
819
820    public void tagsChanged(TagsChangedEvent event) {
821        OsmPrimitive prim = event.getPrimitive();
822        if (prim == null || ! (prim instanceof Relation))
823            return;
824        // trigger a sort of the relation list because the display name may
825        // have changed
826        //
827        List<Relation> sel = model.getSelectedRelations();
828        model.sort();
829        model.setSelectedRelations(sel);
830        displaylist.repaint();
831    }
832
833    public void dataChanged(DataChangedEvent event) {
834        initFromLayer(Main.main.getEditLayer());
835    }
836
837    public void otherDatasetChange(AbstractDatasetChangedEvent event) {/* ignore */}
838}
Note: See TracBrowser for help on using the repository browser.