-
Notifications
You must be signed in to change notification settings - Fork 3
/
MapWithAIPlugin.java
210 lines (178 loc) · 9.57 KB
/
MapWithAIPlugin.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.mapwithai;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JMenuItem;
import org.openstreetmap.josm.actions.JosmAction;
import org.openstreetmap.josm.actions.PreferencesAction;
import org.openstreetmap.josm.data.validation.OsmValidator;
import org.openstreetmap.josm.data.validation.Test;
import org.openstreetmap.josm.gui.MainApplication;
import org.openstreetmap.josm.gui.MainMenu;
import org.openstreetmap.josm.gui.MapFrame;
import org.openstreetmap.josm.gui.download.DownloadDialog;
import org.openstreetmap.josm.gui.download.DownloadSelection;
import org.openstreetmap.josm.gui.download.OSMDownloadSource;
import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
import org.openstreetmap.josm.gui.util.GuiHelper;
import org.openstreetmap.josm.io.remotecontrol.RequestProcessor;
import org.openstreetmap.josm.plugins.Plugin;
import org.openstreetmap.josm.plugins.PluginInformation;
import org.openstreetmap.josm.plugins.mapwithai.backend.DownloadListener;
import org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAIAction;
import org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAIDataUtils;
import org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAILayer;
import org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAIMoveAction;
import org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAIObject;
import org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAIRemoteControl;
import org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAIUploadHook;
import org.openstreetmap.josm.plugins.mapwithai.backend.MergeDuplicateWaysAction;
import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAILayerInfo;
import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.PreConflatedDataUtils;
import org.openstreetmap.josm.plugins.mapwithai.data.validation.tests.ConnectingNodeInformationTest;
import org.openstreetmap.josm.plugins.mapwithai.data.validation.tests.RoutingIslandsTest;
import org.openstreetmap.josm.plugins.mapwithai.data.validation.tests.StreetAddressOrder;
import org.openstreetmap.josm.plugins.mapwithai.data.validation.tests.StreetAddressTest;
import org.openstreetmap.josm.plugins.mapwithai.data.validation.tests.StubEndsTest;
import org.openstreetmap.josm.plugins.mapwithai.gui.MapWithAIMenu;
import org.openstreetmap.josm.plugins.mapwithai.gui.download.MapWithAIDownloadOptions;
import org.openstreetmap.josm.plugins.mapwithai.gui.download.MapWithAIDownloadSourceType;
import org.openstreetmap.josm.plugins.mapwithai.gui.preferences.MapWithAIPreferences;
import org.openstreetmap.josm.plugins.mapwithai.spi.preferences.MapWithAIConfig;
import org.openstreetmap.josm.plugins.mapwithai.spi.preferences.MapWithAIUrls;
import org.openstreetmap.josm.plugins.mapwithai.tools.MapPaintUtils;
import org.openstreetmap.josm.plugins.mapwithai.tools.MapWithAICopyProhibit;
import org.openstreetmap.josm.spi.preferences.Config;
import org.openstreetmap.josm.tools.Destroyable;
import org.openstreetmap.josm.tools.Logging;
/**
* The POJO entry point for the plugin
*/
public final class MapWithAIPlugin extends Plugin implements Destroyable {
/** The name of the plugin */
public static final String NAME = "MapWithAI";
static final String PAINTSTYLE_PREEXISTS = NAME.concat(".paintstyleprexists");
private static String versionInfo;
private final PreferenceSetting preferenceSetting;
private final List<Destroyable> destroyables;
private final MapWithAIMenu mapwithaiMenu;
private static final Map<Class<? extends JosmAction>, Boolean> MENU_ENTRIES = new LinkedHashMap<>();
static {
MENU_ENTRIES.put(MapWithAIAction.class, false);
MENU_ENTRIES.put(MapWithAIMoveAction.class, false);
MENU_ENTRIES.put(MergeDuplicateWaysAction.class, true);
}
private static final List<Class<? extends Test>> VALIDATORS = Arrays.asList(RoutingIslandsTest.class,
ConnectingNodeInformationTest.class, StubEndsTest.class, StreetAddressTest.class, StreetAddressOrder.class);
public MapWithAIPlugin(PluginInformation info) {
super(info);
MapWithAIConfig.setUrlsProvider(MapWithAIUrls.getInstance());
preferenceSetting = new MapWithAIPreferences();
// Add MapWithAI specific menu
final var dataMenu = MainApplication.getMenu().dataMenu;
mapwithaiMenu = new MapWithAIMenu();
dataMenu.add(mapwithaiMenu);
for (final Map.Entry<Class<? extends JosmAction>, Boolean> entry : MENU_ENTRIES.entrySet()) {
if (Arrays.stream(mapwithaiMenu.getMenuComponents()).filter(JMenuItem.class::isInstance)
.map(JMenuItem.class::cast)
.noneMatch(component -> entry.getKey().equals(component.getAction().getClass()))) {
try {
MainMenu.add(mapwithaiMenu, entry.getKey().getDeclaredConstructor().newInstance(),
entry.getValue());
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
Logging.debug(e);
}
}
}
// Add the preferences last to data
final var preferenceAction = PreferencesAction.forPreferenceTab(tr("MapWithAI Preferences"),
tr("MapWithAI Preferences"), MapWithAIPreferences.class);
MainMenu.add(mapwithaiMenu, preferenceAction);
VALIDATORS.forEach(clazz -> {
if (!OsmValidator.getAllAvailableTestClasses().contains(clazz)) {
OsmValidator.addTest(clazz);
}
});
if (!Config.getPref().getKeySet().contains(PAINTSTYLE_PREEXISTS)) {
Config.getPref().putBoolean(PAINTSTYLE_PREEXISTS, MapPaintUtils.checkIfMapWithAIPaintStyleExists());
}
MapPaintUtils.addMapWithAIPaintStyles();
destroyables = new ArrayList<>();
setVersionInfo(info.localversion);
RequestProcessor.addRequestHandlerClass("mapwithai", MapWithAIRemoteControl.class);
new MapWithAIRemoteControl(); // instantiate to get action into Remote Control Preferences
destroyables.add(new MapWithAIUploadHook(info));
destroyables.add(new PreConflatedDataUtils());
mapFrameInitialized(null, MainApplication.getMap());
OSMDownloadSource.addDownloadType(new MapWithAIDownloadSourceType());
MainApplication.worker.execute(() -> UpdateProd.doProd(info.mainversion));
// Preload the MapWithAILayerInfo for the JOSM download window
// This reduces the amount of time taken for first button click by 100ms.
// Don't use the worker thread to avoid blocking user downloads
MapWithAIDataUtils.getForkJoinPool().execute(MapWithAILayerInfo::getInstance);
destroyables.add(new MapWithAICopyProhibit());
}
@Override
public void addDownloadSelection(List<DownloadSelection> list) {
// Run in EDT to avoid blocking (has to be run before MapWithAIDownloadOptions
// so its already initialized)
GuiHelper.runInEDT(MapWithAILayerInfo::getInstance);
final var mapWithAIDownloadOptions = new MapWithAIDownloadOptions();
MainApplication.worker
.execute(() -> GuiHelper.runInEDT(() -> mapWithAIDownloadOptions.addGui(DownloadDialog.getInstance())));
destroyables.add(mapWithAIDownloadOptions);
}
@Override
public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
final var mapWithAIObject = destroyables.stream().filter(MapWithAIObject.class::isInstance)
.map(MapWithAIObject.class::cast).findFirst().orElseGet(MapWithAIObject::new);
if ((oldFrame != null) && (oldFrame.statusLine != null)) {
mapWithAIObject.removeMapStatus(oldFrame.statusLine);
}
if ((newFrame != null) && (newFrame.statusLine != null)) {
mapWithAIObject.addMapStatus(newFrame.statusLine);
}
if (!destroyables.contains(mapWithAIObject)) {
destroyables.add(mapWithAIObject);
}
}
@Override
public PreferenceSetting getPreferenceSetting() {
return preferenceSetting;
}
/**
* The current version for the plugin
*
* @return The version information of the plugin
*/
public static String getVersionInfo() {
return versionInfo;
}
private static void setVersionInfo(String newVersionInfo) {
versionInfo = newVersionInfo;
}
/**
* This is so that if JOSM ever decides to support updating plugins without
* restarting, I don't have to do anything (hopefully -- I might have to change
* the interface and method). Not currently used... (October 16, 2019)
*/
@Override
public void destroy() {
MainApplication.getMenu().dataMenu.remove(this.mapwithaiMenu);
MainApplication.getLayerManager().getLayersOfType(MapWithAILayer.class)
.forEach(layer -> MainApplication.getLayerManager().removeLayer(layer));
if (!Config.getPref().getBoolean(PAINTSTYLE_PREEXISTS)) {
MapPaintUtils.removeMapWithAIPaintStyles();
}
destroyables.forEach(Destroyable::destroy);
OSMDownloadSource.removeDownloadType(OSMDownloadSource.getDownloadType(MapWithAIDownloadSourceType.class));
VALIDATORS.forEach(OsmValidator::removeTest);
DownloadListener.destroyAll();
}
}