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

Last change on this file since 4223 was 4223, checked in by stoecker, 8 years ago

fix #6570 (revert change in r4215, see #6547), i18n update, fix typo in function names

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