source: osm/applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterDialog.java@ 31797

Last change on this file since 31797 was 31797, checked in by floscher, 10 years ago

[mapillary] More coding issues solved and more tests added

File size: 11.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.plugins.mapillary.gui;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.FlowLayout;
7import java.awt.GridLayout;
8import java.awt.event.ActionEvent;
9import java.awt.event.KeyEvent;
10import java.util.Arrays;
11import java.util.Calendar;
12
13import javax.swing.AbstractAction;
14import javax.swing.JButton;
15import javax.swing.JCheckBox;
16import javax.swing.JComboBox;
17import javax.swing.JDialog;
18import javax.swing.JLabel;
19import javax.swing.JOptionPane;
20import javax.swing.JPanel;
21import javax.swing.JSpinner;
22import javax.swing.JTextField;
23import javax.swing.SpinnerNumberModel;
24
25import org.openstreetmap.josm.Main;
26import org.openstreetmap.josm.gui.SideButton;
27import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
28import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage;
29import org.openstreetmap.josm.plugins.mapillary.MapillaryDataListener;
30import org.openstreetmap.josm.plugins.mapillary.MapillaryImage;
31import org.openstreetmap.josm.plugins.mapillary.MapillaryImportedImage;
32import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer;
33import org.openstreetmap.josm.tools.Shortcut;
34
35/**
36 * ToggleDialog that lets you filter the images that are being shown.
37 *
38 * @author nokutu
39 * @see MapillaryFilterChooseSigns
40 *
41 */
42public class MapillaryFilterDialog extends ToggleDialog implements
43 MapillaryDataListener {
44
45 private static final long serialVersionUID = -4192029663670922103L;
46
47 private static MapillaryFilterDialog INSTANCE;
48
49 private static final String[] TIME_LIST = { tr("All"), tr("Years"),
50 tr("Months"), tr("Days") };
51
52 private final JPanel panel;
53
54 /** Spinner to choose the range of dates. */
55 public SpinnerNumberModel spinner;
56
57 private final JCheckBox imported = new JCheckBox(tr("Imported images"));
58 private final JCheckBox downloaded = new JCheckBox(
59 new downloadCheckBoxAction());
60 private final JCheckBox onlySigns = new JCheckBox(new OnlySignsAction());
61 private final JComboBox<String> time;
62 private final JTextField user;
63
64 private final SideButton updateButton = new SideButton(new UpdateAction());
65 private final SideButton resetButton = new SideButton(new ResetAction());
66 private final JButton signChooser = new JButton(new SignChooserAction());
67
68 private final MapillaryFilterChooseSigns signFilter = MapillaryFilterChooseSigns
69 .getInstance();
70
71 /** The list of sign names */
72 private final String[] SIGN_TAGS = { "prohibitory_speed_limit",
73 "priority_stop", "other_give_way", "mandatory_roundabout",
74 "other_no_entry", "prohibitory_no_traffic_both_ways",
75 "danger_intersection", "mandatory_go", "mandatory_keep",
76 "danger_priority_next_intersection", "danger_uneven_road",
77 "prohibitory_no_parking", "prohibitory_on_overtaking",
78 "danger_pedestrian_crossing", "prohibitory_no_u_turn",
79 "prohibitory_noturn" };
80 /** The the {@link JCheckBox} where the respective tag should be searched */
81 private final JCheckBox[] SIGN_CHECKBOXES = { this.signFilter.maxSpeed,
82 this.signFilter.stop, this.signFilter.giveWay,
83 this.signFilter.roundabout, this.signFilter.access,
84 this.signFilter.access, this.signFilter.intersection,
85 this.signFilter.direction, this.signFilter.direction,
86 this.signFilter.intersection, this.signFilter.uneven,
87 this.signFilter.noParking, this.signFilter.noOvertaking,
88 this.signFilter.crossing, this.signFilter.noTurn, this.signFilter.noTurn };
89
90 private MapillaryFilterDialog() {
91 super(tr("Mapillary filter"), "mapillaryfilter.png",
92 tr("Open Mapillary filter dialog"), Shortcut.registerShortcut(
93 tr("Mapillary filter"), tr("Open Mapillary filter dialog"),
94 KeyEvent.VK_M, Shortcut.NONE), 200);
95
96 this.panel = new JPanel();
97
98 this.signChooser.setEnabled(false);
99 JPanel signChooserPanel = new JPanel();
100 signChooserPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
101 signChooserPanel.add(this.signChooser);
102
103 JPanel fromPanel = new JPanel();
104 fromPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
105 fromPanel.add(new JLabel(tr("Not older than: ")));
106 this.spinner = new SpinnerNumberModel(1, 0, 10000, 1);
107 fromPanel.add(new JSpinner(this.spinner));
108 this.time = new JComboBox<>(TIME_LIST);
109 fromPanel.add(this.time);
110
111 JPanel userSearchPanel = new JPanel();
112 userSearchPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
113 this.user = new JTextField(10);
114 this.user.addActionListener(new UpdateAction());
115 userSearchPanel.add(new JLabel(tr("User")));
116 userSearchPanel.add(this.user);
117
118 this.imported.setSelected(true);
119 this.downloaded.setSelected(true);
120
121 JPanel col1 = new JPanel(new GridLayout(2, 1));
122 col1.add(this.downloaded);
123 col1.add(fromPanel);
124 this.panel.add(col1);
125 JPanel col2 = new JPanel(new GridLayout(2, 1));
126 col2.add(this.imported);
127 col2.add(userSearchPanel);
128 this.panel.add(col2);
129 JPanel col3 = new JPanel(new GridLayout(2, 1));
130 col3.add(this.onlySigns);
131 col3.add(signChooserPanel);
132 this.panel.add(col3);
133
134 createLayout(this.panel, true,
135 Arrays.asList(new SideButton[] { this.updateButton, this.resetButton }));
136 }
137
138 /**
139 * Returns the unique instance of the class.
140 *
141 * @return THe unique instance of the class.
142 */
143 public static MapillaryFilterDialog getInstance() {
144 if (INSTANCE == null)
145 INSTANCE = new MapillaryFilterDialog();
146 return INSTANCE;
147 }
148
149 @Override
150 public void imagesAdded() {
151 refresh();
152 }
153
154 @Override
155 public void selectedImageChanged(MapillaryAbstractImage oldImage,
156 MapillaryAbstractImage newImage) {
157 }
158
159 /**
160 * Resets the dialog to its default state.
161 */
162 public void reset() {
163 this.imported.setSelected(true);
164 this.downloaded.setSelected(true);
165 this.onlySigns.setEnabled(true);
166 this.onlySigns.setSelected(false);
167 this.user.setText("");
168 this.time.setSelectedItem(TIME_LIST[0]);
169 this.spinner.setValue(1);
170 refresh();
171 }
172
173 /**
174 * Applies the selected filter.
175 */
176 public synchronized void refresh() {
177 boolean imported = this.imported.isSelected();
178 boolean downloaded = this.downloaded.isSelected();
179 boolean onlySigns = this.onlySigns.isSelected();
180
181 for (MapillaryAbstractImage img : MapillaryLayer.getInstance().getData()
182 .getImages()) {
183 img.setVisible(true);
184 if (img instanceof MapillaryImportedImage) {
185 if (!imported)
186 img.setVisible(false);
187 continue;
188 } else if (img instanceof MapillaryImage) {
189 if (!downloaded) {
190 img.setVisible(false);
191 continue;
192 }
193 if (onlySigns) {
194 if (((MapillaryImage) img).getSigns().isEmpty()) {
195 img.setVisible(false);
196 continue;
197 }
198 if (!checkSigns((MapillaryImage) img)) {
199 img.setVisible(false);
200 continue;
201 }
202 }
203 if (!this.user.getText().equals("")
204 && !this.user.getText().equals(((MapillaryImage) img).getUser())) {
205 img.setVisible(false);
206 continue;
207 }
208 }
209 // Calculates the amount of days since the image was taken
210 Long currentTime = currentTime();
211 if (this.time.getSelectedItem().equals(TIME_LIST[1])) {
212 if (img.getCapturedAt() < currentTime
213 - ((Integer) this.spinner.getValue()).longValue() * 365 * 24 * 60
214 * 60 * 1000) {
215 img.setVisible(false);
216 continue;
217 }
218 }
219 if (this.time.getSelectedItem().equals(TIME_LIST[2])) {
220 if (img.getCapturedAt() < currentTime
221 - ((Integer) this.spinner.getValue()).longValue() * 30 * 24 * 60
222 * 60 * 1000) {
223 img.setVisible(false);
224 continue;
225 }
226 }
227 if (this.time.getSelectedItem().equals(TIME_LIST[3])) {
228 if (img.getCapturedAt() < currentTime
229 - ((Integer) this.spinner.getValue()).longValue() * 60 * 60 * 1000) {
230 img.setVisible(false);
231 continue;
232 }
233 }
234 }
235 Main.map.repaint();
236 }
237
238 /**
239 * Checks if the image fulfills the sign conditions.
240 *
241 * @param img
242 * The {@link MapillaryAbstractImage} object that is going to be
243 * checked.
244 * @return {@code true} if it fulfills the conditions; {@code false}
245 * otherwise.
246 */
247 private boolean checkSigns(MapillaryImage img) {
248 for (int i = 0; i < this.SIGN_TAGS.length; i++) {
249 if (checkSign(img, this.SIGN_CHECKBOXES[i], this.SIGN_TAGS[i]))
250 return true;
251 }
252 return false;
253 }
254
255 private static boolean checkSign(MapillaryImage img, JCheckBox signCheckBox,
256 String singString) {
257 boolean contains = false;
258 for (String sign : img.getSigns()) {
259 if (sign.contains(singString))
260 contains = true;
261 }
262 if (contains == signCheckBox.isSelected() && contains)
263 return true;
264 return false;
265 }
266
267 private static long currentTime() {
268 Calendar cal = Calendar.getInstance();
269 return cal.getTimeInMillis();
270 }
271
272 private class downloadCheckBoxAction extends AbstractAction {
273
274 private static final long serialVersionUID = 4672634002899519496L;
275
276 public downloadCheckBoxAction() {
277 putValue(NAME, tr("Downloaded images"));
278 }
279
280 @Override
281 public void actionPerformed(ActionEvent arg0) {
282 MapillaryFilterDialog.this.onlySigns
283 .setEnabled(MapillaryFilterDialog.this.downloaded.isSelected());
284 }
285 }
286
287 private class UpdateAction extends AbstractAction {
288
289 private static final long serialVersionUID = -7417238601979689863L;
290
291 public UpdateAction() {
292 putValue(NAME, tr("Update"));
293 }
294
295 @Override
296 public void actionPerformed(ActionEvent arg0) {
297 MapillaryFilterDialog.getInstance().refresh();
298 }
299 }
300
301 private class ResetAction extends AbstractAction {
302 /**
303 *
304 */
305 private static final long serialVersionUID = 1178261778165525040L;
306
307 public ResetAction() {
308 putValue(NAME, tr("Reset"));
309 }
310
311 @Override
312 public void actionPerformed(ActionEvent arg0) {
313 MapillaryFilterDialog.getInstance().reset();
314 }
315 }
316
317 private class OnlySignsAction extends AbstractAction {
318
319 private static final long serialVersionUID = -2937440338019185723L;
320
321 public OnlySignsAction() {
322 putValue(NAME, tr("Only images with signs"));
323 }
324
325 @Override
326 public void actionPerformed(ActionEvent arg0) {
327 MapillaryFilterDialog.this.signChooser
328 .setEnabled(MapillaryFilterDialog.this.onlySigns.isSelected());
329 }
330 }
331
332 /**
333 * Opens a new window where you can specifically filter signs.
334 *
335 * @author nokutu
336 *
337 */
338 private class SignChooserAction extends AbstractAction {
339
340 private static final long serialVersionUID = 8706299665735930148L;
341
342 public SignChooserAction() {
343 putValue(NAME, tr("Choose signs"));
344 }
345
346 @Override
347 public void actionPerformed(ActionEvent arg0) {
348 JPanel dialog = MapillaryFilterChooseSigns.getInstance();
349 JOptionPane pane = new JOptionPane(dialog, JOptionPane.PLAIN_MESSAGE,
350 JOptionPane.OK_CANCEL_OPTION);
351 JDialog dlg = pane.createDialog(Main.parent, tr("Choose signs"));
352 dlg.setVisible(true);
353 if ((int) pane.getValue() == JOptionPane.OK_OPTION)
354 MapillaryFilterDialog.getInstance().refresh();
355 dlg.dispose();
356 }
357 }
358
359 /**
360 * Destroys the unique instance of the class.
361 */
362 public static void destroyInstance() {
363 MapillaryFilterDialog.INSTANCE = null;
364 }
365}
Note: See TracBrowser for help on using the repository browser.