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

Last change on this file since 2716 was 2710, checked in by stoecker, 14 years ago

close #4222 - unify design of right menus again

  • Property svn:eol-style set to native
File size: 13.5 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.marktr;
5import static org.openstreetmap.josm.tools.I18n.tr;
6import static org.openstreetmap.josm.tools.I18n.trn;
7
8import java.awt.BorderLayout;
9import java.awt.Color;
10import java.awt.Rectangle;
11import java.awt.event.ActionEvent;
12import java.awt.event.ActionListener;
13import java.awt.event.KeyEvent;
14import java.awt.event.MouseAdapter;
15import java.awt.event.MouseEvent;
16import java.util.Collection;
17import java.util.Collections;
18import java.util.LinkedList;
19import java.util.NoSuchElementException;
20
21import javax.swing.BorderFactory;
22import javax.swing.DefaultListModel;
23import javax.swing.JList;
24import javax.swing.JMenuItem;
25import javax.swing.JPanel;
26import javax.swing.JPopupMenu;
27import javax.swing.JScrollPane;
28import javax.swing.ListSelectionModel;
29import javax.swing.SwingConstants;
30import javax.swing.plaf.basic.BasicArrowButton;
31
32import org.openstreetmap.josm.Main;
33import org.openstreetmap.josm.actions.AutoScaleAction;
34import org.openstreetmap.josm.actions.search.SearchAction;
35import org.openstreetmap.josm.actions.search.SearchAction.SearchSetting;
36import org.openstreetmap.josm.data.SelectionChangedListener;
37import org.openstreetmap.josm.data.osm.DataSet;
38import org.openstreetmap.josm.data.osm.Node;
39import org.openstreetmap.josm.data.osm.OsmPrimitive;
40import org.openstreetmap.josm.data.osm.Relation;
41import org.openstreetmap.josm.data.osm.Way;
42import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
43import org.openstreetmap.josm.gui.MapView;
44import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
45import org.openstreetmap.josm.gui.SideButton;
46import org.openstreetmap.josm.gui.layer.OsmDataLayer;
47import org.openstreetmap.josm.tools.Shortcut;
48
49/**
50 * A small tool dialog for displaying the current selection. The selection manager
51 * respects clicks into the selection list. Ctrl-click will remove entries from
52 * the list while single click will make the clicked entry the only selection.
53 *
54 * @author imi
55 */
56public class SelectionListDialog extends ToggleDialog implements SelectionChangedListener, MapView.EditLayerChangeListener {
57
58 private static final int SELECTION_HISTORY_SIZE = 10;
59
60 /**
61 * The selection's list data.
62 */
63 private final DefaultListModel list = new DefaultListModel();
64
65 private LinkedList<Collection<? extends OsmPrimitive>> selectionHistory;
66
67 /**
68 * The display list.
69 */
70 private JList displaylist = new JList(list);
71 private SideButton selectButton;
72 private SideButton searchButton;
73 private JPopupMenu popupMenu;
74 private JMenuItem zoomToElement;
75
76 /**
77 * If the selection changed event is triggered with newSelection equals
78 * this element, the newSelection will not be added to the selection history
79 */
80 private Collection<? extends OsmPrimitive> historyIgnoreSelection = null;
81
82 public SelectionListDialog() {
83 super(tr("Current Selection"), "selectionlist", tr("Open a selection list window."),
84 Shortcut.registerShortcut("subwindow:selection", tr("Toggle: {0}", tr("Current Selection")), KeyEvent.VK_T, Shortcut.GROUP_LAYER, Shortcut.SHIFT_DEFAULT), 150, true);
85
86 selectionHistory = new LinkedList<Collection<? extends OsmPrimitive>>();
87 popupMenu = new JPopupMenu();
88 displaylist.setCellRenderer(new OsmPrimitivRenderer());
89 displaylist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
90 displaylist.addMouseListener(new MouseAdapter() {
91 @Override
92 public void mouseClicked(MouseEvent e) {
93 if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) {
94 updateMap();
95 }
96 }
97
98 @Override
99 public void mousePressed(MouseEvent e) {
100 showPopupMenu(e);
101 }
102
103 @Override
104 public void mouseReleased(MouseEvent e) {
105 showPopupMenu(e);
106 }
107
108 });
109
110 add(new JScrollPane(displaylist), BorderLayout.CENTER);
111
112 JPanel buttonPanel = getButtonPanel(2);
113
114 selectButton = new SideButton(marktr("Select"), "select", "SelectionList",
115 tr("Set the selected elements on the map to the selected items in the list above."),
116 new ActionListener() {
117 public void actionPerformed(ActionEvent e) {
118 updateMap();
119 }
120 });
121 buttonPanel.add(selectButton);
122 BasicArrowButton selectionHistoryMenuButton = createArrowButton(selectButton);
123 selectionHistoryMenuButton.addActionListener(new ActionListener() {
124 public void actionPerformed(ActionEvent e) {
125 showSelectionHistoryMenu();
126 }
127 });
128 add(buttonPanel, BorderLayout.SOUTH);
129
130 zoomToElement = new JMenuItem(tr("Zoom to selected element(s)"));
131 zoomToElement.addActionListener(new ActionListener() {
132 public void actionPerformed(ActionEvent e) {
133 zoomToSelectedElement();
134 }
135 });
136
137 searchButton = new SideButton(marktr("Search"), "search", "SelectionList", tr("Search for objects."),
138 Main.main.menu.search);
139 buttonPanel.add(searchButton);
140
141 BasicArrowButton searchHistoryMenuButton = createArrowButton(searchButton);
142 searchHistoryMenuButton.addActionListener(new ActionListener() {
143 public void actionPerformed(ActionEvent e) {
144 showSearchHistoryMenu();
145 }
146 });
147
148 popupMenu.add(zoomToElement);
149 JMenuItem zoomToSelection = new JMenuItem(tr("Zoom to selection"));
150 zoomToSelection.addActionListener(new ActionListener() {
151 public void actionPerformed(ActionEvent e) {
152 zoomToSelection();
153 }
154 });
155 popupMenu.add(zoomToSelection);
156
157 if (Main.main.getCurrentDataSet() != null) {
158 selectionChanged(Main.main.getCurrentDataSet().getSelected());
159 }
160
161 MapView.addEditLayerChangeListener(this);
162 }
163
164 @Override
165 public void tearDown() {
166 MapView.removeEditLayerChangeListener(this);
167 }
168
169 @Override
170 public void showNotify() {
171 DataSet.selListeners.add(this);
172 updateSelection();
173 }
174
175 @Override
176 public void hideNotify() {
177 DataSet.selListeners.remove(this);
178 }
179
180 private BasicArrowButton createArrowButton(SideButton parentButton) {
181 BasicArrowButton arrowButton = new BasicArrowButton(SwingConstants.SOUTH, null, null, Color.BLACK, null);
182 arrowButton.setBorder(BorderFactory.createEmptyBorder());
183 parentButton.setLayout(new BorderLayout());
184 parentButton.add(arrowButton, BorderLayout.EAST);
185 return arrowButton;
186 }
187
188 @Override
189 public void setVisible(boolean b) {
190 super.setVisible(b);
191 if (b && Main.main.getCurrentDataSet() != null) {
192 selectionChanged(Main.main.getCurrentDataSet().getSelected());
193 }
194 }
195
196 protected void showPopupMenu(MouseEvent e) {
197 if (e.isPopupTrigger()) {
198 zoomToElement.setVisible(displaylist.getSelectedIndex() >= 0);
199 popupMenu.show(e.getComponent(), e.getX(), e.getY());
200 }
201 }
202
203 public void zoomToSelection() {
204 new AutoScaleAction("selection").actionPerformed(null);
205 }
206
207 /**
208 * Zooms to the element(s) selected in {@link #displaylist}
209 */
210 public void zoomToSelectedElement() {
211 BoundingXYVisitor box = new BoundingXYVisitor();
212 int[] selected = displaylist.getSelectedIndices();
213 if (selected.length == 0)
214 return;
215 for (int i = 0; i < selected.length; i++) {
216 Object o = list.get(selected[i]);
217 if (o instanceof OsmPrimitive) {
218 ((OsmPrimitive) o).visit(box);
219 }
220 }
221 if (box.getBounds() == null)
222 return;
223 box.enlargeBoundingBox();
224 Main.map.mapView.recalculateCenterScale(box);
225 }
226
227 private void showSelectionHistoryMenu() {
228 if (selectionHistory.size() == 0)
229 return;
230 JPopupMenu historyMenu = new JPopupMenu();
231 for (Collection<? extends OsmPrimitive> sel : selectionHistory) {
232 SelectionMenuItem item = new SelectionMenuItem(sel);
233 historyMenu.add(item);
234 }
235 Rectangle r = selectButton.getBounds();
236 historyMenu.show(selectButton, r.x, r.y + r.height);
237 }
238
239 private void showSearchHistoryMenu() {
240 if (SearchAction.searchHistory.size() == 0)
241 return;
242 JPopupMenu historyMenu = new JPopupMenu();
243 for (SearchAction.SearchSetting s : SearchAction.searchHistory) {
244 SearchMenuItem item = new SearchMenuItem(s);
245 historyMenu.add(item);
246 }
247 Rectangle r = searchButton.getBounds();
248 historyMenu.show(searchButton, r.x, r.y + r.height);
249 }
250
251 /**
252 * Called when the selection in the dataset changed.
253 * @param newSelection The new selection array.
254 */
255 public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
256 if (list == null || !isVisible())
257 return; // selection changed may be received in base class constructor before init
258 OsmPrimitive selArr[] = DataSet.sort(newSelection);
259 list.setSize(selArr.length);
260 int i = 0;
261 for (OsmPrimitive osm : selArr) {
262 list.setElementAt(osm, i++);
263 }
264 if (selectionHistory != null && newSelection.size() > 0 && !newSelection.equals(historyIgnoreSelection)) {
265 historyIgnoreSelection = null;
266 try {
267 // Check if the newSelection has already been added to the history
268 Collection<? extends OsmPrimitive> first = selectionHistory.getFirst();
269 if (first.equals(newSelection))
270 return;
271 } catch (NoSuchElementException e) {
272 }
273 selectionHistory.addFirst(newSelection);
274 while (selectionHistory.size() > SELECTION_HISTORY_SIZE) {
275 selectionHistory.removeLast();
276 }
277 }
278
279 int ways = 0;
280 int nodes = 0;
281 int relations = 0;
282 for (OsmPrimitive o : newSelection) {
283 if (o instanceof Way) {
284 ways++;
285 } else if (o instanceof Node) {
286 nodes++;
287 } else if (o instanceof Relation) {
288 relations++;
289 }
290 }
291
292 if( (nodes+ways+relations) != 0) {
293 setTitle(tr("Sel.: Rel.:{0} / Ways:{1} / Nodes:{2}", relations, ways, nodes));
294 } else {
295 setTitle(tr("Selection"));
296 }
297 }
298
299 /**
300 * Sets the selection of the map to the current selected items.
301 */
302 public void updateMap() {
303 Collection<OsmPrimitive> sel = new LinkedList<OsmPrimitive>();
304 for (int i = 0; i < list.getSize(); ++i)
305 if (displaylist.isSelectedIndex(i)) {
306 sel.add((OsmPrimitive) list.get(i));
307 }
308 Main.main.getCurrentDataSet().setSelected(sel);
309 }
310
311 /**
312 * A specialized {@link JMenuItem} for presenting one entry of the selection history
313 *
314 * @author Jan Peter Stotz
315 */
316 protected class SelectionMenuItem extends JMenuItem implements ActionListener {
317 protected Collection<? extends OsmPrimitive> sel;
318
319 public SelectionMenuItem(Collection<? extends OsmPrimitive> sel) {
320 super();
321 this.sel = sel;
322 int ways = 0;
323 int nodes = 0;
324 int relations = 0;
325 for (OsmPrimitive o : sel) {
326 if (o instanceof Way) {
327 ways++;
328 } else if (o instanceof Node) {
329 nodes++;
330 } else if (o instanceof Relation) {
331 relations++;
332 }
333 }
334 String text = "";
335 if(ways != 0) {
336 text += (text.length() > 0 ? ", " : "")
337 + trn("{0} way", "{0} ways", ways, ways);
338 }
339 if(nodes != 0) {
340 text += (text.length() > 0 ? ", " : "")
341 + trn("{0} node", "{0} nodes", nodes, nodes);
342 }
343 if(relations != 0) {
344 text += (text.length() > 0 ? ", " : "")
345 + trn("{0} relation", "{0} relations", relations, relations);
346 }
347 setText(tr("Selection: {0}", text));
348 addActionListener(this);
349 }
350
351 public void actionPerformed(ActionEvent e) {
352 historyIgnoreSelection = sel;
353 Main.main.getCurrentDataSet().setSelected(sel);
354 }
355
356 }
357
358 /**
359 * A specialized {@link JMenuItem} for presenting one entry of the search history
360 *
361 * @author Jan Peter Stotz
362 */
363 protected static class SearchMenuItem extends JMenuItem implements ActionListener {
364 protected SearchSetting s;
365
366 public SearchMenuItem(SearchSetting s) {
367 super(s.toString());
368 this.s = s;
369 addActionListener(this);
370 }
371
372 public void actionPerformed(ActionEvent e) {
373 SearchAction.searchWithoutHistory(s);
374 }
375
376 }
377
378 private void updateSelection() {
379 if (Main.main.getCurrentDataSet() == null) {
380 selectionChanged(Collections.<OsmPrimitive>emptyList());
381 } else {
382 selectionChanged(Main.main.getCurrentDataSet().getSelected());
383 }
384 }
385
386 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
387 updateSelection();
388 }
389}
Note: See TracBrowser for help on using the repository browser.