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

Last change on this file since 4459 was 4459, checked in by bastiK, 13 years ago

applied #6856 - Enable plugins to add actions in popup menus (patch by Don-vip)

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