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

Last change on this file since 4221 was 4221, checked in by jttt, 13 years ago

Select new relation in relation list, save "apply only to selection" option in preset search dialog, make selected objects members of newly created relation

  • 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
[2622]833 public void primtivesAdded(final PrimitivesAddedEvent event) {
834 model.addRelations(event.getPrimitives());
[3020]835 model.updateTitle();
[2439]836 }
837
[2622]838 public void primtivesRemoved(final PrimitivesRemovedEvent event) {
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.