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

Last change on this file since 5028 was 5028, checked in by jttt, 7 years ago

Add possibility to hide side buttons in toggle dialogs permanently, show actions from buttons in popup menu

  • 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.ALT_SHIFT), 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            List<Relation> toDelete = new LinkedList<Relation>();
343            for (int i : displaylist.getSelectedIndices()) {
344                toDelete.add(model.getRelation(i));
345            }
346            for (Relation r : toDelete) {
347                deleteRelation(r);
348            }
349            displaylist.clearSelection();
350        }
351
352        public void valueChanged(ListSelectionEvent e) {
353            setEnabled(displaylist.getSelectedIndices() != null && displaylist.getSelectedIndices().length > 0);
354        }
355    }
356
357    /**
358     * The action for creating a new relation
359     *
360     */
361    static class NewAction extends AbstractAction implements LayerChangeListener{
362        public NewAction() {
363            putValue(SHORT_DESCRIPTION,tr("Create a new relation"));
364            putValue(NAME, tr("New"));
365            putValue(SMALL_ICON, ImageProvider.get("dialogs", "addrelation"));
366            updateEnabledState();
367        }
368
369        public void run() {
370            RelationEditor.getEditor(Main.main.getEditLayer(),null, null).setVisible(true);
371        }
372
373        public void actionPerformed(ActionEvent e) {
374            run();
375        }
376
377        protected void updateEnabledState() {
378            setEnabled(Main.main != null && Main.main.getEditLayer() != null);
379        }
380
381        public void activeLayerChange(Layer oldLayer, Layer newLayer) {
382            updateEnabledState();
383        }
384
385        public void layerAdded(Layer newLayer) {
386            updateEnabledState();
387        }
388
389        public void layerRemoved(Layer oldLayer) {
390            updateEnabledState();
391        }
392    }
393
394    /**
395     * Creates a new relation with a copy of the current editor state
396     *
397     */
398    class DuplicateAction extends AbstractAction implements ListSelectionListener {
399        public DuplicateAction() {
400            putValue(SHORT_DESCRIPTION, tr("Create a copy of this relation and open it in another editor window"));
401            putValue(SMALL_ICON, ImageProvider.get("duplicate"));
402            putValue(NAME, tr("Duplicate"));
403            updateEnabledState();
404        }
405
406        public void launchEditorForDuplicate(Relation original) {
407            Relation copy = new Relation(original, true);
408            copy.setModified(true);
409            RelationEditor editor = RelationEditor.getEditor(
410                    Main.main.getEditLayer(),
411                    copy,
412                    null /* no selected members */
413                    );
414            editor.setVisible(true);
415        }
416
417        public void actionPerformed(ActionEvent e) {
418            if (!isEnabled())
419                return;
420            launchEditorForDuplicate(getSelected());
421        }
422
423        protected void updateEnabledState() {
424            setEnabled(displaylist.getSelectedIndices() != null && displaylist.getSelectedIndices().length == 1);
425        }
426
427        public void valueChanged(ListSelectionEvent e) {
428            updateEnabledState();
429        }
430    }
431
432    /**
433     * Sets the current selection to the list of relations selected in this dialog
434     *
435     */
436    class SelectAction extends AbstractAction implements ListSelectionListener{
437        boolean add;
438        public SelectAction(boolean add) {
439            putValue(SHORT_DESCRIPTION, add ? tr("Add the selected relations to the current selection")
440                    : tr("Set the current selection to the list of selected relations"));
441            putValue(SMALL_ICON, ImageProvider.get("dialogs", "select"));
442            putValue(NAME, add ? tr("Select relation (add)") : tr("Select relation"));
443            this.add = add;
444            updateEnabledState();
445        }
446
447        public void actionPerformed(ActionEvent e) {
448            if (!isEnabled()) return;
449            int [] idx = displaylist.getSelectedIndices();
450            if (idx == null || idx.length == 0) return;
451            ArrayList<OsmPrimitive> selection = new ArrayList<OsmPrimitive>(idx.length);
452            for (int i: idx) {
453                selection.add(model.getRelation(i));
454            }
455            if(add) {
456                Main.map.mapView.getEditLayer().data.addSelected(selection);
457            } else {
458                Main.map.mapView.getEditLayer().data.setSelected(selection);
459            }
460        }
461
462        protected void updateEnabledState() {
463            setEnabled(displaylist.getSelectedIndices() != null && displaylist.getSelectedIndices().length > 0);
464        }
465
466        public void valueChanged(ListSelectionEvent e) {
467            updateEnabledState();
468        }
469    }
470
471    /**
472     * Sets the current selection to the list of relations selected in this dialog
473     *
474     */
475    class SelectMembersAction extends AbstractAction implements ListSelectionListener{
476        boolean add;
477        public SelectMembersAction(boolean add) {
478            putValue(SHORT_DESCRIPTION,add ? tr("Add the members of all selected relations to current selection")
479                    : tr("Select the members of all selected relations"));
480            putValue(SMALL_ICON, ImageProvider.get("selectall"));
481            putValue(NAME, add ? tr("Select members (add)") : tr("Select members"));
482            this.add = add;
483            updateEnabledState();
484        }
485
486        public void actionPerformed(ActionEvent e) {
487            if (!isEnabled()) return;
488            List<Relation> relations = model.getSelectedRelations();
489            HashSet<OsmPrimitive> members = new HashSet<OsmPrimitive>();
490            for(Relation r: relations) {
491                members.addAll(r.getMemberPrimitives());
492            }
493            if(add) {
494                Main.map.mapView.getEditLayer().data.addSelected(members);
495            } else {
496                Main.map.mapView.getEditLayer().data.setSelected(members);
497            }
498        }
499
500        protected void updateEnabledState() {
501            setEnabled(displaylist.getSelectedIndices() != null && displaylist.getSelectedIndices().length > 0);
502        }
503
504        public void valueChanged(ListSelectionEvent e) {
505            updateEnabledState();
506        }
507    }
508
509    /**
510     * The action for downloading members of all selected relations
511     *
512     */
513    class DownloadMembersAction extends AbstractAction implements ListSelectionListener{
514
515        public DownloadMembersAction() {
516            putValue(SHORT_DESCRIPTION,tr("Download all members of the selected relations"));
517            putValue(NAME, tr("Download members"));
518            putValue(SMALL_ICON, ImageProvider.get("dialogs", "downloadincomplete"));
519            putValue("help", ht("/Dialog/RelationList#DownloadMembers"));
520            updateEnabledState();
521        }
522
523        protected void updateEnabledState() {
524            setEnabled(! model.getSelectedNonNewRelations().isEmpty());
525        }
526
527        public void valueChanged(ListSelectionEvent e) {
528            updateEnabledState();
529        }
530
531        public void actionPerformed(ActionEvent e) {
532            List<Relation> relations = model.getSelectedNonNewRelations();
533            if (relations.isEmpty())
534                return;
535            Main.worker.submit(new DownloadRelationTask(
536                    model.getSelectedNonNewRelations(),
537                    Main.map.mapView.getEditLayer())
538                    );
539        }
540    }
541
542    /**
543     * Action for downloading incomplete members of selected relations
544     *
545     */
546    class DownloadSelectedIncompleteMembersAction extends AbstractAction implements ListSelectionListener{
547        public DownloadSelectedIncompleteMembersAction() {
548            putValue(SHORT_DESCRIPTION, tr("Download incomplete members of selected relations"));
549            putValue(SMALL_ICON, ImageProvider.get("dialogs/relation", "downloadincompleteselected"));
550            putValue(NAME, tr("Download incomplete members"));
551            updateEnabledState();
552        }
553
554        public Set<OsmPrimitive> buildSetOfIncompleteMembers(List<Relation> rels) {
555            Set<OsmPrimitive> ret = new HashSet<OsmPrimitive>();
556            for(Relation r: rels) {
557                ret.addAll(r.getIncompleteMembers());
558            }
559            return ret;
560        }
561
562        public void actionPerformed(ActionEvent e) {
563            if (!isEnabled())
564                return;
565            List<Relation> rels = model.getSelectedRelationsWithIncompleteMembers();
566            if (rels.isEmpty()) return;
567            Main.worker.submit(new DownloadRelationMemberTask(
568                    rels,
569                    buildSetOfIncompleteMembers(rels),
570                    Main.map.mapView.getEditLayer()
571                    ));
572        }
573
574        protected void updateEnabledState() {
575            setEnabled(!model.getSelectedRelationsWithIncompleteMembers().isEmpty());
576        }
577
578        public void valueChanged(ListSelectionEvent e) {
579            updateEnabledState();
580        }
581    }
582
583    /**
584     * The list model for the list of relations displayed in the relation list
585     * dialog.
586     *
587     */
588    private class RelationListModel extends AbstractListModel {
589        private final ArrayList<Relation> relations = new ArrayList<Relation>();
590        private DefaultListSelectionModel selectionModel;
591
592        public RelationListModel(DefaultListSelectionModel selectionModel) {
593            this.selectionModel = selectionModel;
594        }
595
596        public Relation getRelation(int idx) {
597            return relations.get(idx);
598        }
599
600        public void sort() {
601            Collections.sort(
602                    relations,
603                    DefaultNameFormatter.getInstance().getRelationComparator()
604                    );
605        }
606
607        private boolean isValid(Relation r) {
608            return !r.isDeleted() && r.isVisible() && !r.isIncomplete();
609        }
610
611        public void setRelations(Collection<Relation> relations) {
612            List<Relation> sel =  getSelectedRelations();
613            this.relations.clear();
614            if (relations == null) {
615                selectionModel.clearSelection();
616                fireContentsChanged(this,0,getSize());
617                return;
618
619            }
620            for (Relation r: relations) {
621                if (isValid(r)) {
622                    this.relations.add(r);
623                }
624            }
625            sort();
626            fireIntervalAdded(this, 0, getSize());
627            setSelectedRelations(sel);
628        }
629
630        /**
631         * Add all relations in <code>addedPrimitives</code> to the model for the
632         * relation list dialog
633         *
634         * @param addedPrimitives the collection of added primitives. May include nodes,
635         * ways, and relations.
636         */
637        public void addRelations(Collection<? extends OsmPrimitive> addedPrimitives) {
638            boolean added = false;
639            for (OsmPrimitive p: addedPrimitives) {
640                if (! (p instanceof Relation)) {
641                    continue;
642                }
643
644                Relation r = (Relation)p;
645                if (relations.contains(r)) {
646                    continue;
647                }
648                if (isValid(r)) {
649                    relations.add(r);
650                    added = true;
651                }
652            }
653            if (added) {
654                List<Relation> sel = getSelectedRelations();
655                sort();
656                fireIntervalAdded(this, 0, getSize());
657                setSelectedRelations(sel);
658            }
659        }
660
661        /**
662         * Removes all relations in <code>removedPrimitives</code> from the model
663         *
664         * @param removedPrimitives the removed primitives. May include nodes, ways,
665         *   and relations
666         */
667        public void removeRelations(Collection<? extends OsmPrimitive> removedPrimitives) {
668            if (removedPrimitives == null) return;
669            // extract the removed relations
670            //
671            Set<Relation> removedRelations = new HashSet<Relation>();
672            for (OsmPrimitive p: removedPrimitives) {
673                if (! (p instanceof Relation)) {
674                    continue;
675                }
676                removedRelations.add((Relation)p);
677            }
678            if (removedRelations.isEmpty())
679                return;
680            int size = relations.size();
681            relations.removeAll(removedRelations);
682            if (size != relations.size()) {
683                List<Relation> sel = getSelectedRelations();
684                sort();
685                fireContentsChanged(this, 0, getSize());
686                setSelectedRelations(sel);
687            }
688        }
689
690        /**
691         * Replies the list of selected relations with incomplete members
692         *
693         * @return the list of selected relations with incomplete members
694         */
695        public List<Relation> getSelectedRelationsWithIncompleteMembers() {
696            List<Relation> ret = getSelectedNonNewRelations();
697            Iterator<Relation> it = ret.iterator();
698            while(it.hasNext()) {
699                Relation r = it.next();
700                if (!r.hasIncompleteMembers()) {
701                    it.remove();
702                }
703            }
704            return ret;
705        }
706
707        public Object getElementAt(int index) {
708            return relations.get(index);
709        }
710
711        public int getSize() {
712            return relations.size();
713        }
714
715        /**
716         * Replies the list of selected, non-new relations. Empty list,
717         * if there are no selected, non-new relations.
718         *
719         * @return the list of selected, non-new relations.
720         */
721        public List<Relation> getSelectedNonNewRelations() {
722            ArrayList<Relation> ret = new ArrayList<Relation>();
723            for (int i=0; i<getSize();i++) {
724                if (!selectionModel.isSelectedIndex(i)) {
725                    continue;
726                }
727                if (relations.get(i).isNew()) {
728                    continue;
729                }
730                ret.add(relations.get(i));
731            }
732            return ret;
733        }
734
735        /**
736         * Replies the list of selected relations. Empty list,
737         * if there are no selected relations.
738         *
739         * @return the list of selected, non-new relations.
740         */
741        public List<Relation> getSelectedRelations() {
742            ArrayList<Relation> ret = new ArrayList<Relation>();
743            for (int i=0; i<getSize();i++) {
744                if (!selectionModel.isSelectedIndex(i)) {
745                    continue;
746                }
747                ret.add(relations.get(i));
748            }
749            return ret;
750        }
751
752        /**
753         * Sets the selected relations.
754         *
755         * @return sel the list of selected relations
756         */
757        public void setSelectedRelations(Collection<Relation> sel) {
758            selectionModel.clearSelection();
759            if (sel == null || sel.isEmpty())
760                return;
761            for (Relation r: sel) {
762                int i = relations.indexOf(r);
763                if (i<0) {
764                    continue;
765                }
766                selectionModel.addSelectionInterval(i,i);
767            }
768        }
769
770        /**
771         * Returns the index of the relation
772         *
773         * @return index of relation (null if it cannot be found)
774         */
775        public Integer getRelationIndex(Relation rel) {
776            int i = relations.indexOf(rel);
777            if (i<0)
778                return null;
779            return i;
780        }
781
782        public void updateTitle() {
783            if (getSize() > 0) {
784                RelationListDialog.this.setTitle(tr("Relations: {0}", getSize()));
785            } else {
786                RelationListDialog.this.setTitle(tr("Relations"));
787            }
788        }
789    }
790
791    class RelationDialogPopupMenu extends ListPopupMenu {
792
793        public RelationDialogPopupMenu(JList list) {
794            super(list);
795
796            // -- download members action
797            //
798            add(new DownloadMembersAction());
799
800            // -- download incomplete members action
801            //
802            add(new DownloadSelectedIncompleteMembersAction());
803
804            addSeparator();
805
806            // -- select members action
807            //
808            add(new SelectMembersAction(false));
809            add(new SelectMembersAction(true));
810
811            // -- select action
812            //
813            add(new SelectAction(false));
814            add(new SelectAction(true));
815        }
816    }
817
818    public void addPopupMenuSeparator() {
819        popupMenu.addSeparator();
820    }
821
822    public JMenuItem addPopupMenuAction(Action a) {
823        return popupMenu.add(a);
824    }
825
826    public void addPopupMenuListener(PopupMenuListener l) {
827        popupMenu.addPopupMenuListener(l);
828    }
829
830    public void removePopupMenuListener(PopupMenuListener l) {
831        popupMenu.addPopupMenuListener(l);
832    }
833
834    public Collection<Relation> getSelectedRelations() {
835        return model.getSelectedRelations();
836    }
837
838    /* ---------------------------------------------------------------------------------- */
839    /* DataSetListener                                                                    */
840    /* ---------------------------------------------------------------------------------- */
841
842    public void nodeMoved(NodeMovedEvent event) {/* irrelevant in this context */}
843
844    public void wayNodesChanged(WayNodesChangedEvent event) {/* irrelevant in this context */}
845
846    public void primitivesAdded(final PrimitivesAddedEvent event) {
847        model.addRelations(event.getPrimitives());
848        model.updateTitle();
849    }
850
851    public void primitivesRemoved(final PrimitivesRemovedEvent event) {
852        model.removeRelations(event.getPrimitives());
853        model.updateTitle();
854    }
855
856    public void relationMembersChanged(final RelationMembersChangedEvent event) {
857        List<Relation> sel = model.getSelectedRelations();
858        model.sort();
859        model.setSelectedRelations(sel);
860        displaylist.repaint();
861    }
862
863    public void tagsChanged(TagsChangedEvent event) {
864        OsmPrimitive prim = event.getPrimitive();
865        if (prim == null || ! (prim instanceof Relation))
866            return;
867        // trigger a sort of the relation list because the display name may
868        // have changed
869        //
870        List<Relation> sel = model.getSelectedRelations();
871        model.sort();
872        model.setSelectedRelations(sel);
873        displaylist.repaint();
874    }
875
876    public void dataChanged(DataChangedEvent event) {
877        initFromLayer(Main.main.getEditLayer());
878    }
879
880    public void otherDatasetChange(AbstractDatasetChangedEvent event) {/* ignore */}
881}
Note: See TracBrowser for help on using the repository browser.