[6380] | 1 | // License: GPL. For details, see LICENSE file.
|
---|
[626] | 2 | package org.openstreetmap.josm;
|
---|
[5670] | 3 |
|
---|
[301] | 4 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
| 5 |
|
---|
| 6 | import java.awt.Component;
|
---|
[11106] | 7 | import java.awt.GraphicsEnvironment;
|
---|
[9821] | 8 | import java.io.IOException;
|
---|
[4126] | 9 | import java.lang.ref.WeakReference;
|
---|
[6471] | 10 | import java.net.URL;
|
---|
[5481] | 11 | import java.text.MessageFormat;
|
---|
[2025] | 12 | import java.util.ArrayList;
|
---|
[301] | 13 | import java.util.Collection;
|
---|
[11986] | 14 | import java.util.Collections;
|
---|
[10044] | 15 | import java.util.EnumSet;
|
---|
[6642] | 16 | import java.util.HashMap;
|
---|
[4126] | 17 | import java.util.Iterator;
|
---|
[2025] | 18 | import java.util.List;
|
---|
[301] | 19 | import java.util.Map;
|
---|
[7083] | 20 | import java.util.Objects;
|
---|
[7434] | 21 | import java.util.Set;
|
---|
[5134] | 22 | import java.util.concurrent.Callable;
|
---|
[10212] | 23 | import java.util.concurrent.ExecutionException;
|
---|
[1465] | 24 | import java.util.concurrent.ExecutorService;
|
---|
[5134] | 25 | import java.util.concurrent.Executors;
|
---|
[2322] | 26 | import java.util.concurrent.Future;
|
---|
[301] | 27 |
|
---|
[3252] | 28 | import javax.swing.Action;
|
---|
[301] | 29 |
|
---|
[3444] | 30 | import org.openstreetmap.josm.actions.JosmAction;
|
---|
[301] | 31 | import org.openstreetmap.josm.data.Bounds;
|
---|
| 32 | import org.openstreetmap.josm.data.Preferences;
|
---|
| 33 | import org.openstreetmap.josm.data.UndoRedoHandler;
|
---|
[12735] | 34 | import org.openstreetmap.josm.data.coor.conversion.CoordinateFormatManager;
|
---|
| 35 | import org.openstreetmap.josm.data.coor.conversion.DecimalDegreesCoordinateFormat;
|
---|
| 36 | import org.openstreetmap.josm.data.coor.conversion.ICoordinateFormat;
|
---|
[301] | 37 | import org.openstreetmap.josm.data.osm.DataSet;
|
---|
[6546] | 38 | import org.openstreetmap.josm.data.osm.OsmPrimitive;
|
---|
[13023] | 39 | import org.openstreetmap.josm.data.preferences.JosmBaseDirectories;
|
---|
[301] | 40 | import org.openstreetmap.josm.data.projection.Projection;
|
---|
[4126] | 41 | import org.openstreetmap.josm.data.projection.ProjectionChangeListener;
|
---|
[12630] | 42 | import org.openstreetmap.josm.gui.MainApplication;
|
---|
[301] | 43 | import org.openstreetmap.josm.gui.MainMenu;
|
---|
[10432] | 44 | import org.openstreetmap.josm.gui.MainPanel;
|
---|
[301] | 45 | import org.openstreetmap.josm.gui.MapFrame;
|
---|
[5957] | 46 | import org.openstreetmap.josm.gui.MapFrameListener;
|
---|
[10279] | 47 | import org.openstreetmap.josm.gui.layer.MainLayerManager;
|
---|
[301] | 48 | import org.openstreetmap.josm.gui.preferences.ToolbarPreferences;
|
---|
[7185] | 49 | import org.openstreetmap.josm.io.FileWatcher;
|
---|
[7434] | 50 | import org.openstreetmap.josm.io.OnlineResource;
|
---|
[3934] | 51 | import org.openstreetmap.josm.io.OsmApi;
|
---|
[12846] | 52 | import org.openstreetmap.josm.spi.preferences.Config;
|
---|
[4126] | 53 | import org.openstreetmap.josm.tools.CheckParameterUtil;
|
---|
[301] | 54 | import org.openstreetmap.josm.tools.ImageProvider;
|
---|
[11374] | 55 | import org.openstreetmap.josm.tools.JosmRuntimeException;
|
---|
[10899] | 56 | import org.openstreetmap.josm.tools.Logging;
|
---|
[12776] | 57 | import org.openstreetmap.josm.tools.Platform;
|
---|
[1023] | 58 | import org.openstreetmap.josm.tools.PlatformHook;
|
---|
[1465] | 59 | import org.openstreetmap.josm.tools.PlatformHookOsx;
|
---|
[1023] | 60 | import org.openstreetmap.josm.tools.PlatformHookWindows;
|
---|
[1084] | 61 | import org.openstreetmap.josm.tools.Shortcut;
|
---|
[4288] | 62 | import org.openstreetmap.josm.tools.Utils;
|
---|
[11642] | 63 | import org.openstreetmap.josm.tools.bugreport.BugReport;
|
---|
[626] | 64 |
|
---|
[5829] | 65 | /**
|
---|
| 66 | * Abstract class holding various static global variables and methods used in large parts of JOSM application.
|
---|
| 67 | * @since 98
|
---|
| 68 | */
|
---|
[6883] | 69 | public abstract class Main {
|
---|
[2485] | 70 |
|
---|
[1104] | 71 | /**
|
---|
[6143] | 72 | * The JOSM website URL.
|
---|
[6897] | 73 | * @since 6897 (was public from 6143 to 6896)
|
---|
[6143] | 74 | */
|
---|
[6920] | 75 | private static final String JOSM_WEBSITE = "https://josm.openstreetmap.de";
|
---|
[6453] | 76 |
|
---|
[6143] | 77 | /**
|
---|
[6453] | 78 | * The OSM website URL.
|
---|
[6897] | 79 | * @since 6897 (was public from 6453 to 6896)
|
---|
[6453] | 80 | */
|
---|
[6920] | 81 | private static final String OSM_WEBSITE = "https://www.openstreetmap.org";
|
---|
[6453] | 82 |
|
---|
| 83 | /**
|
---|
[2343] | 84 | * Replies true if JOSM currently displays a map view. False, if it doesn't, i.e. if
|
---|
| 85 | * it only shows the MOTD panel.
|
---|
[10288] | 86 | * <p>
|
---|
| 87 | * You do not need this when accessing the layer manager. The layer manager will be empty if no map view is shown.
|
---|
[2512] | 88 | *
|
---|
[5357] | 89 | * @return <code>true</code> if JOSM currently displays a map view
|
---|
[12630] | 90 | * @deprecated use {@link org.openstreetmap.josm.gui.MainApplication#isDisplayingMapView()}
|
---|
[2343] | 91 | */
|
---|
[12630] | 92 | @Deprecated
|
---|
[6883] | 93 | public static boolean isDisplayingMapView() {
|
---|
[12631] | 94 | return MainApplication.isDisplayingMapView();
|
---|
[2343] | 95 | }
|
---|
[6070] | 96 |
|
---|
[2343] | 97 | /**
|
---|
[1104] | 98 | * Global parent component for all dialogs and message boxes
|
---|
| 99 | */
|
---|
| 100 | public static Component parent;
|
---|
[6070] | 101 |
|
---|
[1104] | 102 | /**
|
---|
| 103 | * Global application.
|
---|
| 104 | */
|
---|
[8126] | 105 | public static volatile Main main;
|
---|
[6070] | 106 |
|
---|
[1104] | 107 | /**
|
---|
| 108 | * The worker thread slave. This is for executing all long and intensive
|
---|
[12634] | 109 | * calculations. The executed runnables are guaranteed to be executed separately and sequential.
|
---|
| 110 | * @deprecated use {@link MainApplication#worker} instead
|
---|
[1104] | 111 | */
|
---|
[12634] | 112 | @Deprecated
|
---|
[12665] | 113 | public static ExecutorService worker;
|
---|
[6070] | 114 |
|
---|
[1104] | 115 | /**
|
---|
| 116 | * Global application preferences
|
---|
| 117 | */
|
---|
[13023] | 118 | public static final Preferences pref = new Preferences(JosmBaseDirectories.getInstance());
|
---|
[1814] | 119 |
|
---|
[1104] | 120 | /**
|
---|
[10975] | 121 | * The MapFrame.
|
---|
[10271] | 122 | * <p>
|
---|
[12637] | 123 | * There should be no need to access this to access any map data. Use {@link MainApplication#getLayerManager} instead.
|
---|
[10432] | 124 | *
|
---|
[12637] | 125 | * @deprecated Use {@link MainApplication#getMap()} instead
|
---|
[10432] | 126 | * @see MainPanel
|
---|
[1104] | 127 | */
|
---|
[12630] | 128 | @Deprecated
|
---|
[1104] | 129 | public static MapFrame map;
|
---|
[6070] | 130 |
|
---|
[1104] | 131 | /**
|
---|
| 132 | * The toolbar preference control to register new actions.
|
---|
[12637] | 133 | * @deprecated Use {@link MainApplication#getToolbar} instead
|
---|
[1104] | 134 | */
|
---|
[12637] | 135 | @Deprecated
|
---|
[8126] | 136 | public static volatile ToolbarPreferences toolbar;
|
---|
[626] | 137 |
|
---|
[5829] | 138 | /**
|
---|
| 139 | * The commands undo/redo handler.
|
---|
| 140 | */
|
---|
[12718] | 141 | public final UndoRedoHandler undoRedo = new UndoRedoHandler();
|
---|
[626] | 142 |
|
---|
[5831] | 143 | /**
|
---|
[1104] | 144 | * The main menu bar at top of screen.
|
---|
[12643] | 145 | * @deprecated Use {@link MainApplication#getMenu} instead
|
---|
[1104] | 146 | */
|
---|
[12643] | 147 | @Deprecated
|
---|
[5134] | 148 | public MainMenu menu;
|
---|
[626] | 149 |
|
---|
[5481] | 150 | /**
|
---|
[12125] | 151 | * The main panel.
|
---|
[12642] | 152 | * @deprecated Use {@link MainApplication#getMainPanel} instead
|
---|
[12125] | 153 | * @since 12125
|
---|
| 154 | */
|
---|
[12642] | 155 | @Deprecated
|
---|
[12125] | 156 | public MainPanel panel;
|
---|
| 157 |
|
---|
| 158 | /**
|
---|
[7185] | 159 | * The file watcher service.
|
---|
| 160 | */
|
---|
| 161 | public static final FileWatcher fileWatcher = new FileWatcher();
|
---|
| 162 |
|
---|
[11650] | 163 | private static final Map<String, Throwable> NETWORK_ERRORS = new HashMap<>();
|
---|
[6642] | 164 |
|
---|
[10044] | 165 | private static final Set<OnlineResource> OFFLINE_RESOURCES = EnumSet.noneOf(OnlineResource.class);
|
---|
[7434] | 166 |
|
---|
[1356] | 167 | /**
|
---|
[6730] | 168 | * Logging level (5 = trace, 4 = debug, 3 = info, 2 = warn, 1 = error, 0 = none).
|
---|
[6248] | 169 | * @since 6248
|
---|
[10899] | 170 | * @deprecated Use {@link Logging} class.
|
---|
[1104] | 171 | */
|
---|
[10899] | 172 | @Deprecated
|
---|
[6248] | 173 | public static int logLevel = 3;
|
---|
[6474] | 174 |
|
---|
[10432] | 175 | /**
|
---|
[8857] | 176 | * Replies the first lines of last 5 error and warning messages, used for bug reports
|
---|
| 177 | * @return the first lines of last 5 error and warning messages
|
---|
[7420] | 178 | * @since 7420
|
---|
[12620] | 179 | * @deprecated Use {@link Logging#getLastErrorAndWarnings}.
|
---|
[7420] | 180 | */
|
---|
[12620] | 181 | @Deprecated
|
---|
[7420] | 182 | public static final Collection<String> getLastErrorAndWarnings() {
|
---|
[10899] | 183 | return Logging.getLastErrorAndWarnings();
|
---|
[7420] | 184 | }
|
---|
| 185 |
|
---|
| 186 | /**
|
---|
[8959] | 187 | * Clears the list of last error and warning messages.
|
---|
| 188 | * @since 8959
|
---|
[12620] | 189 | * @deprecated Use {@link Logging#clearLastErrorAndWarnings}.
|
---|
[8959] | 190 | */
|
---|
[12620] | 191 | @Deprecated
|
---|
[8959] | 192 | public static void clearLastErrorAndWarnings() {
|
---|
[10899] | 193 | Logging.clearLastErrorAndWarnings();
|
---|
[8959] | 194 | }
|
---|
| 195 |
|
---|
| 196 | /**
|
---|
[6248] | 197 | * Prints an error message if logging is on.
|
---|
[5481] | 198 | * @param msg The message to print.
|
---|
[6248] | 199 | * @since 6248
|
---|
[12620] | 200 | * @deprecated Use {@link Logging#error(String)}.
|
---|
[5481] | 201 | */
|
---|
[12620] | 202 | @Deprecated
|
---|
[6248] | 203 | public static void error(String msg) {
|
---|
[10899] | 204 | Logging.error(msg);
|
---|
[6248] | 205 | }
|
---|
[6474] | 206 |
|
---|
[6248] | 207 | /**
|
---|
| 208 | * Prints a warning message if logging is on.
|
---|
| 209 | * @param msg The message to print.
|
---|
[12620] | 210 | * @deprecated Use {@link Logging#warn(String)}.
|
---|
[6248] | 211 | */
|
---|
[12620] | 212 | @Deprecated
|
---|
[6248] | 213 | public static void warn(String msg) {
|
---|
[10899] | 214 | Logging.warn(msg);
|
---|
[4190] | 215 | }
|
---|
[6474] | 216 |
|
---|
[5481] | 217 | /**
|
---|
[6248] | 218 | * Prints an informational message if logging is on.
|
---|
[5481] | 219 | * @param msg The message to print.
|
---|
[12620] | 220 | * @deprecated Use {@link Logging#info(String)}.
|
---|
[5481] | 221 | */
|
---|
[12620] | 222 | @Deprecated
|
---|
[6248] | 223 | public static void info(String msg) {
|
---|
[10899] | 224 | Logging.info(msg);
|
---|
[4190] | 225 | }
|
---|
[6474] | 226 |
|
---|
[5481] | 227 | /**
|
---|
[6248] | 228 | * Prints a debug message if logging is on.
|
---|
[5481] | 229 | * @param msg The message to print.
|
---|
[12620] | 230 | * @deprecated Use {@link Logging#debug(String)}.
|
---|
[5481] | 231 | */
|
---|
[12620] | 232 | @Deprecated
|
---|
[6248] | 233 | public static void debug(String msg) {
|
---|
[10899] | 234 | Logging.debug(msg);
|
---|
[1104] | 235 | }
|
---|
[6474] | 236 |
|
---|
[5481] | 237 | /**
|
---|
[6730] | 238 | * Prints a trace message if logging is on.
|
---|
| 239 | * @param msg The message to print.
|
---|
[12620] | 240 | * @deprecated Use {@link Logging#trace(String)}.
|
---|
[6730] | 241 | */
|
---|
[12620] | 242 | @Deprecated
|
---|
[6730] | 243 | public static void trace(String msg) {
|
---|
[10899] | 244 | Logging.trace(msg);
|
---|
[6730] | 245 | }
|
---|
| 246 |
|
---|
| 247 | /**
|
---|
[6852] | 248 | * Determines if debug log level is enabled.
|
---|
| 249 | * Useful to avoid costly construction of debug messages when not enabled.
|
---|
| 250 | * @return {@code true} if log level is at least debug, {@code false} otherwise
|
---|
| 251 | * @since 6852
|
---|
[12620] | 252 | * @deprecated Use {@link Logging#isDebugEnabled}.
|
---|
[6852] | 253 | */
|
---|
[12620] | 254 | @Deprecated
|
---|
[6852] | 255 | public static boolean isDebugEnabled() {
|
---|
[12620] | 256 | return Logging.isDebugEnabled();
|
---|
[6852] | 257 | }
|
---|
| 258 |
|
---|
| 259 | /**
|
---|
| 260 | * Determines if trace log level is enabled.
|
---|
| 261 | * Useful to avoid costly construction of trace messages when not enabled.
|
---|
| 262 | * @return {@code true} if log level is at least trace, {@code false} otherwise
|
---|
| 263 | * @since 6852
|
---|
[12620] | 264 | * @deprecated Use {@link Logging#isTraceEnabled}.
|
---|
[6852] | 265 | */
|
---|
[12620] | 266 | @Deprecated
|
---|
[6852] | 267 | public static boolean isTraceEnabled() {
|
---|
[12620] | 268 | return Logging.isTraceEnabled();
|
---|
[6852] | 269 | }
|
---|
| 270 |
|
---|
| 271 | /**
|
---|
[6535] | 272 | * Prints a formatted error message if logging is on. Calls {@link MessageFormat#format}
|
---|
[5481] | 273 | * function to format text.
|
---|
[6535] | 274 | * @param msg The formatted message to print.
|
---|
[5481] | 275 | * @param objects The objects to insert into format string.
|
---|
[6248] | 276 | * @since 6248
|
---|
[12620] | 277 | * @deprecated Use {@link Logging#error(String, Object...)}.
|
---|
[5481] | 278 | */
|
---|
[12620] | 279 | @Deprecated
|
---|
[6248] | 280 | public static void error(String msg, Object... objects) {
|
---|
[10899] | 281 | Logging.error(msg, objects);
|
---|
[6248] | 282 | }
|
---|
[6474] | 283 |
|
---|
[6248] | 284 | /**
|
---|
[6535] | 285 | * Prints a formatted warning message if logging is on. Calls {@link MessageFormat#format}
|
---|
[6248] | 286 | * function to format text.
|
---|
[6535] | 287 | * @param msg The formatted message to print.
|
---|
[6248] | 288 | * @param objects The objects to insert into format string.
|
---|
[12620] | 289 | * @deprecated Use {@link Logging#warn(String, Object...)}.
|
---|
[6248] | 290 | */
|
---|
[12620] | 291 | @Deprecated
|
---|
[6248] | 292 | public static void warn(String msg, Object... objects) {
|
---|
[10899] | 293 | Logging.warn(msg, objects);
|
---|
[5481] | 294 | }
|
---|
[6474] | 295 |
|
---|
[5481] | 296 | /**
|
---|
[6535] | 297 | * Prints a formatted informational message if logging is on. Calls {@link MessageFormat#format}
|
---|
[5481] | 298 | * function to format text.
|
---|
[6535] | 299 | * @param msg The formatted message to print.
|
---|
[5481] | 300 | * @param objects The objects to insert into format string.
|
---|
[12620] | 301 | * @deprecated Use {@link Logging#info(String, Object...)}.
|
---|
[5481] | 302 | */
|
---|
[12620] | 303 | @Deprecated
|
---|
[6248] | 304 | public static void info(String msg, Object... objects) {
|
---|
[10899] | 305 | Logging.info(msg, objects);
|
---|
[5481] | 306 | }
|
---|
[6474] | 307 |
|
---|
[5481] | 308 | /**
|
---|
[6535] | 309 | * Prints a formatted debug message if logging is on. Calls {@link MessageFormat#format}
|
---|
[5481] | 310 | * function to format text.
|
---|
[6535] | 311 | * @param msg The formatted message to print.
|
---|
[5481] | 312 | * @param objects The objects to insert into format string.
|
---|
[12620] | 313 | * @deprecated Use {@link Logging#debug(String, Object...)}.
|
---|
[5481] | 314 | */
|
---|
[12620] | 315 | @Deprecated
|
---|
[6248] | 316 | public static void debug(String msg, Object... objects) {
|
---|
[10899] | 317 | Logging.debug(msg, objects);
|
---|
[5481] | 318 | }
|
---|
[6474] | 319 |
|
---|
[6248] | 320 | /**
|
---|
[8015] | 321 | * Prints a formatted trace message if logging is on. Calls {@link MessageFormat#format}
|
---|
| 322 | * function to format text.
|
---|
| 323 | * @param msg The formatted message to print.
|
---|
| 324 | * @param objects The objects to insert into format string.
|
---|
[12620] | 325 | * @deprecated Use {@link Logging#trace(String, Object...)}.
|
---|
[8015] | 326 | */
|
---|
[12620] | 327 | @Deprecated
|
---|
[8015] | 328 | public static void trace(String msg, Object... objects) {
|
---|
[10899] | 329 | Logging.trace(msg, objects);
|
---|
[8015] | 330 | }
|
---|
| 331 |
|
---|
| 332 | /**
|
---|
[6248] | 333 | * Prints an error message for the given Throwable.
|
---|
| 334 | * @param t The throwable object causing the error
|
---|
| 335 | * @since 6248
|
---|
[12620] | 336 | * @deprecated Use {@link Logging#error(Throwable)}.
|
---|
[6248] | 337 | */
|
---|
[12620] | 338 | @Deprecated
|
---|
[6248] | 339 | public static void error(Throwable t) {
|
---|
[12620] | 340 | Logging.error(t);
|
---|
[6248] | 341 | }
|
---|
[6474] | 342 |
|
---|
[6248] | 343 | /**
|
---|
| 344 | * Prints a warning message for the given Throwable.
|
---|
| 345 | * @param t The throwable object causing the error
|
---|
| 346 | * @since 6248
|
---|
[12620] | 347 | * @deprecated Use {@link Logging#warn(Throwable)}.
|
---|
[6248] | 348 | */
|
---|
[12620] | 349 | @Deprecated
|
---|
[6248] | 350 | public static void warn(Throwable t) {
|
---|
[12620] | 351 | Logging.warn(t);
|
---|
[6642] | 352 | }
|
---|
| 353 |
|
---|
| 354 | /**
|
---|
[10420] | 355 | * Prints a debug message for the given Throwable. Useful for exceptions usually ignored
|
---|
| 356 | * @param t The throwable object causing the error
|
---|
[10421] | 357 | * @since 10420
|
---|
[12620] | 358 | * @deprecated Use {@link Logging#debug(Throwable)}.
|
---|
[10420] | 359 | */
|
---|
[12620] | 360 | @Deprecated
|
---|
[10420] | 361 | public static void debug(Throwable t) {
|
---|
[12620] | 362 | Logging.debug(t);
|
---|
[10420] | 363 | }
|
---|
| 364 |
|
---|
| 365 | /**
|
---|
| 366 | * Prints a trace message for the given Throwable. Useful for exceptions usually ignored
|
---|
| 367 | * @param t The throwable object causing the error
|
---|
[10421] | 368 | * @since 10420
|
---|
[12620] | 369 | * @deprecated Use {@link Logging#trace(Throwable)}.
|
---|
[10420] | 370 | */
|
---|
[12620] | 371 | @Deprecated
|
---|
[10420] | 372 | public static void trace(Throwable t) {
|
---|
[12620] | 373 | Logging.trace(t);
|
---|
[10420] | 374 | }
|
---|
| 375 |
|
---|
| 376 | /**
|
---|
[6642] | 377 | * Prints an error message for the given Throwable.
|
---|
| 378 | * @param t The throwable object causing the error
|
---|
| 379 | * @param stackTrace {@code true}, if the stacktrace should be displayed
|
---|
[6643] | 380 | * @since 6642
|
---|
[12620] | 381 | * @deprecated Use {@link Logging#log(java.util.logging.Level, Throwable)}
|
---|
| 382 | * or {@link Logging#logWithStackTrace(java.util.logging.Level, Throwable)}.
|
---|
[6642] | 383 | */
|
---|
[12620] | 384 | @Deprecated
|
---|
[6642] | 385 | public static void error(Throwable t, boolean stackTrace) {
|
---|
| 386 | if (stackTrace) {
|
---|
[10899] | 387 | Logging.log(Logging.LEVEL_ERROR, t);
|
---|
| 388 | } else {
|
---|
| 389 | Logging.logWithStackTrace(Logging.LEVEL_ERROR, t);
|
---|
[6642] | 390 | }
|
---|
| 391 | }
|
---|
| 392 |
|
---|
| 393 | /**
|
---|
[10420] | 394 | * Prints an error message for the given Throwable.
|
---|
| 395 | * @param t The throwable object causing the error
|
---|
| 396 | * @param message additional error message
|
---|
[10421] | 397 | * @since 10420
|
---|
[12620] | 398 | * @deprecated Use {@link Logging#log(java.util.logging.Level, String, Throwable)}.
|
---|
[10420] | 399 | */
|
---|
[12620] | 400 | @Deprecated
|
---|
[10420] | 401 | public static void error(Throwable t, String message) {
|
---|
[10899] | 402 | Logging.log(Logging.LEVEL_ERROR, message, t);
|
---|
[10420] | 403 | }
|
---|
| 404 |
|
---|
| 405 | /**
|
---|
[6642] | 406 | * Prints a warning message for the given Throwable.
|
---|
| 407 | * @param t The throwable object causing the error
|
---|
| 408 | * @param stackTrace {@code true}, if the stacktrace should be displayed
|
---|
[6643] | 409 | * @since 6642
|
---|
[12620] | 410 | * @deprecated Use {@link Logging#log(java.util.logging.Level, Throwable)}
|
---|
| 411 | * or {@link Logging#logWithStackTrace(java.util.logging.Level, Throwable)}.
|
---|
[6642] | 412 | */
|
---|
[12620] | 413 | @Deprecated
|
---|
[6642] | 414 | public static void warn(Throwable t, boolean stackTrace) {
|
---|
| 415 | if (stackTrace) {
|
---|
[10899] | 416 | Logging.log(Logging.LEVEL_WARN, t);
|
---|
| 417 | } else {
|
---|
| 418 | Logging.logWithStackTrace(Logging.LEVEL_WARN, t);
|
---|
[6642] | 419 | }
|
---|
[6248] | 420 | }
|
---|
[6474] | 421 |
|
---|
[6642] | 422 | /**
|
---|
[10420] | 423 | * Prints a warning message for the given Throwable.
|
---|
| 424 | * @param t The throwable object causing the error
|
---|
| 425 | * @param message additional error message
|
---|
[10421] | 426 | * @since 10420
|
---|
[12620] | 427 | * @deprecated Use {@link Logging#log(java.util.logging.Level, String, Throwable)}.
|
---|
[10420] | 428 | */
|
---|
[12620] | 429 | @Deprecated
|
---|
[10420] | 430 | public static void warn(Throwable t, String message) {
|
---|
[10899] | 431 | Logging.log(Logging.LEVEL_WARN, message, t);
|
---|
[10420] | 432 | }
|
---|
| 433 |
|
---|
| 434 | /**
|
---|
[6642] | 435 | * Returns a human-readable message of error, also usable for developers.
|
---|
| 436 | * @param t The error
|
---|
| 437 | * @return The human-readable error message
|
---|
| 438 | * @since 6642
|
---|
[12620] | 439 | * @deprecated Use {@link Logging#getErrorMessage}.
|
---|
[6642] | 440 | */
|
---|
[12620] | 441 | @Deprecated
|
---|
[6642] | 442 | public static String getErrorMessage(Throwable t) {
|
---|
[6783] | 443 | if (t == null) {
|
---|
| 444 | return null;
|
---|
[10899] | 445 | } else {
|
---|
| 446 | return Logging.getErrorMessage(t);
|
---|
[6783] | 447 | }
|
---|
[6311] | 448 | }
|
---|
[301] | 449 |
|
---|
[1104] | 450 | /**
|
---|
| 451 | * Platform specific code goes in here.
|
---|
[12641] | 452 | * Plugins may replace it, however, some hooks will be called before any plugins have been loaded.
|
---|
[1104] | 453 | * So if you need to hook into those early ones, split your class and send the one with the early hooks
|
---|
| 454 | * to the JOSM team for inclusion.
|
---|
| 455 | */
|
---|
[8126] | 456 | public static volatile PlatformHook platform;
|
---|
[1023] | 457 |
|
---|
[8840] | 458 | private static volatile InitStatusListener initListener;
|
---|
[4681] | 459 |
|
---|
[11352] | 460 | /**
|
---|
| 461 | * Initialization task listener.
|
---|
| 462 | */
|
---|
[8512] | 463 | public interface InitStatusListener {
|
---|
[4681] | 464 |
|
---|
[11352] | 465 | /**
|
---|
| 466 | * Called when an initialization task updates its status.
|
---|
| 467 | * @param event task name
|
---|
| 468 | * @return new status
|
---|
| 469 | */
|
---|
[8497] | 470 | Object updateStatus(String event);
|
---|
[8510] | 471 |
|
---|
[11352] | 472 | /**
|
---|
| 473 | * Called when an initialization task completes.
|
---|
| 474 | * @param status final status
|
---|
| 475 | */
|
---|
[8497] | 476 | void finish(Object status);
|
---|
[4681] | 477 | }
|
---|
| 478 |
|
---|
[11352] | 479 | /**
|
---|
| 480 | * Sets initialization task listener.
|
---|
| 481 | * @param listener initialization task listener
|
---|
| 482 | */
|
---|
[4681] | 483 | public static void setInitStatusListener(InitStatusListener listener) {
|
---|
[8497] | 484 | CheckParameterUtil.ensureParameterNotNull(listener);
|
---|
[4681] | 485 | initListener = listener;
|
---|
| 486 | }
|
---|
| 487 |
|
---|
[6523] | 488 | /**
|
---|
[10340] | 489 | * Constructs new {@code Main} object.
|
---|
| 490 | * @see #initialize()
|
---|
[6523] | 491 | */
|
---|
[11656] | 492 | protected Main() {
|
---|
| 493 | setInstance(this);
|
---|
[10340] | 494 | }
|
---|
| 495 |
|
---|
[11656] | 496 | private static void setInstance(Main instance) {
|
---|
| 497 | main = instance;
|
---|
| 498 | }
|
---|
| 499 |
|
---|
[10340] | 500 | /**
|
---|
| 501 | * Initializes the main object. A lot of global variables are initialized here.
|
---|
| 502 | * @since 10340
|
---|
| 503 | */
|
---|
| 504 | public void initialize() {
|
---|
[12629] | 505 | // Initializes tasks that must be run before parallel tasks
|
---|
| 506 | runInitializationTasks(beforeInitializationTasks());
|
---|
[4681] | 507 |
|
---|
[12629] | 508 | // Initializes tasks to be executed (in parallel) by a ExecutorService
|
---|
[11642] | 509 | try {
|
---|
[10899] | 510 | ExecutorService service = Executors.newFixedThreadPool(
|
---|
[8734] | 511 | Runtime.getRuntime().availableProcessors(), Utils.newThreadFactory("main-init-%d", Thread.NORM_PRIORITY));
|
---|
[12629] | 512 | for (Future<Void> i : service.invokeAll(parallelInitializationTasks())) {
|
---|
[5195] | 513 | i.get();
|
---|
| 514 | }
|
---|
[11092] | 515 | // asynchronous initializations to be completed eventually
|
---|
[12629] | 516 | asynchronousRunnableTasks().forEach(service::submit);
|
---|
| 517 | asynchronousCallableTasks().forEach(service::submit);
|
---|
[8738] | 518 | service.shutdown();
|
---|
[10212] | 519 | } catch (InterruptedException | ExecutionException ex) {
|
---|
[11374] | 520 | throw new JosmRuntimeException(ex);
|
---|
[4718] | 521 | }
|
---|
[3669] | 522 |
|
---|
[12629] | 523 | // Initializes tasks that must be run after parallel tasks
|
---|
| 524 | runInitializationTasks(afterInitializationTasks());
|
---|
| 525 | }
|
---|
[4489] | 526 |
|
---|
[12629] | 527 | private static void runInitializationTasks(List<InitializationTask> tasks) {
|
---|
| 528 | for (InitializationTask task : tasks) {
|
---|
| 529 | try {
|
---|
| 530 | task.call();
|
---|
| 531 | } catch (JosmRuntimeException e) {
|
---|
| 532 | // Can happen if the current projection needs NTV2 grid which is not available
|
---|
| 533 | // In this case we want the user be able to change his projection
|
---|
| 534 | BugReport.intercept(e).warn();
|
---|
| 535 | }
|
---|
| 536 | }
|
---|
[1104] | 537 | }
|
---|
[626] | 538 |
|
---|
[10340] | 539 | /**
|
---|
[12629] | 540 | * Returns tasks that must be run before parallel tasks.
|
---|
| 541 | * @return tasks that must be run before parallel tasks
|
---|
| 542 | * @see #afterInitializationTasks
|
---|
| 543 | * @see #parallelInitializationTasks
|
---|
| 544 | */
|
---|
| 545 | protected List<InitializationTask> beforeInitializationTasks() {
|
---|
| 546 | return Collections.emptyList();
|
---|
| 547 | }
|
---|
| 548 |
|
---|
| 549 | /**
|
---|
| 550 | * Returns tasks to be executed (in parallel) by a ExecutorService.
|
---|
| 551 | * @return tasks to be executed (in parallel) by a ExecutorService
|
---|
| 552 | */
|
---|
| 553 | protected Collection<InitializationTask> parallelInitializationTasks() {
|
---|
| 554 | return Collections.emptyList();
|
---|
| 555 | }
|
---|
| 556 |
|
---|
| 557 | /**
|
---|
| 558 | * Returns asynchronous callable initializations to be completed eventually
|
---|
| 559 | * @return asynchronous callable initializations to be completed eventually
|
---|
| 560 | */
|
---|
| 561 | protected List<Callable<?>> asynchronousCallableTasks() {
|
---|
| 562 | return Collections.emptyList();
|
---|
| 563 | }
|
---|
| 564 |
|
---|
| 565 | /**
|
---|
| 566 | * Returns asynchronous runnable initializations to be completed eventually
|
---|
| 567 | * @return asynchronous runnable initializations to be completed eventually
|
---|
| 568 | */
|
---|
| 569 | protected List<Runnable> asynchronousRunnableTasks() {
|
---|
| 570 | return Collections.emptyList();
|
---|
| 571 | }
|
---|
| 572 |
|
---|
| 573 | /**
|
---|
| 574 | * Returns tasks that must be run after parallel tasks.
|
---|
| 575 | * @return tasks that must be run after parallel tasks
|
---|
| 576 | * @see #beforeInitializationTasks
|
---|
| 577 | * @see #parallelInitializationTasks
|
---|
| 578 | */
|
---|
| 579 | protected List<InitializationTask> afterInitializationTasks() {
|
---|
| 580 | return Collections.emptyList();
|
---|
| 581 | }
|
---|
| 582 |
|
---|
| 583 | protected static final class InitializationTask implements Callable<Void> {
|
---|
[6779] | 584 |
|
---|
| 585 | private final String name;
|
---|
[10936] | 586 | private final Runnable task;
|
---|
[6779] | 587 |
|
---|
[12629] | 588 | /**
|
---|
| 589 | * Constructs a new {@code InitializationTask}.
|
---|
| 590 | * @param name translated name to be displayed to user
|
---|
| 591 | * @param task runnable initialization task
|
---|
| 592 | */
|
---|
| 593 | public InitializationTask(String name, Runnable task) {
|
---|
[6779] | 594 | this.name = name;
|
---|
[10899] | 595 | this.task = task;
|
---|
[6779] | 596 | }
|
---|
| 597 |
|
---|
| 598 | @Override
|
---|
[8497] | 599 | public Void call() {
|
---|
| 600 | Object status = null;
|
---|
[6779] | 601 | if (initListener != null) {
|
---|
[8497] | 602 | status = initListener.updateStatus(name);
|
---|
[6779] | 603 | }
|
---|
[10899] | 604 | task.run();
|
---|
[8497] | 605 | if (initListener != null) {
|
---|
| 606 | initListener.finish(status);
|
---|
[6852] | 607 | }
|
---|
[6779] | 608 | return null;
|
---|
| 609 | }
|
---|
| 610 | }
|
---|
| 611 |
|
---|
[1104] | 612 | /**
|
---|
[10271] | 613 | * Returns the main layer manager that is used by the map view.
|
---|
| 614 | * @return The layer manager. The value returned will never change.
|
---|
[10279] | 615 | * @since 10279
|
---|
[12636] | 616 | * @deprecated use {@link MainApplication#getLayerManager} instead
|
---|
[10271] | 617 | */
|
---|
[12636] | 618 | @Deprecated
|
---|
[10279] | 619 | public static MainLayerManager getLayerManager() {
|
---|
[12636] | 620 | return MainApplication.getLayerManager();
|
---|
[10271] | 621 | }
|
---|
| 622 |
|
---|
| 623 | /**
|
---|
[6546] | 624 | * Replies the current selected primitives, from a end-user point of view.
|
---|
| 625 | * It is not always technically the same collection of primitives than {@link DataSet#getSelected()}.
|
---|
| 626 | * @return The current selected primitives, from a end-user point of view. Can be {@code null}.
|
---|
| 627 | * @since 6546
|
---|
| 628 | */
|
---|
| 629 | public Collection<OsmPrimitive> getInProgressSelection() {
|
---|
[12636] | 630 | return Collections.emptyList();
|
---|
[6546] | 631 | }
|
---|
[1750] | 632 |
|
---|
[11352] | 633 | /**
|
---|
[12718] | 634 | * Gets the active edit data set.
|
---|
| 635 | * @return That data set, <code>null</code>.
|
---|
[12691] | 636 | * @since 12691
|
---|
| 637 | */
|
---|
[12718] | 638 | public abstract DataSet getEditDataSet();
|
---|
[12691] | 639 |
|
---|
| 640 | /**
|
---|
[12718] | 641 | * Sets the active data set.
|
---|
| 642 | * @param ds New edit data set, or <code>null</code>
|
---|
| 643 | * @since 12718
|
---|
| 644 | */
|
---|
| 645 | public abstract void setEditDataSet(DataSet ds);
|
---|
| 646 |
|
---|
| 647 | /**
|
---|
| 648 | * Determines if the list of data sets managed by JOSM contains {@code ds}.
|
---|
| 649 | * @param ds the data set to look for
|
---|
| 650 | * @return {@code true} if the list of data sets managed by JOSM contains {@code ds}
|
---|
| 651 | * @since 12718
|
---|
| 652 | */
|
---|
| 653 | public abstract boolean containsDataSet(DataSet ds);
|
---|
| 654 |
|
---|
| 655 | /**
|
---|
[11352] | 656 | * Registers a {@code JosmAction} and its shortcut.
|
---|
| 657 | * @param action action defining its own shortcut
|
---|
[12639] | 658 | * @deprecated use {@link MainApplication#registerActionShortcut(JosmAction)} instead
|
---|
[11352] | 659 | */
|
---|
[12639] | 660 | @Deprecated
|
---|
[5278] | 661 | public static void registerActionShortcut(JosmAction action) {
|
---|
[12639] | 662 | MainApplication.registerActionShortcut(action);
|
---|
[5278] | 663 | }
|
---|
| 664 |
|
---|
[11352] | 665 | /**
|
---|
| 666 | * Registers an action and its shortcut.
|
---|
| 667 | * @param action action to register
|
---|
| 668 | * @param shortcut shortcut to associate to {@code action}
|
---|
[12639] | 669 | * @deprecated use {@link MainApplication#registerActionShortcut(Action, Shortcut)} instead
|
---|
[11352] | 670 | */
|
---|
[12639] | 671 | @Deprecated
|
---|
[3252] | 672 | public static void registerActionShortcut(Action action, Shortcut shortcut) {
|
---|
[12639] | 673 | MainApplication.registerActionShortcut(action, shortcut);
|
---|
[3252] | 674 | }
|
---|
| 675 |
|
---|
[11352] | 676 | /**
|
---|
| 677 | * Unregisters a shortcut.
|
---|
| 678 | * @param shortcut shortcut to unregister
|
---|
[12639] | 679 | * @deprecated use {@link MainApplication#unregisterShortcut(Shortcut)} instead
|
---|
[11352] | 680 | */
|
---|
[12639] | 681 | @Deprecated
|
---|
[5382] | 682 | public static void unregisterShortcut(Shortcut shortcut) {
|
---|
[12639] | 683 | MainApplication.unregisterShortcut(shortcut);
|
---|
[3252] | 684 | }
|
---|
| 685 |
|
---|
[11352] | 686 | /**
|
---|
| 687 | * Unregisters a {@code JosmAction} and its shortcut.
|
---|
| 688 | * @param action action to unregister
|
---|
[12639] | 689 | * @deprecated use {@link MainApplication#unregisterActionShortcut(JosmAction)} instead
|
---|
[11352] | 690 | */
|
---|
[12639] | 691 | @Deprecated
|
---|
[3444] | 692 | public static void unregisterActionShortcut(JosmAction action) {
|
---|
[12639] | 693 | MainApplication.unregisterActionShortcut(action);
|
---|
[3444] | 694 | }
|
---|
| 695 |
|
---|
[11352] | 696 | /**
|
---|
| 697 | * Unregisters an action and its shortcut.
|
---|
| 698 | * @param action action to unregister
|
---|
| 699 | * @param shortcut shortcut to unregister
|
---|
[12639] | 700 | * @deprecated use {@link MainApplication#unregisterActionShortcut(Action, Shortcut)} instead
|
---|
[11352] | 701 | */
|
---|
[12639] | 702 | @Deprecated
|
---|
[3444] | 703 | public static void unregisterActionShortcut(Action action, Shortcut shortcut) {
|
---|
[12639] | 704 | MainApplication.unregisterActionShortcut(action, shortcut);
|
---|
[3444] | 705 | }
|
---|
[6070] | 706 |
|
---|
[5696] | 707 | /**
|
---|
| 708 | * Replies the registered action for the given shortcut
|
---|
| 709 | * @param shortcut The shortcut to look for
|
---|
| 710 | * @return the registered action for the given shortcut
|
---|
[12639] | 711 | * @deprecated use {@link MainApplication#getRegisteredActionShortcut(Shortcut)} instead
|
---|
[5696] | 712 | * @since 5696
|
---|
| 713 | */
|
---|
[12639] | 714 | @Deprecated
|
---|
[5696] | 715 | public static Action getRegisteredActionShortcut(Shortcut shortcut) {
|
---|
[12639] | 716 | return MainApplication.getRegisteredActionShortcut(shortcut);
|
---|
[5696] | 717 | }
|
---|
[3444] | 718 |
|
---|
[1104] | 719 | ///////////////////////////////////////////////////////////////////////////
|
---|
| 720 | // Implementation part
|
---|
| 721 | ///////////////////////////////////////////////////////////////////////////
|
---|
[626] | 722 |
|
---|
[5829] | 723 | /**
|
---|
[1104] | 724 | * Should be called before the main constructor to setup some parameter stuff
|
---|
| 725 | */
|
---|
[10962] | 726 | public static void preConstructorInit() {
|
---|
[1990] | 727 | // init default coordinate format
|
---|
[12846] | 728 | ICoordinateFormat fmt = CoordinateFormatManager.getCoordinateFormat(Config.getPref().get("coordinates"));
|
---|
[12735] | 729 | if (fmt == null) {
|
---|
| 730 | fmt = DecimalDegreesCoordinateFormat.INSTANCE;
|
---|
[1990] | 731 | }
|
---|
[12735] | 732 | CoordinateFormatManager.setCoordinateFormat(fmt);
|
---|
[1104] | 733 | }
|
---|
[626] | 734 |
|
---|
[11986] | 735 | /**
|
---|
[8412] | 736 | * Closes JOSM and optionally terminates the Java Virtual Machine (JVM).
|
---|
[6342] | 737 | * @param exit If {@code true}, the JVM is terminated by running {@link System#exit} with a given return code.
|
---|
| 738 | * @param exitCode The return code
|
---|
[12636] | 739 | * @return {@code true}
|
---|
| 740 | * @since 12636
|
---|
[5829] | 741 | */
|
---|
[12636] | 742 | public static boolean exitJosm(boolean exit, int exitCode) {
|
---|
| 743 | if (Main.main != null) {
|
---|
| 744 | Main.main.shutdown();
|
---|
| 745 | }
|
---|
[8412] | 746 |
|
---|
[12636] | 747 | if (exit) {
|
---|
| 748 | System.exit(exitCode);
|
---|
[5829] | 749 | }
|
---|
[12636] | 750 | return true;
|
---|
[3378] | 751 | }
|
---|
| 752 |
|
---|
[11986] | 753 | /**
|
---|
| 754 | * Shutdown JOSM.
|
---|
| 755 | */
|
---|
[10340] | 756 | protected void shutdown() {
|
---|
[11106] | 757 | if (!GraphicsEnvironment.isHeadless()) {
|
---|
| 758 | ImageProvider.shutdown(false);
|
---|
| 759 | }
|
---|
[10340] | 760 | try {
|
---|
| 761 | pref.saveDefaults();
|
---|
| 762 | } catch (IOException ex) {
|
---|
[12620] | 763 | Logging.log(Logging.LEVEL_WARN, tr("Failed to save default preferences."), ex);
|
---|
[10340] | 764 | }
|
---|
[11106] | 765 | if (!GraphicsEnvironment.isHeadless()) {
|
---|
| 766 | ImageProvider.shutdown(true);
|
---|
| 767 | }
|
---|
[10340] | 768 | }
|
---|
| 769 |
|
---|
[2798] | 770 | /**
|
---|
[5829] | 771 | * Identifies the current operating system family and initializes the platform hook accordingly.
|
---|
| 772 | * @since 1849
|
---|
| 773 | */
|
---|
[1849] | 774 | public static void determinePlatformHook() {
|
---|
[12776] | 775 | platform = Platform.determinePlatform().accept(PlatformHook.CONSTRUCT_FROM_PLATFORM);
|
---|
[1104] | 776 | }
|
---|
[1023] | 777 |
|
---|
[4126] | 778 | /* ----------------------------------------------------------------------------------------- */
|
---|
| 779 | /* projection handling - Main is a registry for a single, global projection instance */
|
---|
| 780 | /* */
|
---|
| 781 | /* TODO: For historical reasons the registry is implemented by Main. An alternative approach */
|
---|
| 782 | /* would be a singleton org.openstreetmap.josm.data.projection.ProjectionRegistry class. */
|
---|
| 783 | /* ----------------------------------------------------------------------------------------- */
|
---|
| 784 | /**
|
---|
| 785 | * The projection method used.
|
---|
[12631] | 786 | * Use {@link #getProjection()} and {@link #setProjection(Projection)} for access.
|
---|
[4897] | 787 | * Use {@link #setProjection(Projection)} in order to trigger a projection change event.
|
---|
[4126] | 788 | */
|
---|
[8126] | 789 | private static volatile Projection proj;
|
---|
[4126] | 790 |
|
---|
| 791 | /**
|
---|
| 792 | * Replies the current projection.
|
---|
[4489] | 793 | *
|
---|
[5357] | 794 | * @return the currently active projection
|
---|
[4126] | 795 | */
|
---|
| 796 | public static Projection getProjection() {
|
---|
| 797 | return proj;
|
---|
| 798 | }
|
---|
| 799 |
|
---|
| 800 | /**
|
---|
| 801 | * Sets the current projection
|
---|
[4489] | 802 | *
|
---|
[4126] | 803 | * @param p the projection
|
---|
| 804 | */
|
---|
| 805 | public static void setProjection(Projection p) {
|
---|
| 806 | CheckParameterUtil.ensureParameterNotNull(p);
|
---|
| 807 | Projection oldValue = proj;
|
---|
[12631] | 808 | Bounds b = main != null ? main.getRealBounds() : null;
|
---|
[4126] | 809 | proj = p;
|
---|
[5234] | 810 | fireProjectionChanged(oldValue, proj, b);
|
---|
[4126] | 811 | }
|
---|
| 812 |
|
---|
[12631] | 813 | /**
|
---|
| 814 | * Returns the bounds for the current projection. Used for projection events.
|
---|
| 815 | * @return the bounds for the current projection
|
---|
| 816 | * @see #restoreOldBounds
|
---|
| 817 | */
|
---|
| 818 | protected Bounds getRealBounds() {
|
---|
| 819 | // To be overriden
|
---|
| 820 | return null;
|
---|
| 821 | }
|
---|
| 822 |
|
---|
| 823 | /**
|
---|
| 824 | * Restore clean state corresponding to old bounds after a projection change event.
|
---|
| 825 | * @param oldBounds bounds previously returned by {@link #getRealBounds}, before the change of projection
|
---|
| 826 | * @see #getRealBounds
|
---|
| 827 | */
|
---|
| 828 | protected void restoreOldBounds(Bounds oldBounds) {
|
---|
| 829 | // To be overriden
|
---|
| 830 | }
|
---|
| 831 |
|
---|
[4126] | 832 | /*
|
---|
| 833 | * Keep WeakReferences to the listeners. This relieves clients from the burden of
|
---|
| 834 | * explicitly removing the listeners and allows us to transparently register every
|
---|
| 835 | * created dataset as projection change listener.
|
---|
| 836 | */
|
---|
[7005] | 837 | private static final List<WeakReference<ProjectionChangeListener>> listeners = new ArrayList<>();
|
---|
[4126] | 838 |
|
---|
[5234] | 839 | private static void fireProjectionChanged(Projection oldValue, Projection newValue, Bounds oldBounds) {
|
---|
[10655] | 840 | if ((newValue == null ^ oldValue == null)
|
---|
[7083] | 841 | || (newValue != null && oldValue != null && !Objects.equals(newValue.toCode(), oldValue.toCode()))) {
|
---|
[8510] | 842 | synchronized (Main.class) {
|
---|
[4126] | 843 | Iterator<WeakReference<ProjectionChangeListener>> it = listeners.iterator();
|
---|
[8510] | 844 | while (it.hasNext()) {
|
---|
[4126] | 845 | WeakReference<ProjectionChangeListener> wr = it.next();
|
---|
[4724] | 846 | ProjectionChangeListener listener = wr.get();
|
---|
| 847 | if (listener == null) {
|
---|
[4126] | 848 | it.remove();
|
---|
| 849 | continue;
|
---|
| 850 | }
|
---|
[4724] | 851 | listener.projectionChanged(oldValue, newValue);
|
---|
[4126] | 852 | }
|
---|
| 853 | }
|
---|
[12631] | 854 | if (newValue != null && oldBounds != null && main != null) {
|
---|
| 855 | main.restoreOldBounds(oldBounds);
|
---|
[4126] | 856 | }
|
---|
| 857 | /* TODO - remove layers with fixed projection */
|
---|
| 858 | }
|
---|
| 859 | }
|
---|
| 860 |
|
---|
| 861 | /**
|
---|
[5538] | 862 | * Register a projection change listener.
|
---|
[12119] | 863 | * The listener is registered to be weak, so keep a reference of it if you want it to be preserved.
|
---|
[4489] | 864 | *
|
---|
[5357] | 865 | * @param listener the listener. Ignored if <code>null</code>.
|
---|
[4126] | 866 | */
|
---|
| 867 | public static void addProjectionChangeListener(ProjectionChangeListener listener) {
|
---|
| 868 | if (listener == null) return;
|
---|
| 869 | synchronized (Main.class) {
|
---|
| 870 | for (WeakReference<ProjectionChangeListener> wr : listeners) {
|
---|
| 871 | // already registered ? => abort
|
---|
| 872 | if (wr.get() == listener) return;
|
---|
| 873 | }
|
---|
[7005] | 874 | listeners.add(new WeakReference<>(listener));
|
---|
[4126] | 875 | }
|
---|
| 876 | }
|
---|
| 877 |
|
---|
| 878 | /**
|
---|
[5538] | 879 | * Removes a projection change listener.
|
---|
[4489] | 880 | *
|
---|
[5357] | 881 | * @param listener the listener. Ignored if <code>null</code>.
|
---|
[4126] | 882 | */
|
---|
| 883 | public static void removeProjectionChangeListener(ProjectionChangeListener listener) {
|
---|
| 884 | if (listener == null) return;
|
---|
[8510] | 885 | synchronized (Main.class) {
|
---|
[11339] | 886 | // remove the listener - and any other listener which got garbage
|
---|
| 887 | // collected in the meantime
|
---|
| 888 | listeners.removeIf(wr -> wr.get() == null || wr.get() == listener);
|
---|
[4126] | 889 | }
|
---|
| 890 | }
|
---|
[5538] | 891 |
|
---|
| 892 | /**
|
---|
| 893 | * Listener for window switch events.
|
---|
[6070] | 894 | *
|
---|
[5538] | 895 | * These are events, when the user activates a window of another application
|
---|
| 896 | * or comes back to JOSM. Window switches from one JOSM window to another
|
---|
| 897 | * are not reported.
|
---|
| 898 | */
|
---|
[8512] | 899 | public interface WindowSwitchListener {
|
---|
[5538] | 900 | /**
|
---|
| 901 | * Called when the user activates a window of another application.
|
---|
| 902 | */
|
---|
| 903 | void toOtherApplication();
|
---|
[9059] | 904 |
|
---|
[5538] | 905 | /**
|
---|
[9059] | 906 | * Called when the user comes from a window of another application back to JOSM.
|
---|
[5538] | 907 | */
|
---|
| 908 | void fromOtherApplication();
|
---|
| 909 | }
|
---|
| 910 |
|
---|
| 911 | /**
|
---|
[11904] | 912 | * Registers a new {@code MapFrameListener} that will be notified of MapFrame changes.
|
---|
| 913 | * <p>
|
---|
| 914 | * It will fire an initial mapFrameInitialized event when the MapFrame is present.
|
---|
| 915 | * Otherwise will only fire when the MapFrame is created or destroyed.
|
---|
[5957] | 916 | * @param listener The MapFrameListener
|
---|
| 917 | * @return {@code true} if the listeners collection changed as a result of the call
|
---|
[11904] | 918 | * @see #addMapFrameListener
|
---|
[12639] | 919 | * @deprecated use {@link MainApplication#addAndFireMapFrameListener} instead
|
---|
[11904] | 920 | * @since 11904
|
---|
[8020] | 921 | */
|
---|
[12639] | 922 | @Deprecated
|
---|
[11904] | 923 | public static boolean addAndFireMapFrameListener(MapFrameListener listener) {
|
---|
[12639] | 924 | return MainApplication.addAndFireMapFrameListener(listener);
|
---|
[8020] | 925 | }
|
---|
| 926 |
|
---|
| 927 | /**
|
---|
| 928 | * Registers a new {@code MapFrameListener} that will be notified of MapFrame changes
|
---|
| 929 | * @param listener The MapFrameListener
|
---|
| 930 | * @return {@code true} if the listeners collection changed as a result of the call
|
---|
[11904] | 931 | * @see #addAndFireMapFrameListener
|
---|
[12639] | 932 | * @deprecated use {@link MainApplication#addMapFrameListener} instead
|
---|
[5957] | 933 | * @since 5957
|
---|
| 934 | */
|
---|
[12639] | 935 | @Deprecated
|
---|
[5957] | 936 | public static boolean addMapFrameListener(MapFrameListener listener) {
|
---|
[12639] | 937 | return MainApplication.addMapFrameListener(listener);
|
---|
[5957] | 938 | }
|
---|
| 939 |
|
---|
| 940 | /**
|
---|
| 941 | * Unregisters the given {@code MapFrameListener} from MapFrame changes
|
---|
| 942 | * @param listener The MapFrameListener
|
---|
| 943 | * @return {@code true} if the listeners collection changed as a result of the call
|
---|
[12639] | 944 | * @deprecated use {@link MainApplication#removeMapFrameListener} instead
|
---|
[5957] | 945 | * @since 5957
|
---|
| 946 | */
|
---|
[12639] | 947 | @Deprecated
|
---|
[5957] | 948 | public static boolean removeMapFrameListener(MapFrameListener listener) {
|
---|
[12639] | 949 | return MainApplication.removeMapFrameListener(listener);
|
---|
[5957] | 950 | }
|
---|
[6642] | 951 |
|
---|
| 952 | /**
|
---|
| 953 | * Adds a new network error that occur to give a hint about broken Internet connection.
|
---|
| 954 | * Do not use this method for errors known for sure thrown because of a bad proxy configuration.
|
---|
[6852] | 955 | *
|
---|
[6642] | 956 | * @param url The accessed URL that caused the error
|
---|
| 957 | * @param t The network error
|
---|
| 958 | * @return The previous error associated to the given resource, if any. Can be {@code null}
|
---|
[6643] | 959 | * @since 6642
|
---|
[6642] | 960 | */
|
---|
| 961 | public static Throwable addNetworkError(URL url, Throwable t) {
|
---|
| 962 | if (url != null && t != null) {
|
---|
| 963 | Throwable old = addNetworkError(url.toExternalForm(), t);
|
---|
| 964 | if (old != null) {
|
---|
[12620] | 965 | Logging.warn("Already here "+old);
|
---|
[6642] | 966 | }
|
---|
| 967 | return old;
|
---|
| 968 | }
|
---|
| 969 | return null;
|
---|
| 970 | }
|
---|
| 971 |
|
---|
| 972 | /**
|
---|
| 973 | * Adds a new network error that occur to give a hint about broken Internet connection.
|
---|
| 974 | * Do not use this method for errors known for sure thrown because of a bad proxy configuration.
|
---|
[6852] | 975 | *
|
---|
[6642] | 976 | * @param url The accessed URL that caused the error
|
---|
| 977 | * @param t The network error
|
---|
| 978 | * @return The previous error associated to the given resource, if any. Can be {@code null}
|
---|
[6643] | 979 | * @since 6642
|
---|
[6642] | 980 | */
|
---|
| 981 | public static Throwable addNetworkError(String url, Throwable t) {
|
---|
| 982 | if (url != null && t != null) {
|
---|
[6806] | 983 | return NETWORK_ERRORS.put(url, t);
|
---|
[6642] | 984 | }
|
---|
| 985 | return null;
|
---|
| 986 | }
|
---|
| 987 |
|
---|
| 988 | /**
|
---|
| 989 | * Returns the network errors that occured until now.
|
---|
| 990 | * @return the network errors that occured until now, indexed by URL
|
---|
| 991 | * @since 6639
|
---|
| 992 | */
|
---|
| 993 | public static Map<String, Throwable> getNetworkErrors() {
|
---|
[7005] | 994 | return new HashMap<>(NETWORK_ERRORS);
|
---|
[6642] | 995 | }
|
---|
[6897] | 996 |
|
---|
| 997 | /**
|
---|
[12011] | 998 | * Clears the network errors cache.
|
---|
| 999 | * @since 12011
|
---|
| 1000 | */
|
---|
| 1001 | public static void clearNetworkErrors() {
|
---|
| 1002 | NETWORK_ERRORS.clear();
|
---|
| 1003 | }
|
---|
| 1004 |
|
---|
| 1005 | /**
|
---|
[6897] | 1006 | * Returns the JOSM website URL.
|
---|
| 1007 | * @return the josm website URL
|
---|
| 1008 | * @since 6897
|
---|
| 1009 | */
|
---|
| 1010 | public static String getJOSMWebsite() {
|
---|
[12846] | 1011 | if (Config.getPref() != null)
|
---|
| 1012 | return Config.getPref().get("josm.url", JOSM_WEBSITE);
|
---|
[6897] | 1013 | return JOSM_WEBSITE;
|
---|
| 1014 | }
|
---|
| 1015 |
|
---|
| 1016 | /**
|
---|
| 1017 | * Returns the JOSM XML URL.
|
---|
| 1018 | * @return the josm XML URL
|
---|
| 1019 | * @since 6897
|
---|
| 1020 | */
|
---|
| 1021 | public static String getXMLBase() {
|
---|
[6920] | 1022 | // Always return HTTP (issues reported with HTTPS)
|
---|
[6900] | 1023 | return "http://josm.openstreetmap.de";
|
---|
[6897] | 1024 | }
|
---|
| 1025 |
|
---|
| 1026 | /**
|
---|
| 1027 | * Returns the OSM website URL.
|
---|
| 1028 | * @return the OSM website URL
|
---|
| 1029 | * @since 6897
|
---|
| 1030 | */
|
---|
| 1031 | public static String getOSMWebsite() {
|
---|
[12846] | 1032 | if (Config.getPref() != null)
|
---|
| 1033 | return Config.getPref().get("osm.url", OSM_WEBSITE);
|
---|
[6897] | 1034 | return OSM_WEBSITE;
|
---|
| 1035 | }
|
---|
[6957] | 1036 |
|
---|
| 1037 | /**
|
---|
[11262] | 1038 | * Returns the OSM website URL depending on the selected {@link OsmApi}.
|
---|
| 1039 | * @return the OSM website URL depending on the selected {@link OsmApi}
|
---|
| 1040 | */
|
---|
| 1041 | private static String getOSMWebsiteDependingOnSelectedApi() {
|
---|
| 1042 | final String api = OsmApi.getOsmApi().getServerUrl();
|
---|
| 1043 | if (OsmApi.DEFAULT_API_URL.equals(api)) {
|
---|
| 1044 | return getOSMWebsite();
|
---|
| 1045 | } else {
|
---|
| 1046 | return api.replaceAll("/api$", "");
|
---|
| 1047 | }
|
---|
| 1048 | }
|
---|
| 1049 |
|
---|
| 1050 | /**
|
---|
[7678] | 1051 | * Replies the base URL for browsing information about a primitive.
|
---|
| 1052 | * @return the base URL, i.e. https://www.openstreetmap.org
|
---|
| 1053 | * @since 7678
|
---|
| 1054 | */
|
---|
| 1055 | public static String getBaseBrowseUrl() {
|
---|
[12846] | 1056 | if (Config.getPref() != null)
|
---|
| 1057 | return Config.getPref().get("osm-browse.url", getOSMWebsiteDependingOnSelectedApi());
|
---|
[11262] | 1058 | return getOSMWebsiteDependingOnSelectedApi();
|
---|
[7678] | 1059 | }
|
---|
| 1060 |
|
---|
| 1061 | /**
|
---|
| 1062 | * Replies the base URL for browsing information about a user.
|
---|
| 1063 | * @return the base URL, i.e. https://www.openstreetmap.org/user
|
---|
| 1064 | * @since 7678
|
---|
| 1065 | */
|
---|
| 1066 | public static String getBaseUserUrl() {
|
---|
[12846] | 1067 | if (Config.getPref() != null)
|
---|
| 1068 | return Config.getPref().get("osm-user.url", getOSMWebsiteDependingOnSelectedApi() + "/user");
|
---|
[11262] | 1069 | return getOSMWebsiteDependingOnSelectedApi() + "/user";
|
---|
[7678] | 1070 | }
|
---|
| 1071 |
|
---|
| 1072 | /**
|
---|
[6957] | 1073 | * Determines if we are currently running on OSX.
|
---|
| 1074 | * @return {@code true} if we are currently running on OSX
|
---|
| 1075 | * @since 6957
|
---|
| 1076 | */
|
---|
| 1077 | public static boolean isPlatformOsx() {
|
---|
| 1078 | return Main.platform instanceof PlatformHookOsx;
|
---|
| 1079 | }
|
---|
[7335] | 1080 |
|
---|
| 1081 | /**
|
---|
| 1082 | * Determines if we are currently running on Windows.
|
---|
| 1083 | * @return {@code true} if we are currently running on Windows
|
---|
| 1084 | * @since 7335
|
---|
| 1085 | */
|
---|
| 1086 | public static boolean isPlatformWindows() {
|
---|
| 1087 | return Main.platform instanceof PlatformHookWindows;
|
---|
| 1088 | }
|
---|
[7434] | 1089 |
|
---|
| 1090 | /**
|
---|
| 1091 | * Determines if the given online resource is currently offline.
|
---|
| 1092 | * @param r the online resource
|
---|
| 1093 | * @return {@code true} if {@code r} is offline and should not be accessed
|
---|
| 1094 | * @since 7434
|
---|
| 1095 | */
|
---|
| 1096 | public static boolean isOffline(OnlineResource r) {
|
---|
| 1097 | return OFFLINE_RESOURCES.contains(r) || OFFLINE_RESOURCES.contains(OnlineResource.ALL);
|
---|
| 1098 | }
|
---|
| 1099 |
|
---|
| 1100 | /**
|
---|
| 1101 | * Sets the given online resource to offline state.
|
---|
| 1102 | * @param r the online resource
|
---|
| 1103 | * @return {@code true} if {@code r} was not already offline
|
---|
| 1104 | * @since 7434
|
---|
| 1105 | */
|
---|
| 1106 | public static boolean setOffline(OnlineResource r) {
|
---|
| 1107 | return OFFLINE_RESOURCES.add(r);
|
---|
| 1108 | }
|
---|
| 1109 |
|
---|
| 1110 | /**
|
---|
[8506] | 1111 | * Sets the given online resource to online state.
|
---|
| 1112 | * @param r the online resource
|
---|
| 1113 | * @return {@code true} if {@code r} was offline
|
---|
| 1114 | * @since 8506
|
---|
| 1115 | */
|
---|
| 1116 | public static boolean setOnline(OnlineResource r) {
|
---|
| 1117 | return OFFLINE_RESOURCES.remove(r);
|
---|
| 1118 | }
|
---|
| 1119 |
|
---|
| 1120 | /**
|
---|
[7434] | 1121 | * Replies the set of online resources currently offline.
|
---|
| 1122 | * @return the set of online resources currently offline
|
---|
| 1123 | * @since 7434
|
---|
| 1124 | */
|
---|
| 1125 | public static Set<OnlineResource> getOfflineResources() {
|
---|
[10044] | 1126 | return EnumSet.copyOf(OFFLINE_RESOURCES);
|
---|
[7434] | 1127 | }
|
---|
[626] | 1128 | }
|
---|