source: josm/trunk/src/org/openstreetmap/josm/gui/MainApplication.java@ 8017

Last change on this file since 8017 was 8017, checked in by bastiK, 9 years ago

see #11090 - basic support for plugin loading at runtime.

This is still in testing stage. It will be announced on
the mailing list when plugin authors can start to adapt
their code.

  • Property svn:eol-style set to native
File size: 27.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trn;
6import gnu.getopt.Getopt;
7import gnu.getopt.LongOpt;
8
9import java.awt.Dimension;
10import java.awt.GraphicsEnvironment;
11import java.awt.Image;
12import java.awt.Toolkit;
13import java.awt.event.WindowAdapter;
14import java.awt.event.WindowEvent;
15import java.io.File;
16import java.io.IOException;
17import java.io.InputStream;
18import java.net.Authenticator;
19import java.net.ProxySelector;
20import java.net.URL;
21import java.security.AllPermission;
22import java.security.CodeSource;
23import java.security.KeyStoreException;
24import java.security.NoSuchAlgorithmException;
25import java.security.PermissionCollection;
26import java.security.Permissions;
27import java.security.Policy;
28import java.security.cert.CertificateException;
29import java.util.ArrayList;
30import java.util.Arrays;
31import java.util.Collection;
32import java.util.HashMap;
33import java.util.LinkedList;
34import java.util.List;
35import java.util.Map;
36import java.util.Set;
37import java.util.TreeSet;
38
39import javax.swing.JFrame;
40import javax.swing.JOptionPane;
41import javax.swing.RepaintManager;
42import javax.swing.SwingUtilities;
43
44import org.jdesktop.swinghelper.debug.CheckThreadViolationRepaintManager;
45import org.openstreetmap.josm.Main;
46import org.openstreetmap.josm.actions.PreferencesAction;
47import org.openstreetmap.josm.data.AutosaveTask;
48import org.openstreetmap.josm.data.CustomConfigurator;
49import org.openstreetmap.josm.data.Version;
50import org.openstreetmap.josm.gui.download.DownloadDialog;
51import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder;
52import org.openstreetmap.josm.gui.preferences.server.ProxyPreference;
53import org.openstreetmap.josm.gui.progress.ProgressMonitor;
54import org.openstreetmap.josm.gui.util.GuiHelper;
55import org.openstreetmap.josm.io.DefaultProxySelector;
56import org.openstreetmap.josm.io.MessageNotifier;
57import org.openstreetmap.josm.io.OnlineResource;
58import org.openstreetmap.josm.io.auth.CredentialsManager;
59import org.openstreetmap.josm.io.auth.DefaultAuthenticator;
60import org.openstreetmap.josm.io.remotecontrol.RemoteControl;
61import org.openstreetmap.josm.plugins.PluginHandler;
62import org.openstreetmap.josm.plugins.PluginInformation;
63import org.openstreetmap.josm.tools.BugReportExceptionHandler;
64import org.openstreetmap.josm.tools.FontsManager;
65import org.openstreetmap.josm.tools.I18n;
66import org.openstreetmap.josm.tools.ImageProvider;
67import org.openstreetmap.josm.tools.OsmUrlToBounds;
68import org.openstreetmap.josm.tools.PlatformHookWindows;
69import org.openstreetmap.josm.tools.Utils;
70
71/**
72 * Main window class application.
73 *
74 * @author imi
75 */
76public class MainApplication extends Main {
77 /**
78 * Allow subclassing (see JOSM.java)
79 */
80 public MainApplication() {}
81
82 /**
83 * Constructs a main frame, ready sized and operating. Does not display the frame.
84 * @param mainFrame The main JFrame of the application
85 */
86 public MainApplication(JFrame mainFrame) {
87 addListener();
88 mainFrame.setContentPane(contentPanePrivate);
89 mainFrame.setJMenuBar(menu);
90 geometry.applySafe(mainFrame);
91 List<Image> l = new LinkedList<>();
92 l.add(ImageProvider.get("logo_16x16x32").getImage());
93 l.add(ImageProvider.get("logo_16x16x8").getImage());
94 l.add(ImageProvider.get("logo_32x32x32").getImage());
95 l.add(ImageProvider.get("logo_32x32x8").getImage());
96 l.add(ImageProvider.get("logo_48x48x32").getImage());
97 l.add(ImageProvider.get("logo_48x48x8").getImage());
98 l.add(ImageProvider.get("logo").getImage());
99 mainFrame.setIconImages(l);
100 mainFrame.addWindowListener(new WindowAdapter(){
101 @Override
102 public void windowClosing(final WindowEvent arg0) {
103 Main.exitJosm(true, 0);
104 }
105 });
106 mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
107 }
108
109 /**
110 * Displays help on the console
111 * @since 2748
112 */
113 public static void showHelp() {
114 // TODO: put in a platformHook for system that have no console by default
115 System.out.println(tr("Java OpenStreetMap Editor")+" ["
116 +Version.getInstance().getAgentString()+"]\n\n"+
117 tr("usage")+":\n"+
118 "\tjava -jar josm.jar <options>...\n\n"+
119 tr("options")+":\n"+
120 "\t--help|-h "+tr("Show this help")+"\n"+
121 "\t--geometry=widthxheight(+|-)x(+|-)y "+tr("Standard unix geometry argument")+"\n"+
122 "\t[--download=]minlat,minlon,maxlat,maxlon "+tr("Download the bounding box")+"\n"+
123 "\t[--download=]<URL> "+tr("Download the location at the URL (with lat=x&lon=y&zoom=z)")+"\n"+
124 "\t[--download=]<filename> "+tr("Open a file (any file type that can be opened with File/Open)")+"\n"+
125 "\t--downloadgps=minlat,minlon,maxlat,maxlon "+tr("Download the bounding box as raw GPS")+"\n"+
126 "\t--downloadgps=<URL> "+tr("Download the location at the URL (with lat=x&lon=y&zoom=z) as raw GPS")+"\n"+
127 "\t--selection=<searchstring> "+tr("Select with the given search")+"\n"+
128 "\t--[no-]maximize "+tr("Launch in maximized mode")+"\n"+
129 "\t--reset-preferences "+tr("Reset the preferences to default")+"\n\n"+
130 "\t--load-preferences=<url-to-xml> "+tr("Changes preferences according to the XML file")+"\n\n"+
131 "\t--set=<key>=<value> "+tr("Set preference key to value")+"\n\n"+
132 "\t--language=<language> "+tr("Set the language")+"\n\n"+
133 "\t--version "+tr("Displays the JOSM version and exits")+"\n\n"+
134 "\t--debug "+tr("Print debugging messages to console")+"\n\n"+
135 "\t--offline=<osm_api|josm_website|all> "+tr("Disable access to the given resource(s), separated by comma")+"\n\n"+
136 tr("options provided as Java system properties")+":\n"+
137 "\t-Djosm.pref=" +tr("/PATH/TO/JOSM/PREF ")+tr("Set the preferences directory")+"\n\n"+
138 "\t-Djosm.userdata="+tr("/PATH/TO/JOSM/USERDATA")+tr("Set the user data directory")+"\n\n"+
139 "\t-Djosm.cache=" +tr("/PATH/TO/JOSM/CACHE ")+tr("Set the cache directory")+"\n\n"+
140 "\t-Djosm.home=" +tr("/PATH/TO/JOSM/HOMEDIR ")+
141 tr("Relocate all 3 directories to homedir. Cache directory will be in homedir/cache")+"\n\n"+
142 tr("-Djosm.home has lower precedence, i.e. the specific setting overrides the general one")+"\n\n"+
143 tr("note: For some tasks, JOSM needs a lot of memory. It can be necessary to add the following\n" +
144 " Java option to specify the maximum size of allocated memory in megabytes")+":\n"+
145 "\t-Xmx...m\n\n"+
146 tr("examples")+":\n"+
147 "\tjava -jar josm.jar track1.gpx track2.gpx london.osm\n"+
148 "\tjava -jar josm.jar "+OsmUrlToBounds.getURL(43.2, 11.1, 13)+"\n"+
149 "\tjava -jar josm.jar london.osm --selection=http://www.ostertag.name/osm/OSM_errors_node-duplicate.xml\n"+
150 "\tjava -jar josm.jar 43.2,11.1,43.4,11.4\n"+
151 "\tjava -Djosm.pref=$XDG_CONFIG_HOME -Djosm.userdata=$XDG_DATA_HOME -Djosm.cache=$XDG_CACHE_HOME -jar josm.jar\n"+
152 "\tjava -Djosm.home=/home/user/.josm_dev -jar josm.jar\n"+
153 "\tjava -Xmx1024m -jar josm.jar\n\n"+
154 tr("Parameters --download, --downloadgps, and --selection are processed in this order.")+"\n"+
155 tr("Make sure you load some data if you use --selection.")+"\n"
156 );
157 }
158
159 /**
160 * JOSM command line options.
161 * @see <a href="https://josm.openstreetmap.de/wiki/Help/CommandLineOptions">Help/CommandLineOptions</a>
162 * @since 5279
163 */
164 public enum Option {
165 /** --help|-h Show this help */
166 HELP(false),
167 /** --version Displays the JOSM version and exits */
168 VERSION(false),
169 /** --debug Print debugging messages to console */
170 DEBUG(false),
171 /** --trace Print detailed debugging messages to console */
172 TRACE(false),
173 /** --language=&lt;language&gt; Set the language */
174 LANGUAGE(true),
175 /** --reset-preferences Reset the preferences to default */
176 RESET_PREFERENCES(false),
177 /** --load-preferences=&lt;url-to-xml&gt; Changes preferences according to the XML file */
178 LOAD_PREFERENCES(true),
179 /** --set=&lt;key&gt;=&lt;value&gt; Set preference key to value */
180 SET(true),
181 /** --geometry=widthxheight(+|-)x(+|-)y Standard unix geometry argument */
182 GEOMETRY(true),
183 /** --no-maximize Do not launch in maximized mode */
184 NO_MAXIMIZE(false),
185 /** --maximize Launch in maximized mode */
186 MAXIMIZE(false),
187 /** --download=minlat,minlon,maxlat,maxlon Download the bounding box <br>
188 * --download=&lt;URL&gt; Download the location at the URL (with lat=x&amp;lon=y&amp;zoom=z) <br>
189 * --download=&lt;filename&gt; Open a file (any file type that can be opened with File/Open) */
190 DOWNLOAD(true),
191 /** --downloadgps=minlat,minlon,maxlat,maxlon Download the bounding box as raw GPS <br>
192 * --downloadgps=&lt;URL&gt; Download the location at the URL (with lat=x&amp;lon=y&amp;zoom=z) as raw GPS */
193 DOWNLOADGPS(true),
194 /** --selection=&lt;searchstring&gt; Select with the given search */
195 SELECTION(true),
196 /** --offline=&lt;osm_api|josm_website|all&gt; Disable access to the given resource(s), delimited by comma */
197 OFFLINE(true);
198
199 private String name;
200 private boolean requiresArgument;
201
202 private Option(boolean requiresArgument) {
203 this.name = name().toLowerCase().replace("_", "-");
204 this.requiresArgument = requiresArgument;
205 }
206
207 /**
208 * Replies the option name
209 * @return The option name, in lowercase
210 */
211 public String getName() {
212 return name;
213 }
214
215 /**
216 * Determines if this option requires an argument.
217 * @return {@code true} if this option requires an argument, {@code false} otherwise
218 */
219 public boolean requiresArgument() {
220 return requiresArgument;
221 }
222
223 public static Map<Option, Collection<String>> fromStringMap(Map<String, Collection<String>> opts) {
224 Map<Option, Collection<String>> res = new HashMap<>();
225 for (Map.Entry<String, Collection<String>> e : opts.entrySet()) {
226 Option o = Option.valueOf(e.getKey().toUpperCase().replace("-", "_"));
227 if (o != null) {
228 res.put(o, e.getValue());
229 }
230 }
231 return res;
232 }
233 }
234
235 private static Map<Option, Collection<String>> buildCommandLineArgumentMap(String[] args) {
236
237 List<LongOpt> los = new ArrayList<>();
238 for (Option o : Option.values()) {
239 los.add(new LongOpt(o.getName(), o.requiresArgument() ? LongOpt.REQUIRED_ARGUMENT : LongOpt.NO_ARGUMENT, null, 0));
240 }
241
242 Getopt g = new Getopt("JOSM", args, "hv", los.toArray(new LongOpt[los.size()]));
243
244 Map<Option, Collection<String>> argMap = new HashMap<>();
245
246 int c;
247 while ((c = g.getopt()) != -1 ) {
248 Option opt = null;
249 switch (c) {
250 case 'h':
251 opt = Option.HELP;
252 break;
253 case 'v':
254 opt = Option.VERSION;
255 break;
256 case 0:
257 opt = Option.values()[g.getLongind()];
258 break;
259 }
260 if (opt != null) {
261 Collection<String> values = argMap.get(opt);
262 if (values == null) {
263 values = new ArrayList<>();
264 argMap.put(opt, values);
265 }
266 values.add(g.getOptarg());
267 } else
268 throw new IllegalArgumentException("Invalid option: "+c);
269 }
270 // positional arguments are a shortcut for the --download ... option
271 for (int i = g.getOptind(); i < args.length; ++i) {
272 Collection<String> values = argMap.get(Option.DOWNLOAD);
273 if (values == null) {
274 values = new ArrayList<>();
275 argMap.put(Option.DOWNLOAD, values);
276 }
277 values.add(args[i]);
278 }
279
280 return argMap;
281 }
282
283 /**
284 * Main application Startup
285 * @param argArray Command-line arguments
286 */
287 public static void main(final String[] argArray) {
288 I18n.init();
289 Main.checkJavaVersion();
290
291 // construct argument table
292 Map<Option, Collection<String>> args = null;
293 try {
294 args = buildCommandLineArgumentMap(argArray);
295 } catch (IllegalArgumentException e) {
296 System.exit(1);
297 return;
298 }
299
300 final boolean languageGiven = args.containsKey(Option.LANGUAGE);
301
302 if (languageGiven) {
303 I18n.set(args.get(Option.LANGUAGE).iterator().next());
304 }
305
306 initApplicationPreferences();
307
308 Policy.setPolicy(new Policy() {
309 // Permissions for plug-ins loaded when josm is started via webstart
310 private PermissionCollection pc;
311
312 {
313 pc = new Permissions();
314 pc.add(new AllPermission());
315 }
316
317 @Override
318 public void refresh() { }
319
320 @Override
321 public PermissionCollection getPermissions(CodeSource codesource) {
322 return pc;
323 }
324 });
325
326 Thread.setDefaultUncaughtExceptionHandler(new BugReportExceptionHandler());
327
328 // initialize the platform hook, and
329 Main.determinePlatformHook();
330 // call the really early hook before we do anything else
331 Main.platform.preStartupHook();
332
333 Main.commandLineArgs = Utils.copyArray(argArray);
334
335 if (args.containsKey(Option.VERSION)) {
336 System.out.println(Version.getInstance().getAgentString());
337 System.exit(0);
338 }
339
340 if (args.containsKey(Option.DEBUG) || args.containsKey(Option.TRACE)) {
341 // Enable JOSM debug level
342 logLevel = 4;
343 Main.info(tr("Printing debugging messages to console"));
344 }
345
346 if (args.containsKey(Option.TRACE)) {
347 // Enable JOSM debug level
348 logLevel = 5;
349 // Enable debug in OAuth signpost via system preference, but only at trace level
350 Utils.updateSystemProperty("debug", "true");
351 Main.info(tr("Enabled detailed debug level (trace)"));
352 }
353
354 Main.pref.init(args.containsKey(Option.RESET_PREFERENCES));
355
356 if (!languageGiven) {
357 I18n.set(Main.pref.get("language", null));
358 }
359 Main.pref.updateSystemProperties();
360
361 // asking for help? show help and exit
362 if (args.containsKey(Option.HELP)) {
363 showHelp();
364 System.exit(0);
365 }
366
367 processOffline(args);
368
369 Main.platform.afterPrefStartupHook();
370
371 FontsManager.initialize();
372
373 handleSpecialLanguages();
374
375 final JFrame mainFrame = new JFrame(tr("Java OpenStreetMap Editor"));
376 Main.parent = mainFrame;
377
378 if (args.containsKey(Option.LOAD_PREFERENCES)) {
379 CustomConfigurator.XMLCommandProcessor config = new CustomConfigurator.XMLCommandProcessor(Main.pref);
380 for (String i : args.get(Option.LOAD_PREFERENCES)) {
381 info("Reading preferences from " + i);
382 try (InputStream is = Utils.openURL(new URL(i))) {
383 config.openAndReadXML(is);
384 } catch (Exception ex) {
385 throw new RuntimeException(ex);
386 }
387 }
388 }
389
390 if (args.containsKey(Option.SET)) {
391 for (String i : args.get(Option.SET)) {
392 String[] kv = i.split("=", 2);
393 Main.pref.put(kv[0], "null".equals(kv[1]) ? null : kv[1]);
394 }
395 }
396
397 DefaultAuthenticator.createInstance();
398 Authenticator.setDefault(DefaultAuthenticator.getInstance());
399 DefaultProxySelector proxySelector = new DefaultProxySelector(ProxySelector.getDefault());
400 ProxySelector.setDefault(proxySelector);
401 OAuthAccessTokenHolder.getInstance().init(Main.pref, CredentialsManager.getInstance());
402
403 final SplashScreen splash = new SplashScreen();
404 final ProgressMonitor monitor = splash.getProgressMonitor();
405 monitor.beginTask(tr("Initializing"));
406 splash.setVisible(Main.pref.getBoolean("draw.splashscreen", true));
407 Main.setInitStatusListener(new InitStatusListener() {
408
409 @Override
410 public void updateStatus(String event) {
411 monitor.indeterminateSubTask(event);
412 }
413 });
414
415 Collection<PluginInformation> pluginsToLoad = PluginHandler.buildListOfPluginsToLoad(splash,monitor.createSubTaskMonitor(1, false));
416 if (!pluginsToLoad.isEmpty() && PluginHandler.checkAndConfirmPluginUpdate(splash)) {
417 monitor.subTask(tr("Updating plugins"));
418 pluginsToLoad = PluginHandler.updatePlugins(splash, null, monitor.createSubTaskMonitor(1, false), false);
419 }
420
421 monitor.indeterminateSubTask(tr("Installing updated plugins"));
422 PluginHandler.installDownloadedPlugins(true);
423
424 monitor.indeterminateSubTask(tr("Loading early plugins"));
425 PluginHandler.loadEarlyPlugins(splash, pluginsToLoad, monitor.createSubTaskMonitor(1, false));
426
427 monitor.indeterminateSubTask(tr("Setting defaults"));
428 preConstructorInit(args);
429
430 monitor.indeterminateSubTask(tr("Creating main GUI"));
431 final Main main = new MainApplication(mainFrame);
432
433 monitor.indeterminateSubTask(tr("Loading plugins"));
434 PluginHandler.loadLatePlugins(splash, pluginsToLoad, monitor.createSubTaskMonitor(1, false));
435 toolbar.refreshToolbarControl();
436
437 // Wait for splash disappearance (fix #9714)
438 GuiHelper.runInEDTAndWait(new Runnable() {
439 @Override
440 public void run() {
441 splash.setVisible(false);
442 splash.dispose();
443 mainFrame.setVisible(true);
444 }
445 });
446
447 Main.MasterWindowListener.setup();
448
449 boolean maximized = Main.pref.getBoolean("gui.maximized", false);
450 if ((!args.containsKey(Option.NO_MAXIMIZE) && maximized) || args.containsKey(Option.MAXIMIZE)) {
451 if (Toolkit.getDefaultToolkit().isFrameStateSupported(JFrame.MAXIMIZED_BOTH)) {
452 Main.windowState = JFrame.MAXIMIZED_BOTH;
453 mainFrame.setExtendedState(Main.windowState);
454 } else {
455 Main.debug("Main window: maximizing not supported");
456 }
457 }
458 if (main.menu.fullscreenToggleAction != null) {
459 main.menu.fullscreenToggleAction.initial();
460 }
461
462 SwingUtilities.invokeLater(new GuiFinalizationWorker(args, proxySelector));
463
464 if (Main.isPlatformWindows()) {
465 try {
466 // Check for insecure certificates to remove.
467 // This is Windows-dependant code but it can't go to preStartupHook (need i18n) neither startupHook (need to be called before remote control)
468 PlatformHookWindows.removeInsecureCertificates();
469 } catch (NoSuchAlgorithmException | CertificateException | KeyStoreException | IOException e) {
470 error(e);
471 }
472 }
473
474 if (RemoteControl.PROP_REMOTECONTROL_ENABLED.get()) {
475 RemoteControl.start();
476 }
477
478 if (MessageNotifier.PROP_NOTIFIER_ENABLED.get()) {
479 MessageNotifier.start();
480 }
481
482 if (Main.pref.getBoolean("debug.edt-checker.enable", Version.getInstance().isLocalBuild())) {
483 // Repaint manager is registered so late for a reason - there is lots of violation during startup process but they don't seem to break anything and are difficult to fix
484 info("Enabled EDT checker, wrongful access to gui from non EDT thread will be printed to console");
485 RepaintManager.setCurrentManager(new CheckThreadViolationRepaintManager());
486 }
487 }
488
489 private static void handleSpecialLanguages() {
490 // Use special font for Khmer script, as the default Java font do not display these characters
491 if ("km".equals(Main.pref.get("language"))) {
492 Collection<String> fonts = Arrays.asList(
493 GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
494 for (String f : new String[]{"Khmer UI", "DaunPenh", "MoolBoran"}) {
495 if (fonts.contains(f)) {
496 GuiHelper.setUIFont(f);
497 break;
498 }
499 }
500 }
501 }
502
503 private static void processOffline(Map<Option, Collection<String>> args) {
504 if (args.containsKey(Option.OFFLINE)) {
505 for (String s : args.get(Option.OFFLINE).iterator().next().split(",")) {
506 try {
507 Main.setOffline(OnlineResource.valueOf(s.toUpperCase()));
508 } catch (IllegalArgumentException e) {
509 Main.error(tr("''{0}'' is not a valid value for argument ''{1}''. Possible values are {2}, possibly delimited by commas.",
510 s.toUpperCase(), Option.OFFLINE.getName(), Arrays.toString(OnlineResource.values())));
511 System.exit(1);
512 return;
513 }
514 }
515 Set<OnlineResource> offline = Main.getOfflineResources();
516 if (!offline.isEmpty()) {
517 Main.warn(trn("JOSM is running in offline mode. This resource will not be available: {0}",
518 "JOSM is running in offline mode. These resources will not be available: {0}",
519 offline.size(), offline.size() == 1 ? offline.iterator().next() : Arrays.toString(offline.toArray())));
520 }
521 }
522 }
523
524 private static class GuiFinalizationWorker implements Runnable {
525
526 private final Map<Option, Collection<String>> args;
527 private final DefaultProxySelector proxySelector;
528
529 public GuiFinalizationWorker(Map<Option, Collection<String>> args, DefaultProxySelector proxySelector) {
530 this.args = args;
531 this.proxySelector = proxySelector;
532 }
533
534 @Override
535 public void run() {
536
537 // Handle proxy/network errors early to inform user he should change settings to be able to use JOSM correctly
538 if (!handleProxyErrors()) {
539 handleNetworkErrors();
540 }
541
542 // Restore autosave layers after crash and start autosave thread
543 handleAutosave();
544
545 // Handle command line instructions
546 postConstructorProcessCmdLine(args);
547
548 // Show download dialog if autostart is enabled
549 DownloadDialog.autostartIfNeeded();
550 }
551
552 private void handleAutosave() {
553 if (AutosaveTask.PROP_AUTOSAVE_ENABLED.get()) {
554 AutosaveTask autosaveTask = new AutosaveTask();
555 List<File> unsavedLayerFiles = autosaveTask.getUnsavedLayersFiles();
556 if (!unsavedLayerFiles.isEmpty()) {
557 ExtendedDialog dialog = new ExtendedDialog(
558 Main.parent,
559 tr("Unsaved osm data"),
560 new String[] {tr("Restore"), tr("Cancel"), tr("Discard")}
561 );
562 dialog.setContent(
563 trn("JOSM found {0} unsaved osm data layer. ",
564 "JOSM found {0} unsaved osm data layers. ", unsavedLayerFiles.size(), unsavedLayerFiles.size()) +
565 tr("It looks like JOSM crashed last time. Would you like to restore the data?"));
566 dialog.setButtonIcons(new String[] {"ok", "cancel", "dialogs/delete"});
567 int selection = dialog.showDialog().getValue();
568 if (selection == 1) {
569 autosaveTask.recoverUnsavedLayers();
570 } else if (selection == 3) {
571 autosaveTask.discardUnsavedLayers();
572 }
573 }
574 autosaveTask.schedule();
575 }
576 }
577
578 private boolean handleNetworkOrProxyErrors(boolean hasErrors, String title, String message) {
579 if (hasErrors) {
580 ExtendedDialog ed = new ExtendedDialog(
581 Main.parent, title,
582 new String[]{tr("Change proxy settings"), tr("Cancel")});
583 ed.setButtonIcons(new String[]{"dialogs/settings.png", "cancel.png"}).setCancelButton(2);
584 ed.setMinimumSize(new Dimension(460, 260));
585 ed.setIcon(JOptionPane.WARNING_MESSAGE);
586 ed.setContent(message);
587
588 if (ed.showDialog().getValue() == 1) {
589 PreferencesAction.forPreferenceSubTab(null, null, ProxyPreference.class).run();
590 }
591 }
592 return hasErrors;
593 }
594
595 private boolean handleProxyErrors() {
596 return handleNetworkOrProxyErrors(proxySelector.hasErrors(), tr("Proxy errors occurred"),
597 tr("JOSM tried to access the following resources:<br>" +
598 "{0}" +
599 "but <b>failed</b> to do so, because of the following proxy errors:<br>" +
600 "{1}" +
601 "Would you like to change your proxy settings now?",
602 Utils.joinAsHtmlUnorderedList(proxySelector.getErrorResources()),
603 Utils.joinAsHtmlUnorderedList(proxySelector.getErrorMessages())
604 ));
605 }
606
607 private boolean handleNetworkErrors() {
608 boolean condition = !NETWORK_ERRORS.isEmpty();
609 if (condition) {
610 Set<String> errors = new TreeSet<>();
611 for (Throwable t : NETWORK_ERRORS.values()) {
612 errors.add(t.toString());
613 }
614 return handleNetworkOrProxyErrors(condition, tr("Network errors occurred"),
615 tr("JOSM tried to access the following resources:<br>" +
616 "{0}" +
617 "but <b>failed</b> to do so, because of the following network errors:<br>" +
618 "{1}" +
619 "It may be due to a missing proxy configuration.<br>" +
620 "Would you like to change your proxy settings now?",
621 Utils.joinAsHtmlUnorderedList(NETWORK_ERRORS.keySet()),
622 Utils.joinAsHtmlUnorderedList(errors)
623 ));
624 }
625 return false;
626 }
627 }
628}
Note: See TracBrowser for help on using the repository browser.