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

Last change on this file since 2224 was 2224, checked in by stoecker, 15 years ago

see #3550 - patch by bastiK - allow resizing right handside dialogs, updated i18n

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