source: osm/applications/editors/josm/plugins/indoorhelper/src/controller/IndoorHelperController.java@ 34741

Last change on this file since 34741 was 34741, checked in by donvip, 6 years ago

fix #17030 - remove indoorhelper validator file

File size: 21.4 KB
Line 
1/*
2 * Indoorhelper is a JOSM plug-in to support users when creating their own indoor maps.
3 * Copyright (C) 2016 Erik Gruschka
4 * Copyright (C) 2018 Rebecca Schmidt
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20package controller;
21
22import static org.openstreetmap.josm.tools.I18n.tr;
23
24import java.awt.event.ActionEvent;
25import java.awt.event.ActionListener;
26import java.awt.event.ItemEvent;
27import java.awt.event.ItemListener;
28import java.awt.event.KeyEvent;
29import java.awt.event.WindowEvent;
30import java.awt.event.WindowListener;
31import java.util.ArrayList;
32import java.util.Collection;
33import java.util.HashMap;
34import java.util.List;
35import java.util.Map;
36import java.util.Optional;
37
38import javax.swing.AbstractAction;
39import javax.swing.JOptionPane;
40
41import org.openstreetmap.josm.actions.ValidateAction;
42import org.openstreetmap.josm.actions.mapmode.DrawAction;
43import org.openstreetmap.josm.actions.mapmode.SelectAction;
44import org.openstreetmap.josm.data.Preferences;
45import org.openstreetmap.josm.data.osm.OsmDataManager;
46import org.openstreetmap.josm.data.osm.OsmPrimitive;
47import org.openstreetmap.josm.data.osm.Tag;
48import org.openstreetmap.josm.gui.MainApplication;
49import org.openstreetmap.josm.gui.MapFrame;
50import org.openstreetmap.josm.gui.help.HelpBrowser;
51import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
52import org.openstreetmap.josm.spi.preferences.Config;
53import org.openstreetmap.josm.spi.preferences.MapListSetting;
54import org.openstreetmap.josm.spi.preferences.Setting;
55import org.openstreetmap.josm.tools.Shortcut;
56
57import model.IndoorHelperModel;
58import model.IndoorLevel;
59import model.TagCatalog.IndoorObject;
60import views.LevelSelectorView;
61import views.ToolBoxView;
62
63/**
64*
65* Class for the Controller which provides the communication between
66* the IndoorHelperModel and the different views.
67*
68* @author egru
69* @author rebsc
70*
71*/
72public class IndoorHelperController {
73
74 private IndoorHelperModel model;
75 private ToolBoxView toolboxView;
76 private String sep;
77 private String levelValue, levelNum;
78 private MapFrame map;
79 private DrawAction drawAction;
80 private SelectAction selectAction;
81 private SpaceAction spaceAction;
82 private transient Shortcut spaceShortcut;
83 private EnterAction enterAction;
84 private transient Shortcut enterShortcut;
85 private boolean outerHelp, innerHelp, levelHelp;
86 private Collection<OsmPrimitive> innerRelation;
87 private LevelSelectorView selectorView;
88
89 /**
90 * Constructor for the {@link IndoorHelperController} which initiates model and views.
91 *
92 */
93 public IndoorHelperController() {
94
95 this.model = new IndoorHelperModel();
96 this.toolboxView = new ToolBoxView();
97
98 this.sep = System.getProperty("file.separator");
99 setPluginPreferences(true);
100
101 // Multipolygon actions
102 this.drawAction = new DrawAction();
103 this.map = MainApplication.getMap();
104 this.selectAction = new SelectAction(map);
105
106 // Ui elements
107 toolboxView.setAllUiElementsEnabled(true);
108 toolboxView.setROUiElementsEnabled(false);
109
110 addToolboxListeners();
111 MainApplication.getMap().addToggleDialog(toolboxView);
112
113 // Shortcuts
114 spaceShortcut = Shortcut.registerShortcut("mapmode:space",
115 "ConfirmObjectDrawing", KeyEvent.VK_SPACE, Shortcut.DIRECT);
116 this.spaceAction = new SpaceAction();
117 MainApplication.registerActionShortcut(spaceAction, spaceShortcut);
118
119 enterShortcut = Shortcut.registerShortcut("mapmode:enter",
120 "ConfirmMultipolygonSelection", KeyEvent.VK_ENTER, Shortcut.DIRECT);
121 this.enterAction = new EnterAction();
122 MainApplication.registerActionShortcut(enterAction, enterShortcut);
123
124 // Helper
125 outerHelp = false;
126 innerHelp = false;
127 levelHelp = false;
128 innerRelation = null;
129 levelValue = new String();
130 levelNum = new String();
131
132 }
133
134
135 /**
136 * Adds the button- and box-listeners to the {@link ToolBoxView}.
137 */
138 private void addToolboxListeners() {
139
140 if (this.toolboxView != null) {
141 this.toolboxView.setApplyButtonListener(new ToolApplyButtonListener());
142 this.toolboxView.setLevelCheckBoxListener(new ToolLevelCheckBoxListener());
143 this.toolboxView.setHelpButtonListener(new ToolHelpButtonListener());
144 this.toolboxView.setAddLevelButtonListener(new ToolAddLevelButtonListener());
145 this.toolboxView.setObjectItemListener(new ToolObjectItemListener());
146 this.toolboxView.setOuterButtonListener(new ToolOuterButtonListener());
147 this.toolboxView.setInnerButtonListener(new ToolInnerButtonListener());
148 this.toolboxView.setMultiCheckBoxListener(new ToolMultiCheckBoxListener());
149 this.toolboxView.setPreset1Listener(new Preset1Listener());
150 this.toolboxView.setPreset2Listener(new Preset2Listener());
151 this.toolboxView.setPreset3Listener(new Preset3Listener());
152 this.toolboxView.setPreset4Listener(new Preset4Listener());
153 }
154 }
155
156 /**
157 * Adds the button-listeners to the {@link LevelSelectorView}.
158 */
159 private void addLevelSelectorListeners() {
160 if (this.selectorView != null) {
161 this.selectorView.setOkButtonListener(new ToolLevelOkButtonListener());
162 this.selectorView.setCancelButtonListener(new ToolLevelCancelButtonListener());
163 this.selectorView.setSelectorWindowListener(new ToolSelectorWindowSListener());
164 }
165
166 }
167
168 /**
169 * The listener which provides the handling of the applyButton.
170 * Gets the texts which were written by the user and writes them to the OSM-data.
171 * After that it checks the tagged data.
172 *
173 * @author egru
174 * @author rebsc
175 */
176 class ToolApplyButtonListener implements ActionListener {
177
178 @Override
179 public void actionPerformed(ActionEvent e) {
180
181 IndoorObject indoorObject = toolboxView.getSelectedObject();
182
183 // collecting all tags
184 List<Tag> tags = new ArrayList<>();
185 if (!toolboxView.getLevelCheckBoxStatus() && !levelValue.equals("")) {
186 tags.add(new Tag("level", levelValue));
187 }
188 if (!toolboxView.getLevelNameText().isEmpty() && !toolboxView.getLevelCheckBoxStatus()) {
189 tags.add(new Tag("level_name", toolboxView.getLevelNameText()));
190 }
191 if (!toolboxView.getNameText().isEmpty()) {
192 tags.add(new Tag("name", toolboxView.getNameText()));
193 }
194 if (!toolboxView.getRefText().isEmpty()) {
195 tags.add(new Tag("ref", toolboxView.getRefText()));
196 }
197 if (!toolboxView.getRepeatOnText().isEmpty()) {
198 tags.add(new Tag("repeat_on", toolboxView.getRepeatOnText()));
199 }
200 if (!toolboxView.getLevelNameText().isEmpty() && !toolboxView.getLevelCheckBoxStatus()) {
201 tags.add(new Tag("level_name", toolboxView.getLevelNameText()));
202 }
203
204 // Tagging to OSM Data
205 model.addTagsToOSM(indoorObject, tags);
206
207 // Reset UI elements
208 toolboxView.resetUiElements();
209
210 //Do the validation process
211 ValidateAction validateAction = new ValidateAction();
212 validateAction.doValidate(true);
213
214 refreshPresets();
215
216 }
217 }
218
219 /**
220 * The listener which is called when a new item in the object list is selected.
221 *
222 * @author egru
223 * @author rebsc
224 *
225 */
226 class ToolObjectItemListener implements ItemListener {
227
228 @Override
229 public void itemStateChanged(ItemEvent e) {
230 if (toolboxView.getSelectedObject().equals(IndoorObject.ROOM)) {
231 toolboxView.setNRUiElementsEnabled(true);
232 toolboxView.setROUiElementsEnabled(false);
233 } else if (toolboxView.getSelectedObject().equals(IndoorObject.STEPS) ||
234 toolboxView.getSelectedObject().equals(IndoorObject.ELEVATOR)) {
235 toolboxView.setROUiElementsEnabled(true);
236 toolboxView.setNRUiElementsEnabled(true);
237 } else {
238 toolboxView.setROUiElementsEnabled(false);
239 }
240 }
241 }
242
243 /**
244 * The listener which is called when the LevelCheckBox is selected.
245 *
246 * @author rebsc
247 */
248 class ToolLevelCheckBoxListener implements ItemListener {
249 @Override
250 public void itemStateChanged(ItemEvent e) {
251 if (e.getStateChange() == ItemEvent.SELECTED) {
252 toolboxView.setLVLUiElementsEnabled(false);
253 } else {
254 toolboxView.setLVLUiElementsEnabled(true);
255 }
256 }
257 }
258
259 /**
260 * The listener which is called when the helpButton got pushed.
261 *
262 * @author rebsc
263 */
264 static class ToolHelpButtonListener implements ActionListener {
265
266 @Override
267 public void actionPerformed(ActionEvent e) {
268 String topic = "Plugin/IndoorHelper";
269 //Open HelpBrowser for short description about the plugin
270 HelpBrowser.setUrlForHelpTopic(Optional.ofNullable(topic).orElse("/"));
271 }
272 }
273
274 /**
275 * The listener which is called when the addLevelButton got pushed.
276 *
277 * @author rebsc
278 */
279 class ToolAddLevelButtonListener implements ActionListener {
280
281 @Override
282 public void actionPerformed(ActionEvent e) {
283
284 if (selectorView == null) {
285 selectorView = new LevelSelectorView();
286 addLevelSelectorListeners();
287
288 //Show LevelSelectorView
289 selectorView.setVisible(true);
290 } else {
291 //Put focus back on LevelSelectorView
292 selectorView.toFront();
293 }
294
295 }
296 }
297
298 /**
299 * The listener which is called when the MultiCheckBox is selected.
300 *
301 * @author rebsc
302 */
303 class ToolMultiCheckBoxListener implements ItemListener {
304 @Override
305 public void itemStateChanged(ItemEvent e) {
306 if (e.getStateChange() == ItemEvent.SELECTED) {
307 toolboxView.setMultiUiElementsEnabled(false);
308 } else {
309 toolboxView.setMultiUiElementsEnabled(true);
310 }
311 }
312 }
313
314 /**
315 * The listener which is called when the OUTER Button got pushed.
316 *
317 * @author rebsc
318 */
319 class ToolOuterButtonListener implements ActionListener {
320
321 @Override
322 public void actionPerformed(ActionEvent e) {
323 // Select drawing action
324 map.selectMapMode(drawAction);
325
326 // For space shortcut to add the relation after spacebar got pushed {@link SpaceAction}
327 outerHelp = true;
328 innerHelp = false;
329 }
330 }
331
332 /**
333 * The listener which is called when the INNER Button got pushed.
334 *
335 * @author rebsc
336 */
337 class ToolInnerButtonListener implements ActionListener {
338 @Override
339 public void actionPerformed(ActionEvent e) {
340 // Select drawing action
341 map.selectMapMode(drawAction);
342
343 // For space shortcut to edit the relation after enter got pushed {@link SpaceAction}{@link EnterAction}
344 innerHelp = true;
345 outerHelp = false;
346
347 }
348 }
349
350 /**
351 * Listener for preset button 1.
352 * @author egru
353 *
354 */
355 class Preset1Listener implements ActionListener {
356
357 @Override
358 public void actionPerformed(ActionEvent e) {
359 model.addTagsToOSM(toolboxView.getPreset1());
360 }
361 }
362
363 /**
364 * Listener for preset button 2.
365 * @author egru
366 *
367 */
368 class Preset2Listener implements ActionListener {
369
370 @Override
371 public void actionPerformed(ActionEvent e) {
372 model.addTagsToOSM(toolboxView.getPreset2());
373 }
374 }
375
376 /**
377 * Listener for preset button 3.
378 * @author egru
379 *
380 */
381 class Preset3Listener implements ActionListener {
382
383 @Override
384 public void actionPerformed(ActionEvent e) {
385 model.addTagsToOSM(toolboxView.getPreset3());
386 }
387 }
388
389 /**
390 * Listener for preset button 4.
391 * @author egru
392 *
393 */
394 class Preset4Listener implements ActionListener {
395
396 @Override
397 public void actionPerformed(ActionEvent e) {
398 model.addTagsToOSM(toolboxView.getPreset4());
399 }
400 }
401
402 /**
403 * Updates the preset button from the current ranking.
404 */
405 private void refreshPresets() {
406 toolboxView.setPresetButtons(model.getPresetRanking());
407 }
408
409 /**
410 * Specific listener for the applyButton
411 * @author rebsc
412 *
413 */
414 class ToolLevelOkButtonListener implements ActionListener {
415
416 @Override
417 public void actionPerformed(ActionEvent e) {
418 levelHelp = true;
419
420 // Get insert level number out of SelectorView
421 if (!selectorView.getLevelNumber().equals("")) {
422 levelNum = selectorView.getLevelNumber();
423
424 //Unset visibility
425 selectorView.dispose();
426 //Select draw-action
427 map.selectMapMode(drawAction);
428
429 } else {
430 JOptionPane.showMessageDialog(null, tr("Please insert a value."), tr("Error"), JOptionPane.ERROR_MESSAGE);
431 }
432
433 selectorView = null;
434 }
435 }
436
437 /**
438 * Specific listener for the cancelButton
439 * @author rebsc
440 *
441 */
442 class ToolLevelCancelButtonListener implements ActionListener {
443
444 @Override
445 public void actionPerformed(ActionEvent e) {
446 selectorView.dispose();
447 selectorView = null;
448 }
449 }
450
451 /**
452 * General listener for LevelSelectorView window
453 * @author rebsc
454 *
455 */
456 class ToolSelectorWindowSListener implements WindowListener {
457
458 @Override
459 public void windowClosed(WindowEvent e) {
460 selectorView = null;
461 }
462
463 @Override
464 public void windowClosing(WindowEvent e) {
465 selectorView = null;
466 }
467
468 @Override
469 public void windowActivated(WindowEvent arg0) {
470 // TODO Auto-generated method stub
471
472 }
473
474 @Override
475 public void windowDeactivated(WindowEvent arg0) {
476 // TODO Auto-generated method stub
477
478 }
479
480 @Override
481 public void windowDeiconified(WindowEvent arg0) {
482 // TODO Auto-generated method stub
483
484 }
485
486 @Override
487 public void windowIconified(WindowEvent arg0) {
488 // TODO Auto-generated method stub
489
490 }
491
492 @Override
493 public void windowOpened(WindowEvent arg0) {
494 // TODO Auto-generated method stub
495
496 }
497 }
498
499 /**
500 * Shortcut for spacebar
501 * @author rebsc
502 */
503 private class SpaceAction extends AbstractAction {
504
505 private static final long serialVersionUID = 1L;
506
507 @Override
508 public void actionPerformed(ActionEvent e) {
509 if (outerHelp) {
510
511 //Create new relation and add the currently drawn object to it
512 model.addRelation("outer");
513 map.selectMapMode(selectAction);
514 outerHelp = false;
515
516 //Clear currently selection
517 MainApplication.getLayerManager().getEditDataSet().clearSelection();
518 } else if (innerHelp) {
519
520 //Save new drawn relation for adding
521 innerRelation = MainApplication.getLayerManager().getEditDataSet().getAllSelected();
522 map.selectMapMode(selectAction);
523
524 //Clear currently selection
525 MainApplication.getLayerManager().getEditDataSet().clearSelection();
526 } else if (levelHelp) {
527
528 List<Tag> tags = new ArrayList<>();
529 tags.add(new Tag("level", levelNum));
530
531 //Add level tag
532 model.addTagsToOSM(tags);
533
534 //Change action
535 map.selectMapMode(selectAction);
536 levelHelp = false;
537 }
538 }
539 }
540
541 /**
542 * Shortcut for enter
543 * @author rebsc
544 */
545 private class EnterAction extends AbstractAction {
546
547 private static final long serialVersionUID = 1L;
548
549 @Override
550 public void actionPerformed(ActionEvent e) {
551 if (innerHelp && !outerHelp) {
552 // Edit the new drawn relation member to selected relation
553 model.editRelation("inner", innerRelation);
554 innerHelp = false;
555 } else if ((innerHelp && outerHelp) || (outerHelp && !innerHelp)) {
556 JOptionPane.showMessageDialog(null,
557 tr("Please press spacebar first to add \"outer\" object to relation."), tr("Relation-Error"), JOptionPane.ERROR_MESSAGE);
558 resetHelper();
559 }
560 }
561 }
562
563 /**
564 * Function which unsets the disabled state of currently hidden and/or disabled objects which have a
565 * specific tag (key). Just unsets the disabled state if object has a tag-value which is part of the
566 * current working level.
567 *
568 * @author rebsc
569 * @param key sepcific key to unset hidden objects which contains it
570 */
571 public void unsetSpecificKeyFilter(String key) {
572
573 Collection<OsmPrimitive> p = OsmDataManager.getInstance().getEditDataSet().allPrimitives();
574 int level = Integer.parseInt(levelValue);
575
576 //Find all primitives with the specific tag and check if value is part of the current
577 //workinglevel. After that unset the disabled status.
578 for (OsmPrimitive osm: p) {
579 if ((osm.isDisabledAndHidden() || osm.isDisabled()) && osm.hasKey(key)) {
580 for (Map.Entry<String, String> e: osm.getInterestingTags().entrySet()) {
581 if (e.getKey().equals(key)) {
582 //Compare values to current working level
583 if (IndoorLevel.isPartOfWorkingLevel(e.getValue(), level)) {
584 osm.unsetDisabledState();
585 } else {
586 osm.setDisabledState(true);
587 }
588 }
589 }
590 }
591 }
592 }
593
594 /**
595 * Function which updates the current working level tag
596 *
597 * @param indoorLevel current working level
598 */
599 public void setIndoorLevel(String indoorLevel) {
600 this.toolboxView.setLevelLabel(indoorLevel);
601 }
602
603 /**
604 * Function which gets the current working level tag
605 *
606 * @param indoorLevel current working level
607 */
608 public void getIndoorLevel(String indoorLevel) {
609 levelValue = indoorLevel;
610 }
611
612 /**
613 * Function which resets the helper for relation adding
614 */
615 private void resetHelper() {
616 innerHelp = false;
617 outerHelp = false;
618 }
619
620 /**
621 * Forces JOSM to load the mappaint settings.
622 */
623 private void updateSettings() {
624 Preferences.main().init(false);
625 MapPaintStyles.readFromPreferences();
626 }
627
628 /**
629 * Enables or disables the preferences for the mapcss-style.
630 *
631 * @param enabled Activates or disables the settings.
632 */
633 private void setPluginPreferences(boolean enabled) {
634 Map<String, Setting<?>> settings = Preferences.main().getAllSettings();
635
636 MapListSetting styleMapListSetting = (MapListSetting) settings.
637 get("mappaint.style.entries");
638 List<Map<String, String>> styleMaps = new ArrayList<>();
639 if (styleMapListSetting != null) {
640 styleMaps = styleMapListSetting.getValue();
641 }
642
643 if (enabled) {
644 //set mappaint active
645
646 List<Map<String, String>> styleMapsNew = new ArrayList<>();
647 if (!styleMaps.isEmpty()) {
648 styleMapsNew.addAll(styleMaps);
649 }
650
651 for (Map<String, String> map : styleMapsNew) {
652 if (map.containsValue(tr("Indoor"))) {
653 styleMapsNew.remove(map);
654 break;
655 }
656 }
657 Map<String, String> indoorMapPaint = new HashMap<>();
658 indoorMapPaint.put("title", tr("Indoor"));
659 indoorMapPaint.put("active", "true");
660 indoorMapPaint.put("url", Config.getDirs().getUserDataDirectory(true) + sep + "styles"
661 + sep + "sit.mapcss");
662 styleMapsNew.add(indoorMapPaint);
663 Config.getPref().putListOfMaps("mappaint.style.entries", styleMapsNew);
664
665 updateSettings();
666 } else {
667 //set mappaint inactive
668
669 List<Map<String, String>> styleMapsNew = new ArrayList<>();
670 if (!styleMaps.isEmpty()) {
671 styleMapsNew.addAll(styleMaps);
672 }
673 for (Map<String, String> map : styleMapsNew) {
674 if (map.containsValue(tr("Indoor"))) {
675 styleMapsNew.remove(map);
676 break;
677 }
678 }
679 Map<String, String> indoorMapPaint = new HashMap<>();
680 indoorMapPaint.put("title", tr("Indoor"));
681 indoorMapPaint.put("active", "false");
682 indoorMapPaint.put("url", Config.getDirs().getUserDataDirectory(true) + sep + "styles"
683 + sep + "sit.mapcss");
684 styleMapsNew.add(indoorMapPaint);
685 Config.getPref().putListOfMaps("mappaint.style.entries", styleMapsNew);
686
687 updateSettings();
688 }
689 }
690}
Note: See TracBrowser for help on using the repository browser.