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
RevLine 
[3719]1// License: GPL. For details, see LICENSE file.
[626]2package org.openstreetmap.josm.gui.dialogs;
3
[2317]4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
[626]5import static org.openstreetmap.josm.tools.I18n.tr;
6
[2317]7import java.awt.Point;
[626]8import java.awt.event.ActionEvent;
9import java.awt.event.KeyEvent;
10import java.awt.event.MouseAdapter;
11import java.awt.event.MouseEvent;
[2126]12import java.util.ArrayList;
[4353]13import java.util.Arrays;
[1886]14import java.util.Collection;
[2126]15import java.util.Collections;
[1886]16import java.util.HashSet;
[3102]17import java.util.Iterator;
[2317]18import java.util.List;
[2487]19import java.util.Set;
[626]20
[1778]21import javax.swing.AbstractAction;
[2126]22import javax.swing.AbstractListModel;
[4459]23import javax.swing.Action;
[2317]24import javax.swing.DefaultListSelectionModel;
[626]25import javax.swing.JList;
[4459]26import javax.swing.JMenuItem;
[2301]27import javax.swing.KeyStroke;
[626]28import javax.swing.ListSelectionModel;
[1916]29import javax.swing.SwingUtilities;
[1419]30import javax.swing.event.ListSelectionEvent;
[997]31import javax.swing.event.ListSelectionListener;
[1778]32
[626]33import org.openstreetmap.josm.Main;
[755]34import org.openstreetmap.josm.data.osm.OsmPrimitive;
[626]35import org.openstreetmap.josm.data.osm.Relation;
[1886]36import org.openstreetmap.josm.data.osm.RelationMember;
[2655]37import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
[2622]38import org.openstreetmap.josm.data.osm.event.DataChangedEvent;
39import org.openstreetmap.josm.data.osm.event.DataSetListener;
40import org.openstreetmap.josm.data.osm.event.DatasetEventManager;
[4070]41import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode;
[2622]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;
[2126]48import org.openstreetmap.josm.gui.DefaultNameFormatter;
[2621]49import org.openstreetmap.josm.gui.MapView;
[4070]50import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
[626]51import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
[2710]52import org.openstreetmap.josm.gui.SideButton;
[3102]53import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask;
[2563]54import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationTask;
[1599]55import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
[626]56import org.openstreetmap.josm.gui.layer.Layer;
57import org.openstreetmap.josm.gui.layer.OsmDataLayer;
[4459]58import org.openstreetmap.josm.gui.widgets.ListPopupMenu;
[1778]59import org.openstreetmap.josm.tools.ImageProvider;
[1084]60import org.openstreetmap.josm.tools.Shortcut;
[626]61
62/**
63 * A dialog showing all known relations, with buttons to add, edit, and
[1023]64 * delete them.
65 *
[1554]66 * We don't have such dialogs for nodes, segments, and ways, because those
[626]67 * objects are visible on the map and can be selected there. Relations are not.
68 */
[2623]69public class RelationListDialog extends ToggleDialog implements DataSetListener {
[2126]70 /** The display list. */
71 private JList displaylist;
72 /** the list model used */
73 private RelationListModel model;
[626]74
[1778]75 /** the edit action */
76 private EditAction editAction;
77 /** the delete action */
78 private DeleteAction deleteAction;
[2485]79 private NewAction newAction;
[2317]80 /** the popup menu */
81 private RelationDialogPopupMenu popupMenu;
[1677]82
[1778]83 /**
84 * constructor
85 */
[1169]86 public RelationListDialog() {
87 super(tr("Relations"), "relationlist", tr("Open a list of all relations."),
[3202]88 Shortcut.registerShortcut("subwindow:relations", tr("Toggle: {0}", tr("Relations")), KeyEvent.VK_R,
[4070]89 Shortcut.GROUP_LAYER, Shortcut.SHIFT_DEFAULT), 150);
[1778]90
91 // create the list of relations
92 //
[2317]93 DefaultListSelectionModel selectionModel = new DefaultListSelectionModel();
94 model = new RelationListModel(selectionModel);
[2126]95 displaylist = new JList(model);
[2317]96 displaylist.setSelectionModel(selectionModel);
[2885]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 });
[2194]106 displaylist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
[2317]107 displaylist.addMouseListener(new MouseEventHandler());
[626]108
[1866]109 // the new action
110 //
[2485]111 newAction = new NewAction();
[1866]112
[1778]113 // the edit action
114 //
115 editAction = new EditAction();
116 displaylist.addListSelectionListener(editAction);
[1023]117
[2194]118 // the duplicate action
[1916]119 //
120 DuplicateAction duplicateAction = new DuplicateAction();
121 displaylist.addListSelectionListener(duplicateAction);
122
[1778]123 // the delete action
124 //
125 deleteAction = new DeleteAction();
126 displaylist.addListSelectionListener(deleteAction);
[2194]127
128 // the select action
129 //
[4158]130 SelectAction selectAction = new SelectAction(false);
[2194]131 displaylist.addListSelectionListener(selectAction);
132
[4353]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 }));
[2487]140
141 // activate DEL in the list of relations
[2301]142 displaylist.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE,0), "deleteRelation");
143 displaylist.getActionMap().put("deleteRelation", deleteAction);
[1677]144
[4459]145 popupMenu = new RelationDialogPopupMenu(displaylist);
[2485]146 }
[2317]147
[2485]148 @Override public void showNotify() {
[2621]149 MapView.addLayerChangeListener(newAction);
[2691]150 newAction.updateEnabledState();
[2741]151 DatasetEventManager.getInstance().addDatasetListener(this, FireMode.IN_EDT);
[2623]152 dataChanged(null);
[1169]153 }
[626]154
[2485]155 @Override public void hideNotify() {
[2621]156 MapView.removeLayerChangeListener(newAction);
[2622]157 DatasetEventManager.getInstance().removeDatasetListener(this);
[1169]158 }
[1023]159
[2126]160 /**
[2487]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.
[2512]165 *
[2487]166 * @param layer the layer. May be null.
[2126]167 */
[2487]168 protected void initFromLayer(Layer layer) {
169 if (layer == null || ! (layer instanceof OsmDataLayer)) {
[2126]170 model.setRelations(null);
[1897]171 return;
172 }
[2487]173 OsmDataLayer l = (OsmDataLayer)layer;
174 model.setRelations(l.data.getRelations());
[3020]175 model.updateTitle();
[1169]176 }
[1023]177
[1169]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 }
[997]186
[1169]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 }
[1677]195
[1419]196 /**
197 * @return The selected relation in the list
198 */
199 private Relation getSelected() {
[2126]200 if(model.getSize() == 1) {
[1419]201 displaylist.setSelectedIndex(0);
[1763]202 }
[1419]203 return (Relation) displaylist.getSelectedValue();
204 }
[1763]205
206 /**
207 * Selects the relation <code>relation</code> in the list of relations.
[1897]208 *
[1763]209 * @param relation the relation
210 */
211 public void selectRelation(Relation relation) {
[2487]212 if (relation == null) {
213 model.setSelectedRelations(null);
[2126]214 } else {
[2487]215 model.setSelectedRelations(Collections.singletonList(relation));
[2894]216 Integer i = model.getRelationIndex(relation);
[2914]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 }
[1780]220 }
[1763]221 }
[1778]222
[2317]223 class MouseEventHandler extends MouseAdapter {
[1916]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) {
[3102]233 if (Main.main.getEditLayer() == null) return;
[1916]234 if (e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e)) {
235 if (e.isControlDown()) {
236 editCurrentRelation();
237 } else {
238 setCurrentRelationAsSelection();
239 }
240 }
241 }
[2317]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 }
[2563]251 popupMenu.show(displaylist, p.x, p.y-3);
[2317]252 }
253 @Override public void mousePressed(MouseEvent e) {
[3102]254 if (Main.main.getEditLayer() == null) return;
[2317]255 if (e.isPopupTrigger()) {
256 openPopup(e);
257 }
258 }
259 @Override public void mouseReleased(MouseEvent e) {
[3102]260 if (Main.main.getEditLayer() == null) return;
[2317]261 if (e.isPopupTrigger()) {
262 openPopup(e);
263 }
264 }
[1916]265 }
266
[1778]267 /**
268 * The edit action
269 *
270 */
[1916]271 class EditAction extends AbstractAction implements ListSelectionListener{
[1778]272 public EditAction() {
273 putValue(SHORT_DESCRIPTION,tr( "Open an editor for the selected relation"));
[2194]274 //putValue(NAME, tr("Edit"));
[1778]275 putValue(SMALL_ICON, ImageProvider.get("dialogs", "edit"));
276 setEnabled(false);
277 }
[1886]278 protected Collection<RelationMember> getMembersForCurrentSelection(Relation r) {
279 Collection<RelationMember> members = new HashSet<RelationMember>();
280 Collection<OsmPrimitive> selection = Main.map.mapView.getEditLayer().data.getSelected();
[1925]281 for (RelationMember member: r.getMembers()) {
[1938]282 if (selection.contains(member.getMember())) {
[1886]283 members.add(member);
284 }
285 }
286 return members;
287 }
[1778]288
[1916]289 public void launchEditor(Relation toEdit) {
[1778]290 if (toEdit == null)
291 return;
[1886]292 RelationEditor.getEditor(Main.map.mapView.getEditLayer(),toEdit, getMembersForCurrentSelection(toEdit)).setVisible(true);
[1778]293 }
294
295 public void actionPerformed(ActionEvent e) {
[1916]296 if (!isEnabled())
297 return;
298 launchEditor(getSelected());
[1778]299 }
300
301 public void valueChanged(ListSelectionEvent e) {
[2194]302 setEnabled(displaylist.getSelectedIndices() != null && displaylist.getSelectedIndices().length == 1);
[1778]303 }
304 }
305
306 /**
307 * The delete action
308 *
309 */
[2194]310 class DeleteAction extends AbstractAction implements ListSelectionListener {
[1856]311 class AbortException extends Exception {}
312
[1778]313 public DeleteAction() {
314 putValue(SHORT_DESCRIPTION,tr("Delete the selected relation"));
[2194]315 //putValue(NAME, tr("Delete"));
[1778]316 putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
317 setEnabled(false);
318 }
319
[2194]320 protected void deleteRelation(Relation toDelete) {
[1778]321 if (toDelete == null)
322 return;
[1856]323 org.openstreetmap.josm.actions.mapmode.DeleteAction.deleteRelation(
324 Main.main.getEditLayer(),
325 toDelete
326 );
[1778]327 }
328
329 public void actionPerformed(ActionEvent e) {
[2194]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 }
[1778]339 }
340
341 public void valueChanged(ListSelectionEvent e) {
342 setEnabled(displaylist.getSelectedIndices() != null && displaylist.getSelectedIndices().length > 0);
343 }
344 }
[1866]345
346 /**
[2487]347 * The action for creating a new relation
[1866]348 *
349 */
[2632]350 static class NewAction extends AbstractAction implements LayerChangeListener{
[1866]351 public NewAction() {
352 putValue(SHORT_DESCRIPTION,tr("Create a new relation"));
[2194]353 //putValue(NAME, tr("New"));
[1866]354 putValue(SMALL_ICON, ImageProvider.get("dialogs", "addrelation"));
[2632]355 updateEnabledState();
[1866]356 }
357
358 public void run() {
[2487]359 RelationEditor.getEditor(Main.main.getEditLayer(),null, null).setVisible(true);
[1866]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 }
[1916]382
383 /**
384 * Creates a new relation with a copy of the current editor state
[1925]385 *
[1916]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"));
[2194]391 //putValue(NAME, tr("Duplicate"));
[1916]392 updateEnabledState();
393 }
394
395 public void launchEditorForDuplicate(Relation original) {
[2410]396 Relation copy = new Relation(original, true);
[2025]397 copy.setModified(true);
[1916]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 }
[2126]420
[2194]421 /**
422 * Sets the current selection to the list of relations selected in this dialog
423 *
424 */
425 class SelectAction extends AbstractAction implements ListSelectionListener{
[4158]426 boolean add;
427 public SelectAction(boolean add) {
428 putValue(SHORT_DESCRIPTION, add ? tr("Add the selected relations to the current selection")
[4221]429 : tr("Set the current selection to the list of selected relations"));
[2194]430 putValue(SMALL_ICON, ImageProvider.get("dialogs", "select"));
[4158]431 putValue(NAME, add ? tr("Select relation (add)") : tr("Select relation"));
432 this.add = add;
433 updateEnabledState();
[2194]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 }
[4221]444 if(add) {
[4158]445 Main.map.mapView.getEditLayer().data.addSelected(selection);
[4221]446 } else {
[4158]447 Main.map.mapView.getEditLayer().data.setSelected(selection);
[4221]448 }
[2194]449 }
450
[4158]451 protected void updateEnabledState() {
[2194]452 setEnabled(displaylist.getSelectedIndices() != null && displaylist.getSelectedIndices().length > 0);
453 }
[4158]454
455 public void valueChanged(ListSelectionEvent e) {
456 updateEnabledState();
457 }
[2194]458 }
459
[2317]460 /**
461 * Sets the current selection to the list of relations selected in this dialog
462 *
463 */
464 class SelectMembersAction extends AbstractAction implements ListSelectionListener{
[4158]465 boolean add;
466 public SelectMembersAction(boolean add) {
467 putValue(SHORT_DESCRIPTION,add ? tr("Add the members of all selected relations to current selection")
[4221]468 : tr("Select the members of all selected relations"));
[2317]469 putValue(SMALL_ICON, ImageProvider.get("selectall"));
[4158]470 putValue(NAME, add ? tr("Select members (add)") : tr("Select members"));
471 this.add = add;
[2317]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 }
[4221]482 if(add) {
[4158]483 Main.map.mapView.getEditLayer().data.addSelected(members);
[4221]484 } else {
[4158]485 Main.map.mapView.getEditLayer().data.setSelected(members);
[4221]486 }
[2317]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
[2487]498 /**
499 * The action for downloading members of all selected relations
[2512]500 *
[2487]501 */
[2317]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;
[2563]524 Main.worker.submit(new DownloadRelationTask(
[2317]525 model.getSelectedNonNewRelations(),
[2563]526 Main.map.mapView.getEditLayer())
527 );
[2317]528 }
529 }
530
[2487]531 /**
[3102]532 * Action for downloading incomplete members of selected relations
[3530]533 *
[3102]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 /**
[2487]573 * The list model for the list of relations displayed in the relation list
574 * dialog.
575 *
576 */
[3020]577 private class RelationListModel extends AbstractListModel {
[2504]578 private final ArrayList<Relation> relations = new ArrayList<Relation>();
[2317]579 private DefaultListSelectionModel selectionModel;
[2126]580
[2317]581 public RelationListModel(DefaultListSelectionModel selectionModel) {
582 this.selectionModel = selectionModel;
583 }
584
[2194]585 public Relation getRelation(int idx) {
586 return relations.get(idx);
587 }
588
[2741]589 public void sort() {
[2623]590 Collections.sort(
591 relations,
[4070]592 DefaultNameFormatter.getInstance().getRelationComparator()
[2623]593 );
594 }
595
596 private boolean isValid(Relation r) {
597 return !r.isDeleted() && r.isVisible() && !r.isIncomplete();
598 }
599
[2741]600 public void setRelations(Collection<Relation> relations) {
[2488]601 List<Relation> sel = getSelectedRelations();
[2504]602 this.relations.clear();
[2506]603 if (relations == null) {
604 selectionModel.clearSelection();
605 fireContentsChanged(this,0,getSize());
606 return;
607
608 }
[2504]609 for (Relation r: relations) {
[2623]610 if (isValid(r)) {
[2504]611 this.relations.add(r);
[2487]612 }
613 }
614 sort();
[2126]615 fireIntervalAdded(this, 0, getSize());
[2488]616 setSelectedRelations(sel);
[2126]617 }
618
[2487]619 /**
620 * Add all relations in <code>addedPrimitives</code> to the model for the
621 * relation list dialog
[2512]622 *
[2487]623 * @param addedPrimitives the collection of added primitives. May include nodes,
624 * ways, and relations.
625 */
[2741]626 public void addRelations(Collection<? extends OsmPrimitive> addedPrimitives) {
[2484]627 boolean added = false;
628 for (OsmPrimitive p: addedPrimitives) {
629 if (! (p instanceof Relation)) {
630 continue;
631 }
[2623]632
633 Relation r = (Relation)p;
634 if (relations.contains(r)) {
[2484]635 continue;
636 }
[2623]637 if (isValid(r)) {
638 relations.add(r);
639 added = true;
640 }
[2484]641 }
642 if (added) {
[2487]643 List<Relation> sel = getSelectedRelations();
644 sort();
[2484]645 fireIntervalAdded(this, 0, getSize());
[2487]646 setSelectedRelations(sel);
[2484]647 }
648 }
649
[2487]650 /**
651 * Removes all relations in <code>removedPrimitives</code> from the model
[2512]652 *
[2487]653 * @param removedPrimitives the removed primitives. May include nodes, ways,
654 * and relations
655 */
[2741]656 public void removeRelations(Collection<? extends OsmPrimitive> removedPrimitives) {
[2487]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
[3102]679 /**
680 * Replies the list of selected relations with incomplete members
[3530]681 *
[3102]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
[2126]696 public Object getElementAt(int index) {
697 return relations.get(index);
698 }
699
700 public int getSize() {
701 return relations.size();
702 }
703
[2317]704 /**
705 * Replies the list of selected, non-new relations. Empty list,
706 * if there are no selected, non-new relations.
[2512]707 *
[2317]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.
[2512]727 *
[2317]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 }
[2487]740
741 /**
742 * Sets the selected relations.
[2512]743 *
[2487]744 * @return sel the list of selected relations
745 */
[2741]746 public void setSelectedRelations(List<Relation> sel) {
[2487]747 selectionModel.clearSelection();
[2506]748 if (sel == null || sel.isEmpty())
[2487]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 }
[2894]758
759 /**
760 * Returns the index of the relation
761 *
[2914]762 * @return index of relation (null if it cannot be found)
[2894]763 */
764 public Integer getRelationIndex(Relation rel) {
765 int i = relations.indexOf(rel);
[2914]766 if (i<0)
[2894]767 return null;
768 return i;
769 }
[2914]770
[3020]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 }
[2126]778 }
[2317]779
[4459]780 class RelationDialogPopupMenu extends ListPopupMenu {
781
782 public RelationDialogPopupMenu(JList list) {
783 super(list);
784
[2317]785 // -- download members action
786 //
[4459]787 add(new DownloadMembersAction());
[2317]788
[3102]789 // -- download incomplete members action
790 //
[4459]791 add(new DownloadSelectedIncompleteMembersAction());
[3102]792
793 addSeparator();
794
[2317]795 // -- select members action
796 //
[4459]797 add(new SelectMembersAction(false));
798 add(new SelectMembersAction(true));
[4158]799
800 // -- select action
801 //
[4459]802 add(new SelectAction(false));
803 add(new SelectAction(true));
[2317]804 }
[4459]805 }
[2317]806
[4459]807 public void addPopupMenuSeparator() {
808 popupMenu.addSeparator();
[2317]809 }
[2439]810
[4459]811 public JMenuItem addPopupMenuAction(Action a) {
812 return popupMenu.add(a);
813 }
814
[2487]815 /* ---------------------------------------------------------------------------------- */
816 /* DataSetListener */
817 /* ---------------------------------------------------------------------------------- */
818
[2622]819 public void nodeMoved(NodeMovedEvent event) {/* irrelevant in this context */}
[2487]820
[2622]821 public void wayNodesChanged(WayNodesChangedEvent event) {/* irrelevant in this context */}
[2487]822
[4223]823 public void primitivesAdded(final PrimitivesAddedEvent event) {
[2622]824 model.addRelations(event.getPrimitives());
[3020]825 model.updateTitle();
[2439]826 }
827
[4223]828 public void primitivesRemoved(final PrimitivesRemovedEvent event) {
[2622]829 model.removeRelations(event.getPrimitives());
[3020]830 model.updateTitle();
[2439]831 }
832
[2622]833 public void relationMembersChanged(final RelationMembersChangedEvent event) {
834 List<Relation> sel = model.getSelectedRelations();
835 model.sort();
836 model.setSelectedRelations(sel);
837 displaylist.repaint();
[2439]838 }
839
[2622]840 public void tagsChanged(TagsChangedEvent event) {
841 OsmPrimitive prim = event.getPrimitive();
[2487]842 if (prim == null || ! (prim instanceof Relation))
843 return;
[2622]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();
[2439]851 }
[2488]852
[2622]853 public void dataChanged(DataChangedEvent event) {
[2860]854 initFromLayer(Main.main.getEditLayer());
[2497]855 }
[2655]856
857 public void otherDatasetChange(AbstractDatasetChangedEvent event) {/* ignore */}
[626]858}
Note: See TracBrowser for help on using the repository browser.