| 1 | // License: GPL. Copyright 2007 by Immanuel Scholz and others |
|---|
| 2 | package org.openstreetmap.josm.gui; |
|---|
| 3 | |
|---|
| 4 | import static org.openstreetmap.josm.tools.I18n.tr; |
|---|
| 5 | import static org.openstreetmap.josm.tools.I18n.trn; |
|---|
| 6 | |
|---|
| 7 | import java.awt.Image; |
|---|
| 8 | import java.awt.Toolkit; |
|---|
| 9 | import java.awt.event.ActionEvent; |
|---|
| 10 | import java.awt.event.WindowAdapter; |
|---|
| 11 | import java.awt.event.WindowEvent; |
|---|
| 12 | import java.io.File; |
|---|
| 13 | import java.net.Authenticator; |
|---|
| 14 | import java.net.ProxySelector; |
|---|
| 15 | import java.net.URL; |
|---|
| 16 | import java.security.AllPermission; |
|---|
| 17 | import java.security.CodeSource; |
|---|
| 18 | import java.security.PermissionCollection; |
|---|
| 19 | import java.security.Permissions; |
|---|
| 20 | import java.security.Policy; |
|---|
| 21 | import java.util.Collection; |
|---|
| 22 | import java.util.HashMap; |
|---|
| 23 | import java.util.LinkedList; |
|---|
| 24 | import java.util.List; |
|---|
| 25 | import java.util.Map; |
|---|
| 26 | |
|---|
| 27 | import javax.swing.JFrame; |
|---|
| 28 | import javax.swing.RepaintManager; |
|---|
| 29 | import javax.swing.SwingUtilities; |
|---|
| 30 | |
|---|
| 31 | import org.jdesktop.swinghelper.debug.CheckThreadViolationRepaintManager; |
|---|
| 32 | import org.openstreetmap.josm.Main; |
|---|
| 33 | import org.openstreetmap.josm.data.AutosaveTask; |
|---|
| 34 | import org.openstreetmap.josm.data.CustomConfigurator; |
|---|
| 35 | import org.openstreetmap.josm.data.Preferences; |
|---|
| 36 | import org.openstreetmap.josm.data.Version; |
|---|
| 37 | import org.openstreetmap.josm.gui.download.DownloadDialog; |
|---|
| 38 | import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder; |
|---|
| 39 | import org.openstreetmap.josm.gui.progress.ProgressMonitor; |
|---|
| 40 | import org.openstreetmap.josm.io.DefaultProxySelector; |
|---|
| 41 | import org.openstreetmap.josm.io.auth.CredentialsManager; |
|---|
| 42 | import org.openstreetmap.josm.io.auth.DefaultAuthenticator; |
|---|
| 43 | import org.openstreetmap.josm.io.remotecontrol.RemoteControl; |
|---|
| 44 | import org.openstreetmap.josm.plugins.PluginHandler; |
|---|
| 45 | import org.openstreetmap.josm.plugins.PluginInformation; |
|---|
| 46 | import org.openstreetmap.josm.tools.BugReportExceptionHandler; |
|---|
| 47 | import org.openstreetmap.josm.tools.I18n; |
|---|
| 48 | import org.openstreetmap.josm.tools.ImageProvider; |
|---|
| 49 | |
|---|
| 50 | /** |
|---|
| 51 | * Main window class application. |
|---|
| 52 | * |
|---|
| 53 | * @author imi |
|---|
| 54 | */ |
|---|
| 55 | public class MainApplication extends Main { |
|---|
| 56 | /** |
|---|
| 57 | * Allow subclassing (see JOSM.java) |
|---|
| 58 | */ |
|---|
| 59 | public MainApplication() {} |
|---|
| 60 | |
|---|
| 61 | /** |
|---|
| 62 | * Construct an main frame, ready sized and operating. Does not |
|---|
| 63 | * display the frame. |
|---|
| 64 | */ |
|---|
| 65 | public MainApplication(JFrame mainFrame) { |
|---|
| 66 | super(); |
|---|
| 67 | mainFrame.setContentPane(contentPanePrivate); |
|---|
| 68 | mainFrame.setJMenuBar(menu); |
|---|
| 69 | geometry.applySafe(mainFrame); |
|---|
| 70 | LinkedList<Image> l = new LinkedList<Image>(); |
|---|
| 71 | l.add(ImageProvider.get("logo_16x16x32").getImage()); |
|---|
| 72 | l.add(ImageProvider.get("logo_16x16x8").getImage()); |
|---|
| 73 | l.add(ImageProvider.get("logo_32x32x32").getImage()); |
|---|
| 74 | l.add(ImageProvider.get("logo_32x32x8").getImage()); |
|---|
| 75 | l.add(ImageProvider.get("logo_48x48x32").getImage()); |
|---|
| 76 | l.add(ImageProvider.get("logo_48x48x8").getImage()); |
|---|
| 77 | l.add(ImageProvider.get("logo").getImage()); |
|---|
| 78 | mainFrame.setIconImages(l); |
|---|
| 79 | mainFrame.addWindowListener(new WindowAdapter(){ |
|---|
| 80 | @Override public void windowClosing(final WindowEvent arg0) { |
|---|
| 81 | Main.exitJosm(true); |
|---|
| 82 | } |
|---|
| 83 | }); |
|---|
| 84 | mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); |
|---|
| 85 | } |
|---|
| 86 | |
|---|
| 87 | /** |
|---|
| 88 | * Displays help on the console |
|---|
| 89 | * |
|---|
| 90 | */ |
|---|
| 91 | public static void showHelp() { |
|---|
| 92 | // TODO: put in a platformHook for system that have no console by default |
|---|
| 93 | System.out.println(tr("Java OpenStreetMap Editor")+"\n\n"+ |
|---|
| 94 | tr("usage")+":\n"+ |
|---|
| 95 | "\tjava -jar josm.jar <options>...\n\n"+ |
|---|
| 96 | tr("options")+":\n"+ |
|---|
| 97 | "\t--help|-?|-h "+tr("Show this help")+"\n"+ |
|---|
| 98 | "\t--geometry=widthxheight(+|-)x(+|-)y "+tr("Standard unix geometry argument")+"\n"+ |
|---|
| 99 | "\t[--download=]minlat,minlon,maxlat,maxlon "+tr("Download the bounding box")+"\n"+ |
|---|
| 100 | "\t[--download=]<url> "+tr("Download the location at the url (with lat=x&lon=y&zoom=z)")+"\n"+ |
|---|
| 101 | "\t[--download=]<filename> "+tr("Open a file (any file type that can be opened with File/Open)")+"\n"+ |
|---|
| 102 | "\t--downloadgps=minlat,minlon,maxlat,maxlon "+tr("Download the bounding box as raw gps")+"\n"+ |
|---|
| 103 | "\t--downloadgps=<url> "+tr("Download the location at the url (with lat=x&lon=y&zoom=z) as raw gps")+"\n"+ |
|---|
| 104 | "\t--selection=<searchstring> "+tr("Select with the given search")+"\n"+ |
|---|
| 105 | "\t--[no-]maximize "+tr("Launch in maximized mode")+"\n"+ |
|---|
| 106 | "\t--reset-preferences "+tr("Reset the preferences to default")+"\n\n"+ |
|---|
| 107 | "\t--load-preferences=<url-to-xml> "+tr("Changes preferences according to the XML file")+"\n\n"+ |
|---|
| 108 | "\t--set=<key>=<value> "+tr("Set preference key to value")+"\n\n"+ |
|---|
| 109 | "\t--language=<language> "+tr("Set the language")+"\n\n"+ |
|---|
| 110 | tr("options provided as Java system properties")+":\n"+ |
|---|
| 111 | "\t-Djosm.home="+tr("/PATH/TO/JOSM/FOLDER/ ")+tr("Change the folder for all user settings")+"\n\n"+ |
|---|
| 112 | tr("note: For some tasks, JOSM needs a lot of memory. It can be necessary to add the following\n" + |
|---|
| 113 | " Java option to specify the maximum size of allocated memory in megabytes")+":\n"+ |
|---|
| 114 | "\t-Xmx...m\n\n"+ |
|---|
| 115 | tr("examples")+":\n"+ |
|---|
| 116 | "\tjava -jar josm.jar track1.gpx track2.gpx london.osm\n"+ |
|---|
| 117 | "\tjava -jar josm.jar http://www.openstreetmap.org/index.html?lat=43.2&lon=11.1&zoom=13\n"+ |
|---|
| 118 | "\tjava -jar josm.jar london.osm --selection=http://www.ostertag.name/osm/OSM_errors_node-duplicate.xml\n"+ |
|---|
| 119 | "\tjava -jar josm.jar 43.2,11.1,43.4,11.4\n"+ |
|---|
| 120 | "\tjava -Djosm.home=/home/user/.josm_dev -jar josm.jar\n"+ |
|---|
| 121 | "\tjava -Xmx400m -jar josm.jar\n\n"+ |
|---|
| 122 | tr("Parameters --download, --downloadgps, and --selection are processed in this order.")+"\n"+ |
|---|
| 123 | tr("Make sure you load some data if you use --selection.")+"\n" |
|---|
| 124 | ); |
|---|
| 125 | } |
|---|
| 126 | |
|---|
| 127 | private static Map<String, Collection<String>> buildCommandLineArgumentMap(String[] args) { |
|---|
| 128 | Map<String, Collection<String>> argMap = new HashMap<String, Collection<String>>(); |
|---|
| 129 | for (String arg : args) { |
|---|
| 130 | if ("-h".equals(arg) || "-?".equals(arg)) { |
|---|
| 131 | arg = "--help"; |
|---|
| 132 | } else if ("-v".equals(arg)) { |
|---|
| 133 | arg = "--version"; |
|---|
| 134 | } |
|---|
| 135 | // handle simple arguments like file names, URLs, bounds |
|---|
| 136 | if (!arg.startsWith("--")) { |
|---|
| 137 | arg = "--download="+arg; |
|---|
| 138 | } |
|---|
| 139 | int i = arg.indexOf('='); |
|---|
| 140 | String key = i == -1 ? arg.substring(2) : arg.substring(2,i); |
|---|
| 141 | String value = i == -1 ? "" : arg.substring(i+1); |
|---|
| 142 | Collection<String> v = argMap.get(key); |
|---|
| 143 | if (v == null) { |
|---|
| 144 | v = new LinkedList<String>(); |
|---|
| 145 | } |
|---|
| 146 | v.add(value); |
|---|
| 147 | argMap.put(key, v); |
|---|
| 148 | } |
|---|
| 149 | return argMap; |
|---|
| 150 | } |
|---|
| 151 | |
|---|
| 152 | /** |
|---|
| 153 | * Main application Startup |
|---|
| 154 | */ |
|---|
| 155 | public static void main(final String[] argArray) { |
|---|
| 156 | I18n.init(); |
|---|
| 157 | Main.checkJava6(); |
|---|
| 158 | Main.pref = new Preferences(); |
|---|
| 159 | |
|---|
| 160 | Policy.setPolicy(new Policy() { |
|---|
| 161 | // Permissions for plug-ins loaded when josm is started via webstart |
|---|
| 162 | private PermissionCollection pc; |
|---|
| 163 | |
|---|
| 164 | { |
|---|
| 165 | pc = new Permissions(); |
|---|
| 166 | pc.add(new AllPermission()); |
|---|
| 167 | } |
|---|
| 168 | |
|---|
| 169 | @Override |
|---|
| 170 | public void refresh() { } |
|---|
| 171 | |
|---|
| 172 | @Override |
|---|
| 173 | public PermissionCollection getPermissions(CodeSource codesource) { |
|---|
| 174 | return pc; |
|---|
| 175 | } |
|---|
| 176 | }); |
|---|
| 177 | |
|---|
| 178 | Thread.setDefaultUncaughtExceptionHandler(new BugReportExceptionHandler()); |
|---|
| 179 | // http://stuffthathappens.com/blog/2007/10/15/one-more-note-on-uncaught-exception-handlers/ |
|---|
| 180 | System.setProperty("sun.awt.exception.handler", BugReportExceptionHandler.class.getName()); |
|---|
| 181 | |
|---|
| 182 | // initialize the platform hook, and |
|---|
| 183 | Main.determinePlatformHook(); |
|---|
| 184 | // call the really early hook before we do anything else |
|---|
| 185 | Main.platform.preStartupHook(); |
|---|
| 186 | |
|---|
| 187 | // construct argument table |
|---|
| 188 | final Map<String, Collection<String>> args = buildCommandLineArgumentMap(argArray); |
|---|
| 189 | |
|---|
| 190 | if (args.containsKey("version")) { |
|---|
| 191 | System.out.println(Version.getInstance().getAgentString()); |
|---|
| 192 | System.exit(0); |
|---|
| 193 | } else { |
|---|
| 194 | System.out.println(Version.getInstance().getReleaseAttributes()); |
|---|
| 195 | } |
|---|
| 196 | |
|---|
| 197 | Main.pref.init(args.containsKey("reset-preferences")); |
|---|
| 198 | |
|---|
| 199 | // Check if passed as parameter |
|---|
| 200 | if (args.containsKey("language")) { |
|---|
| 201 | I18n.set(args.get("language").iterator().next()); |
|---|
| 202 | } else { |
|---|
| 203 | I18n.set(Main.pref.get("language", null)); |
|---|
| 204 | } |
|---|
| 205 | Main.pref.updateSystemProperties(); |
|---|
| 206 | |
|---|
| 207 | JFrame mainFrame = new JFrame(tr("Java OpenStreetMap Editor")); |
|---|
| 208 | Main.parent = mainFrame; |
|---|
| 209 | |
|---|
| 210 | if (args.containsKey("load-preferences")) { |
|---|
| 211 | CustomConfigurator.XMLCommandProcessor config = new CustomConfigurator.XMLCommandProcessor(Main.pref); |
|---|
| 212 | for (String i : args.get("load-preferences")) { |
|---|
| 213 | System.out.println("Reading preferences from " + i); |
|---|
| 214 | try { |
|---|
| 215 | URL url = new URL(i); |
|---|
| 216 | config.openAndReadXML(url.openStream()); |
|---|
| 217 | } catch (Exception ex) { |
|---|
| 218 | throw new RuntimeException(ex); |
|---|
| 219 | } |
|---|
| 220 | } |
|---|
| 221 | } |
|---|
| 222 | |
|---|
| 223 | if (args.containsKey("set")) { |
|---|
| 224 | for (String i : args.get("set")) { |
|---|
| 225 | String[] kv = i.split("=", 2); |
|---|
| 226 | Main.pref.put(kv[0], "null".equals(kv[1]) ? null : kv[1]); |
|---|
| 227 | } |
|---|
| 228 | } |
|---|
| 229 | |
|---|
| 230 | DefaultAuthenticator.createInstance(); |
|---|
| 231 | Authenticator.setDefault(DefaultAuthenticator.getInstance()); |
|---|
| 232 | ProxySelector.setDefault(new DefaultProxySelector(ProxySelector.getDefault())); |
|---|
| 233 | OAuthAccessTokenHolder.getInstance().init(Main.pref, CredentialsManager.getInstance()); |
|---|
| 234 | |
|---|
| 235 | // asking for help? show help and exit |
|---|
| 236 | if (args.containsKey("help")) { |
|---|
| 237 | showHelp(); |
|---|
| 238 | System.exit(0); |
|---|
| 239 | } |
|---|
| 240 | |
|---|
| 241 | SplashScreen splash = new SplashScreen(); |
|---|
| 242 | final ProgressMonitor monitor = splash.getProgressMonitor(); |
|---|
| 243 | monitor.beginTask(tr("Initializing")); |
|---|
| 244 | splash.setVisible(Main.pref.getBoolean("draw.splashscreen", true)); |
|---|
| 245 | Main.setInitStatusListener(new InitStatusListener() { |
|---|
| 246 | |
|---|
| 247 | @Override |
|---|
| 248 | public void updateStatus(String event) { |
|---|
| 249 | monitor.indeterminateSubTask(event); |
|---|
| 250 | } |
|---|
| 251 | }); |
|---|
| 252 | |
|---|
| 253 | List<PluginInformation> pluginsToLoad = PluginHandler.buildListOfPluginsToLoad(splash,monitor.createSubTaskMonitor(1, false)); |
|---|
| 254 | if (!pluginsToLoad.isEmpty() && PluginHandler.checkAndConfirmPluginUpdate(splash)) { |
|---|
| 255 | monitor.subTask(tr("Updating plugins")); |
|---|
| 256 | pluginsToLoad = PluginHandler.updatePlugins(splash,pluginsToLoad, monitor.createSubTaskMonitor(1, false)); |
|---|
| 257 | } |
|---|
| 258 | |
|---|
| 259 | monitor.indeterminateSubTask(tr("Installing updated plugins")); |
|---|
| 260 | PluginHandler.installDownloadedPlugins(true); |
|---|
| 261 | |
|---|
| 262 | monitor.indeterminateSubTask(tr("Loading early plugins")); |
|---|
| 263 | PluginHandler.loadEarlyPlugins(splash,pluginsToLoad, monitor.createSubTaskMonitor(1, false)); |
|---|
| 264 | |
|---|
| 265 | monitor.indeterminateSubTask(tr("Setting defaults")); |
|---|
| 266 | preConstructorInit(args); |
|---|
| 267 | |
|---|
| 268 | monitor.indeterminateSubTask(tr("Creating main GUI")); |
|---|
| 269 | Main.addListener(); |
|---|
| 270 | final Main main = new MainApplication(mainFrame); |
|---|
| 271 | |
|---|
| 272 | monitor.indeterminateSubTask(tr("Loading plugins")); |
|---|
| 273 | PluginHandler.loadLatePlugins(splash,pluginsToLoad, monitor.createSubTaskMonitor(1, false)); |
|---|
| 274 | toolbar.refreshToolbarControl(); |
|---|
| 275 | splash.setVisible(false); |
|---|
| 276 | splash.dispose(); |
|---|
| 277 | mainFrame.setVisible(true); |
|---|
| 278 | |
|---|
| 279 | boolean maximized = Boolean.parseBoolean(Main.pref.get("gui.maximized")); |
|---|
| 280 | if ((!args.containsKey("no-maximize") && maximized) || args.containsKey("maximize")) { |
|---|
| 281 | if (Toolkit.getDefaultToolkit().isFrameStateSupported(JFrame.MAXIMIZED_BOTH)) { |
|---|
| 282 | // Main.debug("Main window maximized"); |
|---|
| 283 | Main.windowState = JFrame.MAXIMIZED_BOTH; |
|---|
| 284 | mainFrame.setExtendedState(Main.windowState); |
|---|
| 285 | } else { |
|---|
| 286 | Main.debug("Main window: maximizing not supported"); |
|---|
| 287 | } |
|---|
| 288 | } else { |
|---|
| 289 | // Main.debug("Main window not maximized"); |
|---|
| 290 | } |
|---|
| 291 | if(main.menu.fullscreenToggleAction != null) { |
|---|
| 292 | main.menu.fullscreenToggleAction.initial(); |
|---|
| 293 | } |
|---|
| 294 | |
|---|
| 295 | SwingUtilities.invokeLater(new Runnable() { |
|---|
| 296 | public void run() { |
|---|
| 297 | if (AutosaveTask.PROP_AUTOSAVE_ENABLED.get()) { |
|---|
| 298 | AutosaveTask autosaveTask = new AutosaveTask(); |
|---|
| 299 | List<File> unsavedLayerFiles = autosaveTask.getUnsavedLayersFiles(); |
|---|
| 300 | if (!unsavedLayerFiles.isEmpty()) { |
|---|
| 301 | ExtendedDialog dialog = new ExtendedDialog( |
|---|
| 302 | Main.parent, |
|---|
| 303 | tr("Unsaved osm data"), |
|---|
| 304 | new String[] {tr("Restore"), tr("Cancel"), tr("Discard")} |
|---|
| 305 | ); |
|---|
| 306 | dialog.setContent( |
|---|
| 307 | trn("JOSM found {0} unsaved osm data layer. ", |
|---|
| 308 | "JOSM found {0} unsaved osm data layers. ", unsavedLayerFiles.size(), unsavedLayerFiles.size()) + |
|---|
| 309 | tr("It looks like JOSM crashed last time. Would you like to restore the data?")); |
|---|
| 310 | dialog.setButtonIcons(new String[] {"ok", "cancel", "dialogs/remove"}); |
|---|
| 311 | int selection = dialog.showDialog().getValue(); |
|---|
| 312 | if (selection == 1) { |
|---|
| 313 | autosaveTask.recoverUnsavedLayers(); |
|---|
| 314 | } else if (selection == 3) { |
|---|
| 315 | autosaveTask.dicardUnsavedLayers(); |
|---|
| 316 | } |
|---|
| 317 | } |
|---|
| 318 | autosaveTask.schedule(); |
|---|
| 319 | } |
|---|
| 320 | |
|---|
| 321 | main.postConstructorProcessCmdLine(args); |
|---|
| 322 | |
|---|
| 323 | DownloadDialog.autostartIfNeeded(); |
|---|
| 324 | } |
|---|
| 325 | }); |
|---|
| 326 | |
|---|
| 327 | if (RemoteControl.PROP_REMOTECONTROL_ENABLED.get()) { |
|---|
| 328 | RemoteControl.start(); |
|---|
| 329 | } |
|---|
| 330 | |
|---|
| 331 | if (Main.pref.getBoolean("debug.edt-checker.enable", Version.getInstance().isLocalBuild())) { |
|---|
| 332 | // 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 |
|---|
| 333 | System.out.println("Enabled EDT checker, wrongful access to gui from non EDT thread will be printed to console"); |
|---|
| 334 | RepaintManager.setCurrentManager(new CheckThreadViolationRepaintManager()); |
|---|
| 335 | } |
|---|
| 336 | } |
|---|
| 337 | } |
|---|