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

Last change on this file since 4957 was 4957, checked in by stoecker, 7 years ago

some shortcut fixes

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