source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java@ 3105

Last change on this file since 3105 was 3105, checked in by Gubaer, 14 years ago

Removing @Overrides - got inserted too early and make troubles while still building for Java 1.5

  • Property svn:eol-style set to native
File size: 28.0 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.gui.dialogs;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trn;
6
7import java.awt.BorderLayout;
8import java.awt.Color;
9import java.awt.Component;
10import java.awt.GridLayout;
11import java.awt.Rectangle;
12import java.awt.event.ActionEvent;
13import java.awt.event.ActionListener;
14import java.awt.event.KeyEvent;
15import java.awt.event.MouseEvent;
16import java.util.ArrayList;
17import java.util.Collection;
18import java.util.Collections;
19import java.util.Comparator;
20import java.util.HashSet;
21import java.util.LinkedList;
22import java.util.List;
23import java.util.Set;
24
25import javax.swing.AbstractAction;
26import javax.swing.AbstractListModel;
27import javax.swing.BorderFactory;
28import javax.swing.DefaultListSelectionModel;
29import javax.swing.JButton;
30import javax.swing.JList;
31import javax.swing.JMenuItem;
32import javax.swing.JPanel;
33import javax.swing.JPopupMenu;
34import javax.swing.JScrollPane;
35import javax.swing.ListSelectionModel;
36import javax.swing.SwingConstants;
37import javax.swing.event.ListDataEvent;
38import javax.swing.event.ListDataListener;
39import javax.swing.event.ListSelectionEvent;
40import javax.swing.event.ListSelectionListener;
41import javax.swing.plaf.basic.BasicArrowButton;
42
43import org.openstreetmap.josm.Main;
44import org.openstreetmap.josm.actions.AutoScaleAction;
45import org.openstreetmap.josm.actions.search.SearchAction.SearchSetting;
46import org.openstreetmap.josm.data.SelectionChangedListener;
47import org.openstreetmap.josm.data.osm.NameFormatter;
48import org.openstreetmap.josm.data.osm.Node;
49import org.openstreetmap.josm.data.osm.OsmPrimitive;
50import org.openstreetmap.josm.data.osm.Relation;
51import org.openstreetmap.josm.data.osm.Way;
52import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
53import org.openstreetmap.josm.data.osm.event.DataChangedEvent;
54import org.openstreetmap.josm.data.osm.event.DataSetListener;
55import org.openstreetmap.josm.data.osm.event.DatasetEventManager;
56import org.openstreetmap.josm.data.osm.event.NodeMovedEvent;
57import org.openstreetmap.josm.data.osm.event.PrimitivesAddedEvent;
58import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent;
59import org.openstreetmap.josm.data.osm.event.RelationMembersChangedEvent;
60import org.openstreetmap.josm.data.osm.event.SelectionEventManager;
61import org.openstreetmap.josm.data.osm.event.TagsChangedEvent;
62import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent;
63import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode;
64import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
65import org.openstreetmap.josm.gui.DefaultNameFormatter;
66import org.openstreetmap.josm.gui.MapView;
67import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
68import org.openstreetmap.josm.gui.SideButton;
69import org.openstreetmap.josm.gui.MapView.EditLayerChangeListener;
70import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationMemberTask;
71import org.openstreetmap.josm.gui.layer.OsmDataLayer;
72import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
73import org.openstreetmap.josm.tools.ImageProvider;
74import org.openstreetmap.josm.tools.Shortcut;
75
76/**
77 * A small tool dialog for displaying the current selection.
78 *
79 */
80public class SelectionListDialog extends ToggleDialog {
81
82 private JList lstPrimitives;
83 private SelectionListModel model;
84
85 private SelectAction actSelect;
86 private SearchAction actSearch;
87 private ZoomToJOSMSelectionAction actZoomToJOSMSelection;
88 private ZoomToListSelection actZoomToListSelection;
89 private DownloadSelectedIncompleteMembersAction actDownloadSelectedIncompleteMembers;
90
91 /**
92 * Builds the panel with the list of selected OSM primitives
93 *
94 * @return the panel with the list of selected OSM primitives
95 */
96 protected JPanel buildListPanel() {
97 JPanel pnl = new JPanel(new BorderLayout());
98 DefaultListSelectionModel selectionModel = new DefaultListSelectionModel();
99 model = new SelectionListModel(selectionModel);
100 lstPrimitives = new JList(model);
101 lstPrimitives.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
102 lstPrimitives.setSelectionModel(selectionModel);
103 lstPrimitives.setCellRenderer(new OsmPrimitivRenderer());
104 pnl.add(new JScrollPane(lstPrimitives), BorderLayout.CENTER);
105
106 return pnl;
107 }
108
109 /**
110 * Builds the row of action buttons at the bottom of this dialog
111 *
112 * @return the panel
113 */
114 protected JPanel buildActionPanel() {
115 JPanel pnl = new JPanel(new GridLayout(1,2));
116
117 // the select action
118 final JButton selectButton = new SideButton(actSelect = new SelectAction());
119 lstPrimitives.getSelectionModel().addListSelectionListener(actSelect);
120 pnl.add(selectButton);
121 BasicArrowButton selectionHistoryMenuButton = createArrowButton(selectButton);
122 selectionHistoryMenuButton.addActionListener(new ActionListener() {
123 public void actionPerformed(ActionEvent e) {
124 SelectionHistoryPopup.launch(selectButton, model.getSelectionHistory());
125 }
126 });
127
128 // the search button
129 final JButton searchButton = new SideButton(actSearch = new SearchAction());
130 pnl.add(searchButton);
131
132 BasicArrowButton searchHistoryMenuButton = createArrowButton(searchButton);
133 searchHistoryMenuButton.addActionListener(new ActionListener() {
134 public void actionPerformed(ActionEvent e) {
135 SearchPopupMenu.launch(searchButton);
136 }
137 });
138
139 return pnl;
140 }
141
142 /**
143 * Builds the content panel for this dialog
144 *
145 * @return the content panel
146 */
147 protected JPanel buildContentPanel() {
148 JPanel pnl = new JPanel(new BorderLayout());
149 pnl.add(buildListPanel(), BorderLayout.CENTER);
150 pnl.add(buildActionPanel(), BorderLayout.SOUTH);
151 return pnl;
152 }
153
154 public SelectionListDialog() {
155 super(tr("Current Selection"), "selectionlist", tr("Open a selection list window."),
156 Shortcut.registerShortcut("subwindow:selection", tr("Toggle: {0}", tr("Current Selection")), KeyEvent.VK_T, Shortcut.GROUP_LAYER, Shortcut.SHIFT_DEFAULT),
157 150, // default height
158 true // default is "show dialog"
159 );
160
161 add(buildContentPanel(), BorderLayout.CENTER);
162 model.addListDataListener(new TitleUpdater());
163 actZoomToJOSMSelection = new ZoomToJOSMSelectionAction();
164 model.addListDataListener(actZoomToJOSMSelection);
165
166 actZoomToListSelection = new ZoomToListSelection();
167 lstPrimitives.getSelectionModel().addListSelectionListener(actZoomToListSelection);
168
169 actDownloadSelectedIncompleteMembers = new DownloadSelectedIncompleteMembersAction();
170 lstPrimitives.getSelectionModel().addListSelectionListener(actDownloadSelectedIncompleteMembers);
171
172 lstPrimitives.addMouseListener(new SelectionPopupMenuLauncher());
173 }
174
175 @Override
176 public void showNotify() {
177 MapView.addEditLayerChangeListener(model);
178 SelectionEventManager.getInstance().addSelectionListener(model, FireMode.IN_EDT_CONSOLIDATED);
179 DatasetEventManager.getInstance().addDatasetListener(model, FireMode.IN_EDT);
180 MapView.addEditLayerChangeListener(actSearch);
181 if (Main.map.mapView.getEditLayer() != null) {
182 model.setJOSMSelection(Main.map.mapView.getEditLayer().data.getSelected());
183 }
184 }
185
186 @Override
187 public void hideNotify() {
188 MapView.removeEditLayerChangeListener(actSearch);
189 MapView.removeEditLayerChangeListener(model);
190 SelectionEventManager.getInstance().removeSelectionListener(model);
191 DatasetEventManager.getInstance().removeDatasetListener(model);
192 }
193
194 private BasicArrowButton createArrowButton(JButton parentButton) {
195 BasicArrowButton arrowButton = new BasicArrowButton(SwingConstants.SOUTH, null, null, Color.BLACK, null);
196 arrowButton.setBorder(BorderFactory.createEmptyBorder());
197 parentButton.setLayout(new BorderLayout());
198 parentButton.add(arrowButton, BorderLayout.EAST);
199 return arrowButton;
200 }
201
202 /**
203 * The popup menu launcher
204 */
205 class SelectionPopupMenuLauncher extends PopupMenuLauncher {
206 private SelectionPopup popup = new SelectionPopup();
207
208 @Override
209 public void launch(MouseEvent evt) {
210 if (model.getSelected().isEmpty()) {
211 int idx = lstPrimitives.locationToIndex(evt.getPoint());
212 if (idx < 0) return;
213 model.setSelected(Collections.singleton((OsmPrimitive)model.getElementAt(idx)));
214 }
215 popup.show(lstPrimitives, evt.getX(), evt.getY());
216 }
217 }
218
219 /**
220 * The popup menu for the selection list
221 */
222 class SelectionPopup extends JPopupMenu {
223 public SelectionPopup() {
224 add(actZoomToJOSMSelection);
225 add(actZoomToListSelection);
226 addSeparator();
227 add(actDownloadSelectedIncompleteMembers);
228 }
229 }
230
231 /**
232 * Updates the dialog title with a summary of the current JOSM selection
233 */
234 class TitleUpdater implements ListDataListener {
235 protected void updateTitle() {
236 setTitle(model.getJOSMSelectionSummary());
237 }
238
239 public void contentsChanged(ListDataEvent e) {
240 updateTitle();
241 }
242
243 public void intervalAdded(ListDataEvent e) {
244 updateTitle();
245 }
246
247 public void intervalRemoved(ListDataEvent e) {
248 updateTitle();
249 }
250 }
251
252 /**
253 * Launches the search dialog
254 */
255 class SearchAction extends AbstractAction implements EditLayerChangeListener {
256 public SearchAction() {
257 putValue(NAME, tr("Search"));
258 putValue(SHORT_DESCRIPTION, tr("Search for objects"));
259 putValue(SMALL_ICON, ImageProvider.get("dialogs","select"));
260 updateEnabledState();
261 }
262
263 public void actionPerformed(ActionEvent e) {
264 if (!isEnabled()) return;
265 org.openstreetmap.josm.actions.search.SearchAction.search();
266 }
267
268 public void updateEnabledState() {
269 setEnabled(Main.main != null && Main.main.getEditLayer() != null);
270 }
271
272 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
273 updateEnabledState();
274 }
275 }
276
277 /**
278 * Sets the current JOSM selection to the OSM primitives selected in the list
279 * of this dialog
280 */
281 class SelectAction extends AbstractAction implements ListSelectionListener {
282 public SelectAction() {
283 putValue(NAME, tr("Select"));
284 putValue(SHORT_DESCRIPTION, tr("Set the selected elements on the map to the selected items in the list above."));
285 putValue(SMALL_ICON, ImageProvider.get("dialogs","select"));
286 updateEnabledState();
287 }
288
289 public void actionPerformed(ActionEvent e) {
290 Collection<OsmPrimitive> sel = model.getSelected();
291 if (sel.isEmpty())return;
292 if (Main.map == null || Main.map.mapView == null || Main.map.mapView.getEditLayer() == null) return;
293 Main.map.mapView.getEditLayer().data.setSelected(sel);
294 }
295
296 public void updateEnabledState() {
297 setEnabled(!model.getSelected().isEmpty());
298 }
299
300 public void valueChanged(ListSelectionEvent e) {
301 updateEnabledState();
302 }
303 }
304
305 /**
306 * The action for zooming to the primitives in the current JOSM selection
307 *
308 */
309 class ZoomToJOSMSelectionAction extends AbstractAction implements ListDataListener {
310
311 public ZoomToJOSMSelectionAction() {
312 putValue(NAME,tr("Zoom to selection"));
313 putValue(SHORT_DESCRIPTION, tr("Zoom to selection"));
314 putValue(SMALL_ICON, ImageProvider.get("dialogs/autoscale", "selection"));
315 updateEnabledState();
316 }
317
318 public void actionPerformed(ActionEvent e) {
319 new AutoScaleAction("selection").autoScale();
320 }
321
322 public void updateEnabledState() {
323 setEnabled(model.getSize() > 0);
324 }
325
326 public void contentsChanged(ListDataEvent e) {
327 updateEnabledState();
328 }
329
330 public void intervalAdded(ListDataEvent e) {
331 updateEnabledState();
332 }
333
334 public void intervalRemoved(ListDataEvent e) {
335 updateEnabledState();
336 }
337 }
338
339 /**
340 * The action for zooming to the primitives which are currently selected in
341 * the list displaying the JOSM selection
342 *
343 */
344 class ZoomToListSelection extends AbstractAction implements ListSelectionListener{
345 public ZoomToListSelection() {
346 putValue(NAME, tr("Zoom to selected element(s)"));
347 putValue(SHORT_DESCRIPTION, tr("Zoom to selected element(s)"));
348 putValue(SMALL_ICON, ImageProvider.get("dialogs/autoscale", "selection"));
349 updateEnabledState();
350 }
351
352 public void actionPerformed(ActionEvent e) {
353 BoundingXYVisitor box = new BoundingXYVisitor();
354 Collection<OsmPrimitive> sel = model.getSelected();
355 if (sel.isEmpty()) return;
356 box.computeBoundingBox(sel);
357 if (box.getBounds() == null)
358 return;
359 box.enlargeBoundingBox();
360 Main.map.mapView.recalculateCenterScale(box);
361 }
362
363 public void updateEnabledState() {
364 setEnabled(!model.getSelected().isEmpty());
365 }
366
367 public void valueChanged(ListSelectionEvent e) {
368 updateEnabledState();
369 }
370 }
371
372 /**
373 * The list model for the list of OSM primitives in the current JOSM selection.
374 *
375 * The model also maintains a history of the last {@see SelectionListModel#SELECTION_HISTORY_SIZE}
376 * JOSM selection.
377 *
378 */
379 static private class SelectionListModel extends AbstractListModel implements EditLayerChangeListener, SelectionChangedListener, DataSetListener{
380
381 private static final int SELECTION_HISTORY_SIZE = 10;
382
383 private final LinkedList<Collection<? extends OsmPrimitive>> history = new LinkedList<Collection<? extends OsmPrimitive>>();
384 private final List<OsmPrimitive> selection = new ArrayList<OsmPrimitive>();
385 private DefaultListSelectionModel selectionModel;
386
387 /**
388 * Constructor
389 * @param selectionModel the selection model used in the list
390 */
391 public SelectionListModel(DefaultListSelectionModel selectionModel) {
392 this.selectionModel = selectionModel;
393 }
394
395 /**
396 * Replies a summary of the current JOSM selection
397 *
398 * @return a summary of the current JOSM selection
399 */
400 public String getJOSMSelectionSummary() {
401 if (selection.isEmpty()) return tr("Selection");
402 int numNodes = 0;
403 int numWays = 0;
404 int numRelations = 0;
405 for (OsmPrimitive p: selection) {
406 switch(p.getType()) {
407 case NODE: numNodes++; break;
408 case WAY: numWays++; break;
409 case RELATION: numRelations++; break;
410 }
411 }
412 return tr("Sel.: Rel.:{0} / Ways:{1} / Nodes:{2}", numRelations, numWays, numNodes);
413 }
414
415 /**
416 * Remembers a JOSM selection the history of JOSM selections
417 *
418 * @param selection the JOSM selection. Ignored if null or empty.
419 */
420 public void remember(Collection<? extends OsmPrimitive> selection) {
421 if (selection == null)return;
422 if (selection.isEmpty())return;
423 if (history.isEmpty()) {
424 history.add(selection);
425 return;
426 }
427 if (history.getFirst().equals(selection)) return;
428 history.addFirst(selection);
429 while (history.size() > SELECTION_HISTORY_SIZE) {
430 history.removeLast();
431 }
432 }
433
434 /**
435 * Replies the history of JOSM selections
436 *
437 * @return
438 */
439 public List<Collection<? extends OsmPrimitive>> getSelectionHistory() {
440 return history;
441 }
442
443 public Object getElementAt(int index) {
444 return selection.get(index);
445 }
446
447 public int getSize() {
448 return selection.size();
449 }
450
451 /**
452 * Replies the collection of OSM primitives currently selected in the view
453 * of this model
454 *
455 * @return
456 */
457 public Collection<OsmPrimitive> getSelected() {
458 Set<OsmPrimitive> sel = new HashSet<OsmPrimitive>();
459 for(int i=0; i< getSize();i++) {
460 if (selectionModel.isSelectedIndex(i)) {
461 sel.add(selection.get(i));
462 }
463 }
464 return sel;
465 }
466
467 /**
468 * Sets the OSM primitives to be selected in the view of this model
469 *
470 * @param sel the collection of primitives to select
471 */
472 public void setSelected(Collection<OsmPrimitive> sel) {
473 selectionModel.clearSelection();
474 if (sel == null) return;
475 for (OsmPrimitive p: sel){
476 int i = selection.indexOf(p);
477 if (i >= 0){
478 selectionModel.addSelectionInterval(i, i);
479 }
480 }
481 }
482
483 @Override
484 protected void fireContentsChanged(Object source, int index0, int index1) {
485 Collection<OsmPrimitive> sel = getSelected();
486 super.fireContentsChanged(source, index0, index1);
487 setSelected(sel);
488 }
489
490 /**
491 * Sets the collection of currently selected OSM objects
492 *
493 * @param selection the collection of currently selected OSM objects
494 */
495 public void setJOSMSelection(Collection<? extends OsmPrimitive> selection) {
496 this.selection.clear();
497 if (selection == null) {
498 fireContentsChanged(this, 0, getSize());
499 return;
500 }
501 this.selection.addAll(selection);
502 sort();
503 fireContentsChanged(this, 0, getSize());
504 remember(selection);
505 }
506
507 /**
508 * Sorts the primitives in the list
509 */
510 public void sort() {
511 Collections.sort(
512 this.selection,
513 new Comparator<OsmPrimitive>() {
514 NameFormatter nf = DefaultNameFormatter.getInstance();
515
516 public int compare(OsmPrimitive o1, OsmPrimitive o2) {
517 if (o1.getType() != o2.getType())
518 return o1.getType().compareTo(o2.getType());
519 return o1.getDisplayName(nf).compareTo(o2.getDisplayName(nf));
520 }
521 }
522 );
523 }
524
525 /**
526 * Triggers a refresh of the view for all primitives in {@code toUpdate}
527 * which are currently displayed in the view
528 *
529 * @param toUpdate the collection of primitives to update
530 */
531 public void update(Collection<? extends OsmPrimitive> toUpdate) {
532 if (toUpdate == null) return;
533 if (toUpdate.isEmpty()) return;
534 Collection<OsmPrimitive> sel = getSelected();
535 for (OsmPrimitive p: toUpdate){
536 int i = selection.indexOf(p);
537 if (i >= 0) {
538 super.fireContentsChanged(this, i,i);
539 }
540 }
541 setSelected(sel);
542 }
543
544 /**
545 * Replies the list of selected relations with incomplete members
546 *
547 * @return the list of selected relations with incomplete members
548 */
549 public List<Relation> getSelectedRelationsWithIncompleteMembers() {
550 List<Relation> ret = new LinkedList<Relation>();
551 for(int i=0; i<getSize(); i++) {
552 if (!selectionModel.isSelectedIndex(i)) {
553 continue;
554 }
555 OsmPrimitive p = selection.get(i);
556 if (! (p instanceof Relation)) {
557 continue;
558 }
559 if (p.isNew()) {
560 continue;
561 }
562 Relation r = (Relation)p;
563 if (r.hasIncompleteMembers()) {
564 ret.add(r);
565 }
566 }
567 return ret;
568 }
569
570 /* ------------------------------------------------------------------------ */
571 /* interface EditLayerChangeListener */
572 /* ------------------------------------------------------------------------ */
573 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
574 if (newLayer == null) {
575 setJOSMSelection(null);
576 } else {
577 setJOSMSelection(newLayer.data.getSelected());
578 }
579 }
580
581 /* ------------------------------------------------------------------------ */
582 /* interface SelectionChangeListener */
583 /* ------------------------------------------------------------------------ */
584 public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
585 setJOSMSelection(newSelection);
586 }
587
588 /* ------------------------------------------------------------------------ */
589 /* interface DataSetListener */
590 /* ------------------------------------------------------------------------ */
591 public void dataChanged(DataChangedEvent event) {
592 // refresh the whole list
593 fireContentsChanged(this, 0, getSize());
594 }
595
596 public void nodeMoved(NodeMovedEvent event) {
597 // may influence the display name of primitives, update the data
598 update(event.getPrimitives());
599 }
600
601 public void otherDatasetChange(AbstractDatasetChangedEvent event) {
602 // may influence the display name of primitives, update the data
603 update(event.getPrimitives());
604 }
605
606 public void relationMembersChanged(RelationMembersChangedEvent event) {
607 // may influence the display name of primitives, update the data
608 update(event.getPrimitives());
609 }
610
611 public void tagsChanged(TagsChangedEvent event) {
612 // may influence the display name of primitives, update the data
613 update(event.getPrimitives());
614 }
615
616 public void wayNodesChanged(WayNodesChangedEvent event) {
617 // may influence the display name of primitives, update the data
618 update(event.getPrimitives());
619 }
620
621 public void primtivesAdded(PrimitivesAddedEvent event) {/* ignored - handled by SelectionChangeListener */}
622 public void primtivesRemoved(PrimitivesRemovedEvent event) {/* ignored - handled by SelectionChangeListener*/}
623 }
624
625 /**
626 * A specialized {@link JMenuItem} for presenting one entry of the search history
627 *
628 * @author Jan Peter Stotz
629 */
630 protected static class SearchMenuItem extends JMenuItem implements ActionListener {
631 protected SearchSetting s;
632
633 public SearchMenuItem(SearchSetting s) {
634 super(s.toString());
635 this.s = s;
636 addActionListener(this);
637 }
638
639 public void actionPerformed(ActionEvent e) {
640 org.openstreetmap.josm.actions.search.SearchAction.searchWithoutHistory(s);
641 }
642 }
643
644 /**
645 * The popup menu for the search history entries
646 *
647 */
648 protected static class SearchPopupMenu extends JPopupMenu {
649 static public void launch(Component parent) {
650 if (org.openstreetmap.josm.actions.search.SearchAction.searchHistory.isEmpty())
651 return;
652 JPopupMenu menu = new SearchPopupMenu();
653 Rectangle r = parent.getBounds();
654 menu.show(parent, r.x, r.y + r.height);
655 }
656
657 public SearchPopupMenu() {
658 for (SearchSetting ss: org.openstreetmap.josm.actions.search.SearchAction.searchHistory) {
659 add(new SearchMenuItem(ss));
660 }
661 }
662 }
663
664 /**
665 * A specialized {@link JMenuItem} for presenting one entry of the selection history
666 *
667 * @author Jan Peter Stotz
668 */
669 protected static class SelectionMenuItem extends JMenuItem implements ActionListener {
670 protected Collection<? extends OsmPrimitive> sel;
671
672 public SelectionMenuItem(Collection<? extends OsmPrimitive> sel) {
673 super();
674 this.sel = sel;
675 int ways = 0;
676 int nodes = 0;
677 int relations = 0;
678 for (OsmPrimitive o : sel) {
679 if (o instanceof Way) {
680 ways++;
681 } else if (o instanceof Node) {
682 nodes++;
683 } else if (o instanceof Relation) {
684 relations++;
685 }
686 }
687 StringBuffer text = new StringBuffer();
688 if(ways != 0) {
689 text.append(text.length() > 0 ? ", " : "")
690 .append(trn("{0} way", "{0} ways", ways, ways));
691 }
692 if(nodes != 0) {
693 text.append(text.length() > 0 ? ", " : "")
694 .append(trn("{0} node", "{0} nodes", nodes, nodes));
695 }
696 if(relations != 0) {
697 text.append(text.length() > 0 ? ", " : "")
698 .append(trn("{0} relation", "{0} relations", relations, relations));
699 }
700 setText(tr("Selection: {0}", text));
701 addActionListener(this);
702 }
703
704 public void actionPerformed(ActionEvent e) {
705 Main.main.getCurrentDataSet().setSelected(sel);
706 }
707 }
708
709 /**
710 * The popup menue for the JOSM selection history entries
711 *
712 */
713 protected static class SelectionHistoryPopup extends JPopupMenu {
714 static public void launch(Component parent, Collection<Collection<? extends OsmPrimitive>> history) {
715 if (history == null || history.isEmpty()) return;
716 JPopupMenu menu = new SelectionHistoryPopup(history);
717 Rectangle r = parent.getBounds();
718 menu.show(parent, r.x, r.y + r.height);
719 }
720
721 public SelectionHistoryPopup(Collection<Collection<? extends OsmPrimitive>> history) {
722 for (Collection<? extends OsmPrimitive> sel : history) {
723 add(new SelectionMenuItem(sel));
724 }
725 }
726 }
727
728 /**
729 * Action for downloading incomplete members of selected relations
730 *
731 */
732 class DownloadSelectedIncompleteMembersAction extends AbstractAction implements ListSelectionListener{
733 public DownloadSelectedIncompleteMembersAction() {
734 putValue(SHORT_DESCRIPTION, tr("Download incomplete members of selected relations"));
735 putValue(SMALL_ICON, ImageProvider.get("dialogs/relation", "downloadincompleteselected"));
736 putValue(NAME, tr("Download incomplete members"));
737 updateEnabledState();
738 }
739
740 public Set<OsmPrimitive> buildSetOfIncompleteMembers(List<Relation> rels) {
741 Set<OsmPrimitive> ret = new HashSet<OsmPrimitive>();
742 for(Relation r: rels) {
743 ret.addAll(r.getIncompleteMembers());
744 }
745 return ret;
746 }
747
748 public void actionPerformed(ActionEvent e) {
749 if (!isEnabled())
750 return;
751 List<Relation> rels = model.getSelectedRelationsWithIncompleteMembers();
752 if (rels.isEmpty()) return;
753 Main.worker.submit(new DownloadRelationMemberTask(
754 rels,
755 buildSetOfIncompleteMembers(rels),
756 Main.map.mapView.getEditLayer()
757 ));
758 }
759
760 protected void updateEnabledState() {
761 setEnabled(!model.getSelectedRelationsWithIncompleteMembers().isEmpty());
762 }
763
764 public void valueChanged(ListSelectionEvent e) {
765 updateEnabledState();
766 }
767 }
768}
Note: See TracBrowser for help on using the repository browser.