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

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

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

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