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

Last change on this file since 12528 was 12528, checked in by Don-vip, 7 years ago

fix #10780 - display undeleted relations in relation list

  • Property svn:eol-style set to native
File size: 26.4 KB
RevLine 
[3719]1// License: GPL. For details, see LICENSE file.
[626]2package org.openstreetmap.josm.gui.dialogs;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
[5616]6import java.awt.BorderLayout;
[6038]7import java.awt.Component;
[626]8import java.awt.event.ActionEvent;
9import java.awt.event.KeyEvent;
10import java.awt.event.MouseEvent;
[2126]11import java.util.ArrayList;
[4353]12import java.util.Arrays;
[1886]13import java.util.Collection;
[2126]14import java.util.Collections;
[1886]15import java.util.HashSet;
[2317]16import java.util.List;
[2487]17import java.util.Set;
[626]18
[1778]19import javax.swing.AbstractAction;
[2126]20import javax.swing.AbstractListModel;
[2317]21import javax.swing.DefaultListSelectionModel;
[6038]22import javax.swing.FocusManager;
[5200]23import javax.swing.JComponent;
[626]24import javax.swing.JList;
[9365]25import javax.swing.JMenuItem;
[5616]26import javax.swing.JPanel;
[5793]27import javax.swing.JPopupMenu;
[5616]28import javax.swing.JScrollPane;
[5200]29import javax.swing.KeyStroke;
[626]30import javax.swing.ListSelectionModel;
[1778]31
[626]32import org.openstreetmap.josm.Main;
[9365]33import org.openstreetmap.josm.actions.ExpertToggleAction;
[5799]34import org.openstreetmap.josm.actions.relation.AddSelectionToRelations;
35import org.openstreetmap.josm.actions.relation.DeleteRelationsAction;
[5793]36import org.openstreetmap.josm.actions.relation.DownloadMembersAction;
37import org.openstreetmap.josm.actions.relation.DownloadSelectedIncompleteMembersAction;
[5799]38import org.openstreetmap.josm.actions.relation.DuplicateRelationAction;
[5793]39import org.openstreetmap.josm.actions.relation.EditRelationAction;
[9668]40import org.openstreetmap.josm.actions.relation.RecentRelationsAction;
[5793]41import org.openstreetmap.josm.actions.relation.SelectMembersAction;
42import org.openstreetmap.josm.actions.relation.SelectRelationAction;
[5616]43import org.openstreetmap.josm.actions.search.SearchCompiler;
[5082]44import org.openstreetmap.josm.data.osm.DataSet;
[755]45import org.openstreetmap.josm.data.osm.OsmPrimitive;
[626]46import org.openstreetmap.josm.data.osm.Relation;
[2655]47import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
[2622]48import org.openstreetmap.josm.data.osm.event.DataChangedEvent;
49import org.openstreetmap.josm.data.osm.event.DataSetListener;
50import org.openstreetmap.josm.data.osm.event.DatasetEventManager;
[4070]51import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode;
[2622]52import org.openstreetmap.josm.data.osm.event.NodeMovedEvent;
53import org.openstreetmap.josm.data.osm.event.PrimitivesAddedEvent;
54import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent;
55import org.openstreetmap.josm.data.osm.event.RelationMembersChangedEvent;
56import org.openstreetmap.josm.data.osm.event.TagsChangedEvent;
57import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent;
[2126]58import org.openstreetmap.josm.gui.DefaultNameFormatter;
[2621]59import org.openstreetmap.josm.gui.MapView;
[9264]60import org.openstreetmap.josm.gui.NavigatableComponent;
[626]61import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
[5821]62import org.openstreetmap.josm.gui.PopupMenuHandler;
[2710]63import org.openstreetmap.josm.gui.SideButton;
[1599]64import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
[626]65import org.openstreetmap.josm.gui.layer.Layer;
[10386]66import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent;
67import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener;
68import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent;
69import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent;
70import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
71import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
[626]72import org.openstreetmap.josm.gui.layer.OsmDataLayer;
[7547]73import org.openstreetmap.josm.gui.util.GuiHelper;
[6025]74import org.openstreetmap.josm.gui.util.HighlightHelper;
[8979]75import org.openstreetmap.josm.gui.widgets.CompileSearchTextDecorator;
[5696]76import org.openstreetmap.josm.gui.widgets.DisableShortcutsOnFocusGainedTextField;
[5958]77import org.openstreetmap.josm.gui.widgets.JosmTextField;
78import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
[1778]79import org.openstreetmap.josm.tools.ImageProvider;
[5200]80import org.openstreetmap.josm.tools.InputMapUtils;
[1084]81import org.openstreetmap.josm.tools.Shortcut;
[10657]82import org.openstreetmap.josm.tools.SubclassFilteredCollection;
[626]83
84/**
[10386]85 * A dialog showing all known relations, with buttons to add, edit, and delete them.
[1023]86 *
[1554]87 * We don't have such dialogs for nodes, segments, and ways, because those
[626]88 * objects are visible on the map and can be selected there. Relations are not.
89 */
[9365]90public class RelationListDialog extends ToggleDialog
91 implements DataSetListener, NavigatableComponent.ZoomChangeListener, ExpertToggleAction.ExpertModeChangeListener {
[2126]92 /** The display list. */
[7001]93 private final JList<Relation> displaylist;
[2126]94 /** the list model used */
[5725]95 private final RelationListModel model;
[626]96
[5725]97 private final NewAction newAction;
[6070]98
[5821]99 /** the popup menu and its handler */
100 private final JPopupMenu popupMenu = new JPopupMenu();
[8308]101 private final transient PopupMenuHandler popupMenuHandler = new PopupMenuHandler(popupMenu);
[1677]102
[5886]103 private final JosmTextField filter;
[6070]104
[5793]105 // Actions
106 /** the edit action */
[5799]107 private final EditRelationAction editAction = new EditRelationAction();
108 /** the delete action */
109 private final DeleteRelationsAction deleteRelationsAction = new DeleteRelationsAction();
110 /** the duplicate action */
111 private final DuplicateRelationAction duplicateAction = new DuplicateRelationAction();
[5793]112 private final DownloadMembersAction downloadMembersAction = new DownloadMembersAction();
[8540]113 private final DownloadSelectedIncompleteMembersAction downloadSelectedIncompleteMembersAction =
114 new DownloadSelectedIncompleteMembersAction();
[5821]115 private final SelectMembersAction selectMembersAction = new SelectMembersAction(false);
[5793]116 private final SelectMembersAction addMembersToSelectionAction = new SelectMembersAction(true);
117 private final SelectRelationAction selectRelationAction = new SelectRelationAction(false);
118 private final SelectRelationAction addRelationToSelectionAction = new SelectRelationAction(true);
[5821]119 /** add all selected primitives to the given relations */
[5799]120 private final AddSelectionToRelations addSelectionToRelations = new AddSelectionToRelations();
[9365]121 private transient JMenuItem addSelectionToRelationMenuItem;
[6070]122
[8308]123 private final transient HighlightHelper highlightHelper = new HighlightHelper();
[9078]124 private final boolean highlightEnabled = Main.pref.getBoolean("draw.target-highlight", true);
[10306]125 private final transient RecentRelationsAction recentRelationsAction;
[7539]126
[1778]127 /**
[5799]128 * Constructs <code>RelationListDialog</code>
[1778]129 */
[1169]130 public RelationListDialog() {
131 super(tr("Relations"), "relationlist", tr("Open a list of all relations."),
[4957]132 Shortcut.registerShortcut("subwindow:relations", tr("Toggle: {0}", tr("Relations")),
[6726]133 KeyEvent.VK_R, Shortcut.ALT_SHIFT), 150, true);
[1778]134
135 // create the list of relations
136 //
[2317]137 DefaultListSelectionModel selectionModel = new DefaultListSelectionModel();
138 model = new RelationListModel(selectionModel);
[7005]139 displaylist = new JList<>(model);
[2317]140 displaylist.setSelectionModel(selectionModel);
[11357]141 displaylist.setCellRenderer(new NoTooltipOsmRenderer());
[2194]142 displaylist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
[2317]143 displaylist.addMouseListener(new MouseEventHandler());
[626]144
[1866]145 // the new action
146 //
[2485]147 newAction = new NewAction();
[1866]148
[5793]149 filter = setupFilter();
[5616]150
[11365]151 displaylist.addListSelectionListener(e -> {
152 if (!e.getValueIsAdjusting()) updateActionsRelationLists();
153 });
[5821]154
155 // Setup popup menu handler
156 setupPopupMenuHandler();
[6070]157
[5616]158 JPanel pane = new JPanel(new BorderLayout());
159 pane.add(filter, BorderLayout.NORTH);
160 pane.add(new JScrollPane(displaylist), BorderLayout.CENTER);
[9668]161
162 SideButton editButton = new SideButton(editAction, false);
163 recentRelationsAction = new RecentRelationsAction(editButton);
164
[12279]165 createLayout(pane, false, Arrays.asList(
[5028]166 new SideButton(newAction, false),
[9668]167 editButton,
[5028]168 new SideButton(duplicateAction, false),
[5799]169 new SideButton(deleteRelationsAction, false),
[5793]170 new SideButton(selectRelationAction, false)
[12279]171 ));
[2487]172
[5200]173 InputMapUtils.unassignCtrlShiftUpDown(displaylist, JComponent.WHEN_FOCUSED);
[6070]174
[7547]175 // Select relation on Enter
[5793]176 InputMapUtils.addEnterAction(displaylist, selectRelationAction);
[5200]177
178 // Edit relation on Ctrl-Enter
179 displaylist.getActionMap().put("edit", editAction);
[12523]180 displaylist.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.CTRL_DOWN_MASK), "edit");
[6070]181
[7547]182 // Do not hide copy action because of default JList override (fix #9815)
183 displaylist.getActionMap().put("copy", Main.main.menu.copy);
184 displaylist.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_C, GuiHelper.getMenuShortcutKeyMaskEx()), "copy");
185
[5799]186 updateActionsRelationLists();
[2485]187 }
[6070]188
[10861]189 @Override
190 public void destroy() {
[11610]191 recentRelationsAction.destroy();
[10861]192 model.clear();
193 super.destroy();
194 }
195
[11610]196 /**
197 * Enable the "recent relations" dropdown menu next to edit button.
198 */
[9668]199 public void enableRecentRelations() {
200 recentRelationsAction.enableArrow();
201 }
202
[5799]203 // inform all actions about list of relations they need
204 private void updateActionsRelationLists() {
[6025]205 List<Relation> sel = model.getSelectedRelations();
206 popupMenuHandler.setPrimitives(sel);
[6070]207
[6038]208 Component focused = FocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
[6070]209
[6025]210 //update highlights
[11386]211 if (highlightEnabled && focused == displaylist && Main.isDisplayingMapView() && highlightHelper.highlightOnly(sel)) {
212 Main.map.mapView.repaint();
[6025]213 }
[5799]214 }
[6070]215
[7539]216 @Override
217 public void showNotify() {
[10386]218 Main.getLayerManager().addLayerChangeListener(newAction);
219 Main.getLayerManager().addActiveLayerChangeListener(newAction);
[9264]220 MapView.addZoomChangeListener(this);
[2691]221 newAction.updateEnabledState();
[2741]222 DatasetEventManager.getInstance().addDatasetListener(this, FireMode.IN_EDT);
[5799]223 DataSet.addSelectionListener(addSelectionToRelations);
[2623]224 dataChanged(null);
[9365]225 ExpertToggleAction.addExpertModeChangeListener(this);
226 expertChanged(ExpertToggleAction.isExpert());
[1169]227 }
[626]228
[7539]229 @Override
230 public void hideNotify() {
[10386]231 Main.getLayerManager().removeActiveLayerChangeListener(newAction);
232 Main.getLayerManager().removeLayerChangeListener(newAction);
[9264]233 MapView.removeZoomChangeListener(this);
[2622]234 DatasetEventManager.getInstance().removeDatasetListener(this);
[5799]235 DataSet.removeSelectionListener(addSelectionToRelations);
[9365]236 ExpertToggleAction.removeExpertModeChangeListener(this);
[1169]237 }
[6070]238
[5725]239 private void resetFilter() {
240 filter.setText(null);
241 }
[1023]242
[2126]243 /**
[2487]244 * Initializes the relation list dialog from a layer. If <code>layer</code> is null
[5266]245 * or if it isn't an {@link OsmDataLayer} the dialog is reset to an empty dialog.
[2487]246 * Otherwise it is initialized with the list of non-deleted and visible relations
247 * in the layer's dataset.
[2512]248 *
[2487]249 * @param layer the layer. May be null.
[2126]250 */
[2487]251 protected void initFromLayer(Layer layer) {
[6105]252 if (!(layer instanceof OsmDataLayer)) {
[2126]253 model.setRelations(null);
[1897]254 return;
255 }
[8510]256 OsmDataLayer l = (OsmDataLayer) layer;
[2487]257 model.setRelations(l.data.getRelations());
[3020]258 model.updateTitle();
[5799]259 updateActionsRelationLists();
[1169]260 }
[1023]261
[1169]262 /**
[1419]263 * @return The selected relation in the list
264 */
265 private Relation getSelected() {
[7001]266 if (model.getSize() == 1) {
[1419]267 displaylist.setSelectedIndex(0);
[1763]268 }
[7001]269 return displaylist.getSelectedValue();
[1419]270 }
[1763]271
272 /**
273 * Selects the relation <code>relation</code> in the list of relations.
[1897]274 *
[1763]275 * @param relation the relation
276 */
277 public void selectRelation(Relation relation) {
[4795]278 selectRelations(Collections.singleton(relation));
279 }
280
281 /**
282 * Selects the relations in the list of relations.
283 * @param relations the relations to be selected
284 */
285 public void selectRelations(Collection<Relation> relations) {
286 if (relations == null || relations.isEmpty()) {
[2487]287 model.setSelectedRelations(null);
[2126]288 } else {
[4795]289 model.setSelectedRelations(relations);
[5725]290 Integer i = model.getVisibleRelationIndex(relations.iterator().next());
[8509]291 if (i != null) {
292 // Not all relations have to be in the list
293 // (for example when the relation list is hidden, it's not updated with new relations)
[2914]294 displaylist.scrollRectToVisible(displaylist.getCellBounds(i, i));
295 }
[1780]296 }
[1763]297 }
[1778]298
[10378]299 private JosmTextField setupFilter() {
[5886]300 final JosmTextField f = new DisableShortcutsOnFocusGainedTextField();
[5793]301 f.setToolTipText(tr("Relation list filter"));
[8979]302 final CompileSearchTextDecorator decorator = CompileSearchTextDecorator.decorate(f);
[10611]303 f.addPropertyChangeListener("filter", evt -> model.setFilter(decorator.getMatch()));
[5793]304 return f;
305 }
306
[11357]307 static final class NoTooltipOsmRenderer extends OsmPrimitivRenderer {
308 @Override
309 protected String getComponentToolTipText(OsmPrimitive value) {
310 // Don't show the default tooltip in the relation list
311 return null;
312 }
313 }
314
[5958]315 class MouseEventHandler extends PopupMenuLauncher {
[6070]316
[8836]317 MouseEventHandler() {
[5958]318 super(popupMenu);
319 }
[6025]320
321 @Override
322 public void mouseExited(MouseEvent me) {
[6058]323 if (highlightEnabled) highlightHelper.clear();
[6025]324 }
[6070]325
[1916]326 protected void setCurrentRelationAsSelection() {
[10446]327 Main.getLayerManager().getEditDataSet().setSelected(displaylist.getSelectedValue());
[1916]328 }
329
330 protected void editCurrentRelation() {
[5793]331 EditRelationAction.launchEditor(getSelected());
[1916]332 }
[6070]333
[7539]334 @Override
335 public void mouseClicked(MouseEvent e) {
[10453]336 if (Main.getLayerManager().getEditLayer() == null) return;
[5958]337 if (isDoubleClick(e)) {
[1916]338 if (e.isControlDown()) {
339 editCurrentRelation();
340 } else {
341 setCurrentRelationAsSelection();
342 }
343 }
344 }
345 }
[6070]346
[1778]347 /**
[10386]348 * The action for creating a new relation.
[1866]349 */
[10386]350 static class NewAction extends AbstractAction implements LayerChangeListener, ActiveLayerChangeListener {
[8836]351 NewAction() {
[8510]352 putValue(SHORT_DESCRIPTION, tr("Create a new relation"));
[5028]353 putValue(NAME, tr("New"));
[10428]354 new ImageProvider("dialogs", "addrelation").getResource().attachImageIcon(this, true);
[2632]355 updateEnabledState();
[1866]356 }
357
358 public void run() {
[10413]359 RelationEditor.getEditor(Main.getLayerManager().getEditLayer(), null, null).setVisible(true);
[1866]360 }
361
[5799]362 @Override
[1866]363 public void actionPerformed(ActionEvent e) {
364 run();
365 }
366
367 protected void updateEnabledState() {
[10453]368 setEnabled(Main.getLayerManager().getEditLayer() != null);
[1866]369 }
370
[5799]371 @Override
[10386]372 public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
[1866]373 updateEnabledState();
[7001]374 }
[1866]375
[5799]376 @Override
[10386]377 public void layerAdded(LayerAddEvent e) {
[1866]378 updateEnabledState();
379 }
380
[5799]381 @Override
[10386]382 public void layerRemoving(LayerRemoveEvent e) {
[1866]383 updateEnabledState();
384 }
[10386]385
386 @Override
387 public void layerOrderChanged(LayerOrderChangeEvent e) {
388 // Do nothing
389 }
[1866]390 }
[1916]391
392 /**
[7001]393 * The list model for the list of relations displayed in the relation list dialog.
[2487]394 */
[7001]395 private class RelationListModel extends AbstractListModel<Relation> {
[8308]396 private final transient List<Relation> relations = new ArrayList<>();
397 private transient List<Relation> filteredRelations;
[9078]398 private final DefaultListSelectionModel selectionModel;
[8308]399 private transient SearchCompiler.Match filter;
[2126]400
[8836]401 RelationListModel(DefaultListSelectionModel selectionModel) {
[2317]402 this.selectionModel = selectionModel;
403 }
404
[10910]405 /**
406 * Clears the model.
407 */
[10861]408 public void clear() {
409 relations.clear();
410 if (filteredRelations != null)
411 filteredRelations.clear();
412 filter = null;
413 }
414
[10910]415 /**
416 * Sorts the model using {@link DefaultNameFormatter} relation comparator.
417 */
[2741]418 public void sort() {
[10619]419 relations.sort(DefaultNameFormatter.getInstance().getRelationComparator());
[2623]420 }
421
422 private boolean isValid(Relation r) {
[12528]423 return !r.isDeleted() && !r.isIncomplete();
[2623]424 }
425
[2741]426 public void setRelations(Collection<Relation> relations) {
[10378]427 List<Relation> sel = getSelectedRelations();
[2504]428 this.relations.clear();
[5619]429 this.filteredRelations = null;
[2506]430 if (relations == null) {
431 selectionModel.clearSelection();
[8510]432 fireContentsChanged(this, 0, getSize());
[2506]433 return;
434 }
[2504]435 for (Relation r: relations) {
[2623]436 if (isValid(r)) {
[2504]437 this.relations.add(r);
[2487]438 }
439 }
440 sort();
[5744]441 updateFilteredRelations();
[2126]442 fireIntervalAdded(this, 0, getSize());
[2488]443 setSelectedRelations(sel);
[2126]444 }
445
[2487]446 /**
447 * Add all relations in <code>addedPrimitives</code> to the model for the
448 * relation list dialog
[2512]449 *
[2487]450 * @param addedPrimitives the collection of added primitives. May include nodes,
451 * ways, and relations.
452 */
[2741]453 public void addRelations(Collection<? extends OsmPrimitive> addedPrimitives) {
[2484]454 boolean added = false;
455 for (OsmPrimitive p: addedPrimitives) {
[8444]456 if (!(p instanceof Relation)) {
[2484]457 continue;
458 }
[2623]459
[8510]460 Relation r = (Relation) p;
[2623]461 if (relations.contains(r)) {
[2484]462 continue;
463 }
[2623]464 if (isValid(r)) {
465 relations.add(r);
466 added = true;
467 }
[2484]468 }
469 if (added) {
[2487]470 List<Relation> sel = getSelectedRelations();
471 sort();
[5744]472 updateFilteredRelations();
[2484]473 fireIntervalAdded(this, 0, getSize());
[2487]474 setSelectedRelations(sel);
[2484]475 }
476 }
477
[2487]478 /**
479 * Removes all relations in <code>removedPrimitives</code> from the model
[2512]480 *
[2487]481 * @param removedPrimitives the removed primitives. May include nodes, ways,
482 * and relations
483 */
[2741]484 public void removeRelations(Collection<? extends OsmPrimitive> removedPrimitives) {
[2487]485 if (removedPrimitives == null) return;
486 // extract the removed relations
487 //
[7005]488 Set<Relation> removedRelations = new HashSet<>();
[2487]489 for (OsmPrimitive p: removedPrimitives) {
[8444]490 if (!(p instanceof Relation)) {
[2487]491 continue;
492 }
[8510]493 removedRelations.add((Relation) p);
[2487]494 }
495 if (removedRelations.isEmpty())
496 return;
497 int size = relations.size();
498 relations.removeAll(removedRelations);
[5709]499 if (filteredRelations != null) {
500 filteredRelations.removeAll(removedRelations);
501 }
[2487]502 if (size != relations.size()) {
503 List<Relation> sel = getSelectedRelations();
504 sort();
505 fireContentsChanged(this, 0, getSize());
506 setSelectedRelations(sel);
507 }
508 }
[6070]509
[5720]510 private void updateFilteredRelations() {
511 if (filter != null) {
[10657]512 filteredRelations = new ArrayList<>(SubclassFilteredCollection.filter(relations, filter::match));
[5720]513 } else if (filteredRelations != null) {
514 filteredRelations = null;
515 }
516 }
[3102]517
[5616]518 public void setFilter(final SearchCompiler.Match filter) {
[5720]519 this.filter = filter;
520 updateFilteredRelations();
[5616]521 List<Relation> sel = getSelectedRelations();
522 fireContentsChanged(this, 0, getSize());
523 setSelectedRelations(sel);
524 updateTitle();
525 }
526
527 private List<Relation> getVisibleRelations() {
528 return filteredRelations == null ? relations : filteredRelations;
529 }
[6070]530
[5709]531 private Relation getVisibleRelation(int index) {
532 if (index < 0 || index >= getVisibleRelations().size()) return null;
533 return getVisibleRelations().get(index);
534 }
[5616]535
536 @Override
[7001]537 public Relation getElementAt(int index) {
[5709]538 return getVisibleRelation(index);
[2126]539 }
540
[5616]541 @Override
[2126]542 public int getSize() {
[5616]543 return getVisibleRelations().size();
[2126]544 }
545
[2317]546 /**
547 * Replies the list of selected relations. Empty list,
548 * if there are no selected relations.
[2512]549 *
[2317]550 * @return the list of selected, non-new relations.
551 */
552 public List<Relation> getSelectedRelations() {
[7005]553 List<Relation> ret = new ArrayList<>();
[8510]554 for (int i = 0; i < getSize(); i++) {
[2317]555 if (!selectionModel.isSelectedIndex(i)) {
556 continue;
557 }
[5720]558 ret.add(getVisibleRelation(i));
[2317]559 }
560 return ret;
561 }
[2487]562
563 /**
564 * Sets the selected relations.
[2512]565 *
[5709]566 * @param sel the list of selected relations
[2487]567 */
[4795]568 public void setSelectedRelations(Collection<Relation> sel) {
[11365]569 selectionModel.setValueIsAdjusting(true);
[2487]570 selectionModel.clearSelection();
[11365]571 if (sel != null && !sel.isEmpty()) {
572 if (!getVisibleRelations().containsAll(sel)) {
573 resetFilter();
[2487]574 }
[11365]575 for (Relation r: sel) {
576 Integer i = getVisibleRelationIndex(r);
577 if (i != null) {
578 selectionModel.addSelectionInterval(i, i);
579 }
580 }
[2487]581 }
[11365]582 selectionModel.setValueIsAdjusting(false);
[2487]583 }
[2894]584
[5725]585 private Integer getVisibleRelationIndex(Relation rel) {
586 int i = getVisibleRelations().indexOf(rel);
[8510]587 if (i < 0)
[5725]588 return null;
589 return i;
590 }
[2914]591
[3020]592 public void updateTitle() {
[8318]593 if (!relations.isEmpty() && relations.size() != getSize()) {
[5616]594 RelationListDialog.this.setTitle(tr("Relations: {0}/{1}", getSize(), relations.size()));
595 } else if (getSize() > 0) {
[3020]596 RelationListDialog.this.setTitle(tr("Relations: {0}", getSize()));
597 } else {
598 RelationListDialog.this.setTitle(tr("Relations"));
599 }
600 }
[2126]601 }
[2317]602
[8512]603 private void setupPopupMenuHandler() {
[6070]604
[5825]605 // -- select action
606 popupMenuHandler.addAction(selectRelationAction);
607 popupMenuHandler.addAction(addRelationToSelectionAction);
608
609 // -- select members action
610 popupMenuHandler.addAction(selectMembersAction);
611 popupMenuHandler.addAction(addMembersToSelectionAction);
612
613 popupMenuHandler.addSeparator();
[5821]614 // -- download members action
615 popupMenuHandler.addAction(downloadMembersAction);
[4459]616
[5821]617 // -- download incomplete members action
618 popupMenuHandler.addAction(downloadSelectedIncompleteMembersAction);
[2317]619
[5821]620 popupMenuHandler.addSeparator();
[5825]621 popupMenuHandler.addAction(editAction).setVisible(false);
622 popupMenuHandler.addAction(duplicateAction).setVisible(false);
623 popupMenuHandler.addAction(deleteRelationsAction).setVisible(false);
[6070]624
[9365]625 addSelectionToRelationMenuItem = popupMenuHandler.addAction(addSelectionToRelations);
[4459]626 }
[6070]627
[5799]628 /* ---------------------------------------------------------------------------------- */
[5821]629 /* Methods that can be called from plugins */
[5799]630 /* ---------------------------------------------------------------------------------- */
631
[5821]632 /**
633 * Replies the popup menu handler.
634 * @return The popup menu handler
635 */
636 public PopupMenuHandler getPopupMenuHandler() {
637 return popupMenuHandler;
[2317]638 }
[2439]639
[7029]640 /**
641 * Replies the list of selected relations. Empty list, if there are no selected relations.
642 * @return the list of selected, non-new relations.
643 */
[4536]644 public Collection<Relation> getSelectedRelations() {
645 return model.getSelectedRelations();
646 }
647
[2487]648 /* ---------------------------------------------------------------------------------- */
649 /* DataSetListener */
650 /* ---------------------------------------------------------------------------------- */
651
[5799]652 @Override
[8413]653 public void nodeMoved(NodeMovedEvent event) {
654 /* irrelevant in this context */
655 }
[2487]656
[5799]657 @Override
[8413]658 public void wayNodesChanged(WayNodesChangedEvent event) {
659 /* irrelevant in this context */
660 }
[2487]661
[5799]662 @Override
[4223]663 public void primitivesAdded(final PrimitivesAddedEvent event) {
[2622]664 model.addRelations(event.getPrimitives());
[3020]665 model.updateTitle();
[2439]666 }
667
[5799]668 @Override
[4223]669 public void primitivesRemoved(final PrimitivesRemovedEvent event) {
[2622]670 model.removeRelations(event.getPrimitives());
[3020]671 model.updateTitle();
[2439]672 }
673
[5799]674 @Override
[2622]675 public void relationMembersChanged(final RelationMembersChangedEvent event) {
676 List<Relation> sel = model.getSelectedRelations();
677 model.sort();
678 model.setSelectedRelations(sel);
679 displaylist.repaint();
[2439]680 }
681
[5799]682 @Override
[2622]683 public void tagsChanged(TagsChangedEvent event) {
684 OsmPrimitive prim = event.getPrimitive();
[6105]685 if (!(prim instanceof Relation))
[2487]686 return;
[7001]687 // trigger a sort of the relation list because the display name may have changed
[2622]688 //
689 List<Relation> sel = model.getSelectedRelations();
690 model.sort();
691 model.setSelectedRelations(sel);
692 displaylist.repaint();
[2439]693 }
[2488]694
[5799]695 @Override
[2622]696 public void dataChanged(DataChangedEvent event) {
[10413]697 initFromLayer(Main.getLayerManager().getEditLayer());
[2497]698 }
[2655]699
[5799]700 @Override
[7001]701 public void otherDatasetChange(AbstractDatasetChangedEvent event) {
702 /* ignore */
703 }
[9264]704
705 @Override
706 public void zoomChanged() {
707 // re-filter relations
708 if (model.filter != null) {
709 model.setFilter(model.filter);
710 }
711 }
[9365]712
713 @Override
714 public void expertChanged(boolean isExpert) {
715 addSelectionToRelationMenuItem.setVisible(isExpert);
716 }
[626]717}
Note: See TracBrowser for help on using the repository browser.