1 | package org.openstreetmap.josm.gui.dialogs;
|
---|
2 |
|
---|
3 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
4 |
|
---|
5 | import java.awt.BorderLayout;
|
---|
6 | import java.awt.GridBagLayout;
|
---|
7 | import java.awt.GridLayout;
|
---|
8 | import java.awt.event.ActionEvent;
|
---|
9 | import java.awt.event.ActionListener;
|
---|
10 | import java.awt.event.KeyEvent;
|
---|
11 | import java.awt.event.MouseAdapter;
|
---|
12 | import java.awt.event.MouseEvent;
|
---|
13 | import java.io.IOException;
|
---|
14 | import java.io.InputStream;
|
---|
15 | import java.net.MalformedURLException;
|
---|
16 | import java.net.URL;
|
---|
17 | import java.net.URLConnection;
|
---|
18 | import java.util.Arrays;
|
---|
19 | import java.util.Collection;
|
---|
20 | import java.util.LinkedList;
|
---|
21 | import java.util.Map;
|
---|
22 |
|
---|
23 | import javax.swing.ButtonGroup;
|
---|
24 | import javax.swing.DefaultListModel;
|
---|
25 | import javax.swing.JButton;
|
---|
26 | import javax.swing.JLabel;
|
---|
27 | import javax.swing.JList;
|
---|
28 | import javax.swing.JOptionPane;
|
---|
29 | import javax.swing.JPanel;
|
---|
30 | import javax.swing.JRadioButton;
|
---|
31 | import javax.swing.JScrollPane;
|
---|
32 | import javax.swing.JTextField;
|
---|
33 | import javax.swing.ListSelectionModel;
|
---|
34 |
|
---|
35 | import org.openstreetmap.josm.Main;
|
---|
36 | import org.openstreetmap.josm.data.SelectionChangedListener;
|
---|
37 | import org.openstreetmap.josm.data.osm.OsmPrimitive;
|
---|
38 | import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
|
---|
39 | import org.openstreetmap.josm.gui.PleaseWaitRunnable;
|
---|
40 | import org.openstreetmap.josm.io.OsmIdReader;
|
---|
41 | import org.openstreetmap.josm.io.ProgressInputStream;
|
---|
42 | import org.openstreetmap.josm.tools.GBC;
|
---|
43 | import org.openstreetmap.josm.tools.ImageProvider;
|
---|
44 | import org.openstreetmap.josm.tools.SearchCompiler;
|
---|
45 | import org.xml.sax.SAXException;
|
---|
46 |
|
---|
47 | /**
|
---|
48 | * A small tool dialog for displaying the current selection. The selection manager
|
---|
49 | * respects clicks into the selection list. Ctrl-click will remove entries from
|
---|
50 | * the list while single click will make the clicked entry the only selection.
|
---|
51 | *
|
---|
52 | * @author imi
|
---|
53 | */
|
---|
54 | public class SelectionListDialog extends ToggleDialog implements SelectionChangedListener {
|
---|
55 | public static enum SearchMode {replace, add, remove}
|
---|
56 |
|
---|
57 | private static class SelectionWebsiteLoader extends PleaseWaitRunnable {
|
---|
58 | public final URL url;
|
---|
59 | public Collection<OsmPrimitive> sel;
|
---|
60 | private final SearchMode mode;
|
---|
61 | private OsmIdReader idReader = new OsmIdReader();
|
---|
62 | public SelectionWebsiteLoader(String urlStr, SearchMode mode) {
|
---|
63 | super(tr("Load Selection"));
|
---|
64 | this.mode = mode;
|
---|
65 | URL u = null;
|
---|
66 | try {u = new URL(urlStr);} catch (MalformedURLException e) {}
|
---|
67 | this.url = u;
|
---|
68 | }
|
---|
69 | @Override protected void realRun() {
|
---|
70 | Main.pleaseWaitDlg.currentAction.setText(tr("Contact {0}...", url.getHost()));
|
---|
71 | sel = mode != SearchMode.remove ? new LinkedList<OsmPrimitive>() : Main.ds.allNonDeletedPrimitives();
|
---|
72 | try {
|
---|
73 | URLConnection con = url.openConnection();
|
---|
74 | InputStream in = new ProgressInputStream(con);
|
---|
75 | Main.pleaseWaitDlg.currentAction.setText(tr("Downloading..."));
|
---|
76 | Map<Long, String> ids = idReader.parseIds(in);
|
---|
77 | for (OsmPrimitive osm : Main.ds.allNonDeletedPrimitives()) {
|
---|
78 | if (ids.containsKey(osm.id) && osm.getClass().getName().toLowerCase().endsWith(ids.get(osm.id))) {
|
---|
79 | if (mode == SearchMode.remove)
|
---|
80 | sel.remove(osm);
|
---|
81 | else
|
---|
82 | sel.add(osm);
|
---|
83 | }
|
---|
84 | }
|
---|
85 | } catch (IOException e) {
|
---|
86 | e.printStackTrace();
|
---|
87 | JOptionPane.showMessageDialog(Main.parent, tr("Could not read from url: \"{0}\"",url));
|
---|
88 | } catch (SAXException e) {
|
---|
89 | e.printStackTrace();
|
---|
90 | JOptionPane.showMessageDialog(Main.parent,tr("Parsing error in url: \"{0}\"",url));
|
---|
91 | }
|
---|
92 | }
|
---|
93 | @Override protected void cancel() {
|
---|
94 | sel = null;
|
---|
95 | idReader.cancel();
|
---|
96 | }
|
---|
97 | @Override protected void finish() {
|
---|
98 | if (sel != null)
|
---|
99 | Main.ds.setSelected(sel);
|
---|
100 | }
|
---|
101 | }
|
---|
102 |
|
---|
103 | /**
|
---|
104 | * The selection's list data.
|
---|
105 | */
|
---|
106 | private final DefaultListModel list = new DefaultListModel();
|
---|
107 | /**
|
---|
108 | * The display list.
|
---|
109 | */
|
---|
110 | private JList displaylist = new JList(list);
|
---|
111 |
|
---|
112 | public SelectionListDialog() {
|
---|
113 | super(tr("Current Selection"), "selectionlist", tr("Open a selection list window."), KeyEvent.VK_E, 150);
|
---|
114 | displaylist.setCellRenderer(new OsmPrimitivRenderer());
|
---|
115 | displaylist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
---|
116 | displaylist.addMouseListener(new MouseAdapter(){
|
---|
117 | @Override public void mouseClicked(MouseEvent e) {
|
---|
118 | if (e.getClickCount() < 2)
|
---|
119 | return;
|
---|
120 | updateMap();
|
---|
121 | }
|
---|
122 | });
|
---|
123 |
|
---|
124 | add(new JScrollPane(displaylist), BorderLayout.CENTER);
|
---|
125 |
|
---|
126 | JPanel buttonPanel = new JPanel(new GridLayout(1,2));
|
---|
127 |
|
---|
128 | buttonPanel.add(createButton("Select", "mapmode/selection/select", "Set the selected elements on the map to the selected items in the list above.", new ActionListener(){
|
---|
129 | public void actionPerformed(ActionEvent e) {
|
---|
130 | updateMap();
|
---|
131 | }
|
---|
132 | }));
|
---|
133 |
|
---|
134 | buttonPanel.add(createButton("Reload", "dialogs/refresh", "Refresh the selection list.", new ActionListener(){
|
---|
135 | public void actionPerformed(ActionEvent e) {
|
---|
136 | selectionChanged(Main.ds.getSelected());
|
---|
137 | }
|
---|
138 | }));
|
---|
139 |
|
---|
140 | buttonPanel.add(createButton("Search", "dialogs/search", "Search for objects.", new ActionListener(){
|
---|
141 | private String lastSearch = "";
|
---|
142 | public void actionPerformed(ActionEvent e) {
|
---|
143 | JLabel label = new JLabel(tr("Please enter a search string."));
|
---|
144 | final JTextField input = new JTextField(lastSearch);
|
---|
145 | input.setToolTipText(tr("<html>Fulltext search.<ul>" +
|
---|
146 | "<li><code>Baker Street</code> - 'Baker' and 'Street' in any key or name.</li>" +
|
---|
147 | "<li><code>\"Baker Street\"</code> - 'Baker Street' in any key or name.</li>" +
|
---|
148 | "<li><code>name:Bak</code> - 'Bak' anywhere in the name.</li>" +
|
---|
149 | "<li><code>-name:Bak</code> - not 'Bak' in the name.</li>" +
|
---|
150 | "<li><code>foot:</code> - key=foot set to any value." +
|
---|
151 | "</ul></html>"));
|
---|
152 |
|
---|
153 | JRadioButton replace = new JRadioButton(tr("replace selection"), true);
|
---|
154 | JRadioButton add = new JRadioButton(tr("add to selection"), false);
|
---|
155 | JRadioButton remove = new JRadioButton(tr("remove from selection"), false);
|
---|
156 | ButtonGroup bg = new ButtonGroup();
|
---|
157 | bg.add(replace);
|
---|
158 | bg.add(add);
|
---|
159 | bg.add(remove);
|
---|
160 |
|
---|
161 | JPanel p = new JPanel(new GridBagLayout());
|
---|
162 | p.add(label, GBC.eop());
|
---|
163 | p.add(input, GBC.eop().fill(GBC.HORIZONTAL));
|
---|
164 | p.add(replace, GBC.eol());
|
---|
165 | p.add(add, GBC.eol());
|
---|
166 | p.add(remove, GBC.eol());
|
---|
167 | JOptionPane pane = new JOptionPane(p, JOptionPane.INFORMATION_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null){
|
---|
168 | @Override public void selectInitialValue() {
|
---|
169 | input.requestFocusInWindow();
|
---|
170 | }
|
---|
171 | };
|
---|
172 | pane.createDialog(Main.parent,tr("Search")).setVisible(true);
|
---|
173 | if (!Integer.valueOf(JOptionPane.OK_OPTION).equals(pane.getValue()))
|
---|
174 | return;
|
---|
175 | lastSearch = input.getText();
|
---|
176 | SearchMode mode = replace.isSelected() ? SearchMode.replace : (add.isSelected() ? SearchMode.add : SearchMode.remove);
|
---|
177 | search(lastSearch, mode);
|
---|
178 | }
|
---|
179 | }));
|
---|
180 |
|
---|
181 | add(buttonPanel, BorderLayout.SOUTH);
|
---|
182 | selectionChanged(Main.ds.getSelected());
|
---|
183 | }
|
---|
184 |
|
---|
185 | private JButton createButton(String name, String icon, String tooltip, ActionListener action) {
|
---|
186 | JButton button = new JButton(tr(name), ImageProvider.get(icon));
|
---|
187 | button.setToolTipText(tr(tooltip));
|
---|
188 | button.addActionListener(action);
|
---|
189 | button.putClientProperty("help", "Dialog/SelectionList/"+name);
|
---|
190 | return button;
|
---|
191 | }
|
---|
192 |
|
---|
193 | @Override public void setVisible(boolean b) {
|
---|
194 | if (b) {
|
---|
195 | Main.ds.addSelectionChangedListener(this);
|
---|
196 | selectionChanged(Main.ds.getSelected());
|
---|
197 | } else {
|
---|
198 | Main.ds.removeSelectionChangedListener(this);
|
---|
199 | }
|
---|
200 | super.setVisible(b);
|
---|
201 | }
|
---|
202 |
|
---|
203 |
|
---|
204 |
|
---|
205 | /**
|
---|
206 | * Called when the selection in the dataset changed.
|
---|
207 | * @param newSelection The new selection array.
|
---|
208 | */
|
---|
209 | public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
|
---|
210 | if (list == null)
|
---|
211 | return; // selection changed may be received in base class constructor before init
|
---|
212 | OsmPrimitive[] selArr = new OsmPrimitive[newSelection.size()];
|
---|
213 | selArr = newSelection.toArray(selArr);
|
---|
214 | Arrays.sort(selArr);
|
---|
215 | list.setSize(selArr.length);
|
---|
216 | int i = 0;
|
---|
217 | for (OsmPrimitive osm : selArr)
|
---|
218 | list.setElementAt(osm, i++);
|
---|
219 | }
|
---|
220 |
|
---|
221 | /**
|
---|
222 | * Sets the selection of the map to the current selected items.
|
---|
223 | */
|
---|
224 | public void updateMap() {
|
---|
225 | Collection<OsmPrimitive> sel = new LinkedList<OsmPrimitive>();
|
---|
226 | for (int i = 0; i < list.getSize(); ++i)
|
---|
227 | if (displaylist.isSelectedIndex(i))
|
---|
228 | sel.add((OsmPrimitive)list.get(i));
|
---|
229 | Main.ds.setSelected(sel);
|
---|
230 | }
|
---|
231 |
|
---|
232 | public static void search(String search, SearchMode mode) {
|
---|
233 | if (search.startsWith("http://") || search.startsWith("ftp://") || search.startsWith("https://") || search.startsWith("file:/")) {
|
---|
234 | SelectionWebsiteLoader loader = new SelectionWebsiteLoader(search, mode);
|
---|
235 | if (loader.url != null) {
|
---|
236 | Main.worker.execute(loader);
|
---|
237 | return;
|
---|
238 | }
|
---|
239 | }
|
---|
240 | Collection<OsmPrimitive> sel = Main.ds.getSelected();
|
---|
241 | SearchCompiler.Match matcher = SearchCompiler.compile(search);
|
---|
242 | for (OsmPrimitive osm : Main.ds.allNonDeletedPrimitives()) {
|
---|
243 | if (mode == SearchMode.replace) {
|
---|
244 | if (matcher.match(osm))
|
---|
245 | sel.add(osm);
|
---|
246 | else
|
---|
247 | sel.remove(osm);
|
---|
248 | } else if (mode == SearchMode.add && !osm.selected && matcher.match(osm))
|
---|
249 | sel.add(osm);
|
---|
250 | else if (mode == SearchMode.remove && osm.selected && matcher.match(osm))
|
---|
251 | sel.remove(osm);
|
---|
252 | }
|
---|
253 | Main.ds.setSelected(sel);
|
---|
254 | }
|
---|
255 | }
|
---|