source: josm/trunk/src/org/openstreetmap/josm/Main.java@ 4018

Last change on this file since 4018 was 3993, checked in by framm, 13 years ago

use short timeout for initial API connection, related to #6037

  • Property svn:eol-style set to native
File size: 28.6 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm;
3import static org.openstreetmap.josm.tools.I18n.tr;
4
5import java.awt.BorderLayout;
6import java.awt.Component;
7import java.awt.Dimension;
8import java.awt.GridBagConstraints;
9import java.awt.GridBagLayout;
10import java.awt.Rectangle;
11import java.awt.Toolkit;
12import java.awt.event.ComponentEvent;
13import java.awt.event.ComponentListener;
14import java.awt.event.KeyEvent;
15import java.awt.event.WindowAdapter;
16import java.awt.event.WindowEvent;
17import java.io.File;
18import java.net.URI;
19import java.net.URISyntaxException;
20import java.util.ArrayList;
21import java.util.Collection;
22import java.util.List;
23import java.util.Map;
24import java.util.StringTokenizer;
25import java.util.concurrent.ExecutorService;
26import java.util.concurrent.Executors;
27import java.util.concurrent.Future;
28import java.util.regex.Matcher;
29import java.util.regex.Pattern;
30
31import javax.swing.Action;
32import javax.swing.InputMap;
33import javax.swing.JComponent;
34import javax.swing.JFrame;
35import javax.swing.JLabel;
36import javax.swing.JOptionPane;
37import javax.swing.JPanel;
38import javax.swing.JTextArea;
39import javax.swing.KeyStroke;
40import javax.swing.UIManager;
41
42import org.openstreetmap.josm.actions.JosmAction;
43import org.openstreetmap.josm.actions.OpenFileAction;
44import org.openstreetmap.josm.actions.downloadtasks.DownloadGpsTask;
45import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
46import org.openstreetmap.josm.actions.downloadtasks.DownloadTask;
47import org.openstreetmap.josm.actions.downloadtasks.PostDownloadHandler;
48import org.openstreetmap.josm.actions.mapmode.MapMode;
49import org.openstreetmap.josm.actions.search.SearchAction;
50import org.openstreetmap.josm.data.Bounds;
51import org.openstreetmap.josm.data.Preferences;
52import org.openstreetmap.josm.data.UndoRedoHandler;
53import org.openstreetmap.josm.data.coor.CoordinateFormat;
54import org.openstreetmap.josm.data.coor.LatLon;
55import org.openstreetmap.josm.data.osm.DataSet;
56import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy;
57import org.openstreetmap.josm.data.projection.Projection;
58import org.openstreetmap.josm.data.validation.OsmValidator;
59import org.openstreetmap.josm.gui.GettingStarted;
60import org.openstreetmap.josm.gui.MainMenu;
61import org.openstreetmap.josm.gui.MapFrame;
62import org.openstreetmap.josm.gui.MapView;
63import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
64import org.openstreetmap.josm.gui.io.SaveLayersDialog;
65import org.openstreetmap.josm.gui.layer.Layer;
66import org.openstreetmap.josm.gui.layer.OsmDataLayer;
67import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener;
68import org.openstreetmap.josm.gui.preferences.ImageryPreference;
69import org.openstreetmap.josm.gui.preferences.MapPaintPreference;
70import org.openstreetmap.josm.gui.preferences.ProjectionPreference;
71import org.openstreetmap.josm.gui.preferences.TaggingPresetPreference;
72import org.openstreetmap.josm.gui.preferences.ToolbarPreferences;
73import org.openstreetmap.josm.io.OsmApi;
74import org.openstreetmap.josm.plugins.PluginHandler;
75import org.openstreetmap.josm.tools.I18n;
76import org.openstreetmap.josm.tools.ImageProvider;
77import org.openstreetmap.josm.tools.OsmUrlToBounds;
78import org.openstreetmap.josm.tools.PlatformHook;
79import org.openstreetmap.josm.tools.PlatformHookOsx;
80import org.openstreetmap.josm.tools.PlatformHookUnixoid;
81import org.openstreetmap.josm.tools.PlatformHookWindows;
82import org.openstreetmap.josm.tools.Shortcut;
83
84abstract public class Main {
85
86 /**
87 * Replies true if JOSM currently displays a map view. False, if it doesn't, i.e. if
88 * it only shows the MOTD panel.
89 *
90 * @return true if JOSM currently displays a map view
91 */
92 static public boolean isDisplayingMapView() {
93 if (map == null) return false;
94 if (map.mapView == null) return false;
95 return true;
96 }
97 /**
98 * Global parent component for all dialogs and message boxes
99 */
100 public static Component parent;
101 /**
102 * Global application.
103 */
104 public static Main main;
105 /**
106 * The worker thread slave. This is for executing all long and intensive
107 * calculations. The executed runnables are guaranteed to be executed separately
108 * and sequential.
109 */
110 public final static ExecutorService worker = Executors.newSingleThreadExecutor();
111 /**
112 * Global application preferences
113 */
114 public static Preferences pref;
115
116 /**
117 * The global paste buffer.
118 */
119 public static PrimitiveDeepCopy pasteBuffer = new PrimitiveDeepCopy();
120 public static Layer pasteSource;
121 /**
122 * The projection method used.
123 */
124 public static Projection proj;
125 /**
126 * The MapFrame. Use setMapFrame to set or clear it.
127 */
128 public static MapFrame map;
129 /**
130 * True, when in applet mode
131 */
132 public static boolean applet = false;
133
134 /**
135 * The toolbar preference control to register new actions.
136 */
137 public static ToolbarPreferences toolbar;
138
139 public UndoRedoHandler undoRedo = new UndoRedoHandler();
140
141 /**
142 * The main menu bar at top of screen.
143 */
144 public final MainMenu menu;
145
146 public final OsmValidator validator;
147 /**
148 * The MOTD Layer.
149 */
150 private GettingStarted gettingStarted = new GettingStarted();
151
152 /**
153 * Print a debug message if debugging is on.
154 */
155 static public int debug_level = 1;
156 static public final void debug(String msg) {
157 if (debug_level <= 0)
158 return;
159 System.out.println(msg);
160 }
161
162 /**
163 * Platform specific code goes in here.
164 * Plugins may replace it, however, some hooks will be called before any plugins have been loeaded.
165 * So if you need to hook into those early ones, split your class and send the one with the early hooks
166 * to the JOSM team for inclusion.
167 */
168 public static PlatformHook platform;
169
170 /**
171 * Wheather or not the java vm is openjdk
172 * We use this to work around openjdk bugs
173 */
174 public static boolean isOpenjdk;
175
176 /**
177 * Set or clear (if passed <code>null</code>) the map.
178 */
179 public final void setMapFrame(final MapFrame map) {
180 MapFrame old = Main.map;
181 panel.setVisible(false);
182 panel.removeAll();
183 if (map != null) {
184 map.fillPanel(panel);
185 } else {
186 old.destroy();
187 panel.add(gettingStarted, BorderLayout.CENTER);
188 }
189 panel.setVisible(true);
190 redoUndoListener.commandChanged(0,0);
191
192 Main.map = map;
193
194 PluginHandler.notifyMapFrameChanged(old, map);
195 }
196
197 /**
198 * Remove the specified layer from the map. If it is the last layer,
199 * remove the map as well.
200 */
201 public final void removeLayer(final Layer layer) {
202 if (map != null) {
203 map.mapView.removeLayer(layer);
204 if (map.mapView.getAllLayers().isEmpty()) {
205 setMapFrame(null);
206 }
207 }
208 }
209
210 public Main() {
211 main = this;
212 isOpenjdk = System.getProperty("java.vm.name").toUpperCase().indexOf("OPENJDK") != -1;
213 platform.startupHook();
214
215 // We try to establish an API connection early, so that any API
216 // capabilities are already known to the editor instance. However
217 // if it goes wrong that's not critical at this stage.
218 try {
219 OsmApi.getOsmApi().initialize(null, true);
220 } catch (Exception x) {
221 // ignore any exception here.
222 }
223
224 contentPanePrivate.add(panel, BorderLayout.CENTER);
225 panel.add(gettingStarted, BorderLayout.CENTER);
226 menu = new MainMenu();
227
228 undoRedo.listenerCommands.add(redoUndoListener);
229
230 // creating toolbar
231 contentPanePrivate.add(toolbar.control, BorderLayout.NORTH);
232
233 registerActionShortcut(menu.help, Shortcut.registerShortcut("system:help", tr("Help"),
234 KeyEvent.VK_F1, Shortcut.GROUP_DIRECT));
235
236 TaggingPresetPreference.initialize();
237 MapPaintPreference.initialize();
238 ImageryPreference.initialize();
239
240 validator = new OsmValidator();
241 MapView.addLayerChangeListener(validator);
242
243 toolbar.refreshToolbarControl();
244
245 toolbar.control.updateUI();
246 contentPanePrivate.updateUI();
247
248 }
249
250 /**
251 * Add a new layer to the map. If no map exists, create one.
252 */
253 public final void addLayer(final Layer layer) {
254 if (map == null) {
255 final MapFrame mapFrame = new MapFrame(contentPanePrivate);
256 setMapFrame(mapFrame);
257 mapFrame.selectMapMode((MapMode)mapFrame.getDefaultButtonAction());
258 mapFrame.setVisible(true);
259 mapFrame.initializeDialogsPane();
260 // bootstrapping problem: make sure the layer list dialog is going to
261 // listen to change events of the very first layer
262 //
263 layer.addPropertyChangeListener(LayerListDialog.getInstance().getModel());
264 }
265 map.mapView.addLayer(layer);
266 }
267
268 /**
269 * Replies true if there is an edit layer
270 *
271 * @return true if there is an edit layer
272 */
273 public boolean hasEditLayer() {
274 if (getEditLayer() == null) return false;
275 return true;
276 }
277
278 /**
279 * Replies the current edit layer
280 *
281 * @return the current edit layer. null, if no current edit layer exists
282 */
283 public OsmDataLayer getEditLayer() {
284 if (map == null) return null;
285 if (map.mapView == null) return null;
286 return map.mapView.getEditLayer();
287 }
288
289 /**
290 * Replies the current data set.
291 *
292 * @return the current data set. null, if no current data set exists
293 */
294 public DataSet getCurrentDataSet() {
295 if (!hasEditLayer()) return null;
296 return getEditLayer().data;
297 }
298
299 /**
300 * Returns the currently active layer
301 *
302 * @return the currently active layer. null, if currently no active layer exists
303 */
304 public Layer getActiveLayer() {
305 if (map == null) return null;
306 if (map.mapView == null) return null;
307 return map.mapView.getActiveLayer();
308 }
309
310 protected static JPanel contentPanePrivate = new JPanel(new BorderLayout());
311
312 /**
313 * @deprecated If you just need to register shortcut for action, use registerActionShortcut instead of accessing InputMap directly
314 */
315 @Deprecated
316 public static final JPanel contentPane = contentPanePrivate;
317
318 public static void registerActionShortcut(Action action, Shortcut shortcut) {
319 registerActionShortcut(action, shortcut.getKeyStroke());
320 }
321
322 public static void registerActionShortcut(Action action, KeyStroke keyStroke) {
323 if (keyStroke == null)
324 return;
325
326 InputMap inputMap = contentPanePrivate.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
327 Object existing = inputMap.get(keyStroke);
328 if (existing != null && !existing.equals(action)) {
329 System.out.println(String.format("Keystroke %s is already assigned to %s, will be overridden by %s", keyStroke, existing, action));
330 }
331 inputMap.put(keyStroke, action);
332
333 contentPanePrivate.getActionMap().put(action, action);
334 }
335
336 public static void unregisterActionShortcut(Shortcut shortcut) {
337 contentPanePrivate.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).remove(shortcut.getKeyStroke());
338 }
339
340 public static void unregisterActionShortcut(JosmAction action) {
341 unregisterActionShortcut(action, action.getShortcut());
342 }
343
344 public static void unregisterActionShortcut(Action action, Shortcut shortcut) {
345 contentPanePrivate.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).remove(shortcut.getKeyStroke());
346 contentPanePrivate.getActionMap().remove(action);
347 }
348
349
350 ///////////////////////////////////////////////////////////////////////////
351 // Implementation part
352 ///////////////////////////////////////////////////////////////////////////
353
354 public static JPanel panel = new JPanel(new BorderLayout());
355
356 protected static Rectangle bounds;
357 protected static int windowState = JFrame.NORMAL;
358
359 private final CommandQueueListener redoUndoListener = new CommandQueueListener(){
360 public void commandChanged(final int queueSize, final int redoSize) {
361 menu.undo.setEnabled(queueSize > 0);
362 menu.redo.setEnabled(redoSize > 0);
363 }
364 };
365
366 /**
367 * Should be called before the main constructor to setup some parameter stuff
368 * @param args The parsed argument list.
369 */
370 public static void preConstructorInit(Map<String, Collection<String>> args) {
371 ProjectionPreference.setProjection();
372
373 try {
374 String defaultlaf = platform.getDefaultStyle();
375 String laf = Main.pref.get("laf", defaultlaf);
376 try {
377 UIManager.setLookAndFeel(laf);
378 }
379 catch (final java.lang.ClassNotFoundException e) {
380 System.out.println("Look and Feel not found: " + laf);
381 Main.pref.put("laf", defaultlaf);
382 }
383 catch (final javax.swing.UnsupportedLookAndFeelException e) {
384 System.out.println("Look and Feel not supported: " + laf);
385 Main.pref.put("laf", defaultlaf);
386 }
387 toolbar = new ToolbarPreferences();
388 contentPanePrivate.updateUI();
389 panel.updateUI();
390 } catch (final Exception e) {
391 e.printStackTrace();
392 }
393 UIManager.put("OptionPane.okIcon", ImageProvider.get("ok"));
394 UIManager.put("OptionPane.yesIcon", UIManager.get("OptionPane.okIcon"));
395 UIManager.put("OptionPane.cancelIcon", ImageProvider.get("cancel"));
396 UIManager.put("OptionPane.noIcon", UIManager.get("OptionPane.cancelIcon"));
397
398 I18n.translateJavaInternalMessages();
399
400 // init default coordinate format
401 //
402 try {
403 //CoordinateFormat format = CoordinateFormat.valueOf(Main.pref.get("coordinates"));
404 CoordinateFormat.setCoordinateFormat(CoordinateFormat.valueOf(Main.pref.get("coordinates")));
405 } catch (IllegalArgumentException iae) {
406 CoordinateFormat.setCoordinateFormat(CoordinateFormat.DECIMAL_DEGREES);
407 }
408
409 Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
410 String geometry = null;
411 if (args.containsKey("geometry")) {
412 geometry = args.get("geometry").iterator().next();
413 } else {
414 geometry = Main.pref.get("gui.geometry");
415 }
416 if (geometry.length() != 0) {
417 final Matcher m = Pattern.compile("(\\d+)x(\\d+)(([+-])(\\d+)([+-])(\\d+))?").matcher(geometry);
418 if (m.matches()) {
419 int w = Integer.valueOf(m.group(1));
420 int h = Integer.valueOf(m.group(2));
421 int x = 0, y = 0;
422 if (m.group(3) != null) {
423 x = Integer.valueOf(m.group(5));
424 y = Integer.valueOf(m.group(7));
425 if (m.group(4).equals("-")) {
426 x = screenDimension.width - x - w;
427 }
428 if (m.group(6).equals("-")) {
429 y = screenDimension.height - y - h;
430 }
431 }
432 // copied from WindowsGeometry.applySafe()
433 if (x > Toolkit.getDefaultToolkit().getScreenSize().width - 10) {
434 x = 0;
435 }
436 if (y > Toolkit.getDefaultToolkit().getScreenSize().height - 10) {
437 y = 0;
438 }
439 bounds = new Rectangle(x,y,w,h);
440 if(!Main.pref.get("gui.geometry").equals(geometry)) {
441 // remember this geometry
442 // Main.debug("Main window: saving geometry \"" + geometry + "\"");
443 Main.pref.put("gui.geometry", geometry);
444 }
445 } else {
446 System.out.println("Ignoring malformed geometry: "+geometry);
447 }
448 }
449 if (bounds == null) {
450 bounds = !args.containsKey("no-maximize") ? new Rectangle(0,0,screenDimension.width,screenDimension.height) : new Rectangle(1000,740);
451 }
452 // Main.debug("window geometry: "+bounds);
453 }
454
455 public void postConstructorProcessCmdLine(Map<String, Collection<String>> args) {
456 if (args.containsKey("download")) {
457 List<File> fileList = new ArrayList<File>();
458 for (String s : args.get("download")) {
459 File f = null;
460 switch(paramType(s)) {
461 case httpUrl:
462 downloadFromParamHttp(false, s);
463 break;
464 case bounds:
465 downloadFromParamBounds(false, s);
466 break;
467 case fileUrl:
468 try {
469 f = new File(new URI(s));
470 } catch (URISyntaxException e) {
471 JOptionPane.showMessageDialog(
472 Main.parent,
473 tr("Ignoring malformed file URL: \"{0}\"", s),
474 tr("Warning"),
475 JOptionPane.WARNING_MESSAGE
476 );
477 }
478 if (f!=null) {
479 fileList.add(f);
480 }
481 break;
482 case fileName:
483 f = new File(s);
484 fileList.add(f);
485 break;
486 }
487 }
488 if(!fileList.isEmpty())
489 {
490 OpenFileAction.openFiles(fileList, true);
491 }
492 }
493 if (args.containsKey("downloadgps")) {
494 for (String s : args.get("downloadgps")) {
495 switch(paramType(s)) {
496 case httpUrl:
497 downloadFromParamHttp(true, s);
498 break;
499 case bounds:
500 downloadFromParamBounds(true, s);
501 break;
502 case fileUrl:
503 case fileName:
504 JOptionPane.showMessageDialog(
505 Main.parent,
506 tr("Parameter \"downloadgps\" does not accept file names or file URLs"),
507 tr("Warning"),
508 JOptionPane.WARNING_MESSAGE
509 );
510 }
511 }
512 }
513 if (args.containsKey("selection")) {
514 for (String s : args.get("selection")) {
515 SearchAction.search(s, SearchAction.SearchMode.add);
516 }
517 }
518 }
519
520 public static boolean saveUnsavedModifications() {
521 if (map == null) return true;
522 SaveLayersDialog dialog = new SaveLayersDialog(Main.parent);
523 List<OsmDataLayer> layersWithUnmodifiedChanges = new ArrayList<OsmDataLayer>();
524 for (OsmDataLayer l: Main.map.mapView.getLayersOfType(OsmDataLayer.class)) {
525 if (l.requiresSaveToFile() || l.requiresUploadToServer()) {
526 layersWithUnmodifiedChanges.add(l);
527 }
528 }
529 dialog.prepareForSavingAndUpdatingLayersBeforeExit();
530 if (!layersWithUnmodifiedChanges.isEmpty()) {
531 dialog.getModel().populate(layersWithUnmodifiedChanges);
532 dialog.setVisible(true);
533 switch(dialog.getUserAction()) {
534 case CANCEL: return false;
535 case PROCEED: return true;
536 default: return false;
537 }
538 }
539
540 return true;
541 }
542
543 public static boolean exitJosm(boolean exit) {
544 if (Main.saveUnsavedModifications()) {
545 Main.saveGuiGeometry();
546 // Remove all layers because somebody may rely on layerRemoved events (like AutosaveTask)
547 if (Main.isDisplayingMapView()) {
548 Collection<Layer> layers = new ArrayList<Layer>(Main.map.mapView.getAllLayers());
549 for (Layer l: layers) {
550 Main.map.mapView.removeLayer(l);
551 }
552 }
553 if (exit) {
554 System.exit(0);
555 return true;
556 } else
557 return true;
558 } else
559 return false;
560 }
561
562 /**
563 * The type of a command line parameter, to be used in switch statements.
564 * @see paramType
565 */
566 private enum DownloadParamType { httpUrl, fileUrl, bounds, fileName }
567
568 /**
569 * Guess the type of a parameter string specified on the command line with --download= or --downloadgps.
570 * @param s A parameter string
571 * @return The guessed parameter type
572 */
573 private DownloadParamType paramType(String s) {
574 if(s.startsWith("http:")) return DownloadParamType.httpUrl;
575 if(s.startsWith("file:")) return DownloadParamType.fileUrl;
576 final StringTokenizer st = new StringTokenizer(s, ",");
577 // we assume a string with exactly 3 commas is a bounds parameter
578 if (st.countTokens() == 4) return DownloadParamType.bounds;
579 // everything else must be a file name
580 return DownloadParamType.fileName;
581 }
582
583 /**
584 * Download area specified on the command line as OSM URL.
585 * @param rawGps Flag to download raw GPS tracks
586 * @param s The URL parameter
587 */
588 private static void downloadFromParamHttp(final boolean rawGps, String s) {
589 final Bounds b = OsmUrlToBounds.parse(s);
590 if (b == null) {
591 JOptionPane.showMessageDialog(
592 Main.parent,
593 tr("Ignoring malformed URL: \"{0}\"", s),
594 tr("Warning"),
595 JOptionPane.WARNING_MESSAGE
596 );
597 } else {
598 downloadFromParamBounds(rawGps, b);
599 }
600 }
601
602 /**
603 * Download area specified on the command line as bounds string.
604 * @param rawGps Flag to download raw GPS tracks
605 * @param s The bounds parameter
606 */
607 private static void downloadFromParamBounds(final boolean rawGps, String s) {
608 final StringTokenizer st = new StringTokenizer(s, ",");
609 if (st.countTokens() == 4) {
610 Bounds b = new Bounds(
611 new LatLon(Double.parseDouble(st.nextToken()),Double.parseDouble(st.nextToken())),
612 new LatLon(Double.parseDouble(st.nextToken()),Double.parseDouble(st.nextToken()))
613 );
614 downloadFromParamBounds(rawGps, b);
615 }
616 }
617
618 /**
619 * Download area specified as Bounds value.
620 * @param rawGps Flag to download raw GPS tracks
621 * @param b The bounds value
622 * @see downloadFromParamBounds(final boolean rawGps, String s)
623 * @see downloadFromParamHttp
624 */
625 private static void downloadFromParamBounds(final boolean rawGps, Bounds b) {
626 DownloadTask task = rawGps ? new DownloadGpsTask() : new DownloadOsmTask();
627 // asynchronously launch the download task ...
628 Future<?> future = task.download(true, b, null);
629 // ... and the continuation when the download is finished (this will wait for the download to finish)
630 Main.worker.execute(new PostDownloadHandler(task, future));
631 }
632
633 public static void determinePlatformHook() {
634 String os = System.getProperty("os.name");
635 if (os == null) {
636 System.err.println("Your operating system has no name, so I'm guessing its some kind of *nix.");
637 platform = new PlatformHookUnixoid();
638 } else if (os.toLowerCase().startsWith("windows")) {
639 platform = new PlatformHookWindows();
640 } else if (os.equals("Linux") || os.equals("Solaris") ||
641 os.equals("SunOS") || os.equals("AIX") ||
642 os.equals("FreeBSD") || os.equals("NetBSD") || os.equals("OpenBSD")) {
643 platform = new PlatformHookUnixoid();
644 } else if (os.toLowerCase().startsWith("mac os x")) {
645 platform = new PlatformHookOsx();
646 } else {
647 System.err.println("I don't know your operating system '"+os+"', so I'm guessing its some kind of *nix.");
648 platform = new PlatformHookUnixoid();
649 }
650 }
651
652 static public void saveGuiGeometry() {
653 // save the current window geometry and the width of the toggle dialog area
654 String newGeometry = "";
655 String newToggleDlgWidth = null;
656 try {
657 Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
658 int width = (int)bounds.getWidth();
659 int height = (int)bounds.getHeight();
660 int x = (int)bounds.getX();
661 int y = (int)bounds.getY();
662 if (width > screenDimension.width) {
663 width = screenDimension.width;
664 }
665 if (height > screenDimension.height) {
666 width = screenDimension.height;
667 }
668 if (x < 0) {
669 x = 0;
670 }
671 if (y < 0) {
672 y = 0;
673 }
674 newGeometry = width + "x" + height + "+" + x + "+" + y;
675
676 if (map != null) {
677 newToggleDlgWidth = Integer.toString(map.getToggleDlgWidth());
678 if (newToggleDlgWidth.equals(Integer.toString(MapFrame.DEF_TOGGLE_DLG_WIDTH))) {
679 newToggleDlgWidth = "";
680 }
681 }
682 }
683 catch (Exception e) {
684 System.out.println("Failed to get GUI geometry: " + e);
685 e.printStackTrace();
686 }
687 boolean maximized = (windowState & JFrame.MAXIMIZED_BOTH) != 0;
688 // Main.debug("Main window: saving geometry \"" + newGeometry + "\" " + (maximized?"maximized":"normal"));
689 pref.put("gui.maximized", maximized);
690 pref.put("gui.geometry", newGeometry);
691 if (newToggleDlgWidth != null) {
692 pref.put("toggleDialogs.width", newToggleDlgWidth);
693 }
694 }
695 private static class WindowPositionSizeListener extends WindowAdapter implements
696 ComponentListener {
697
698 @Override
699 public void windowStateChanged(WindowEvent e) {
700 Main.windowState = e.getNewState();
701 // Main.debug("Main window state changed to " + Main.windowState);
702 }
703
704 public void componentHidden(ComponentEvent e) {
705 }
706
707 public void componentMoved(ComponentEvent e) {
708 handleComponentEvent(e);
709 }
710
711 public void componentResized(ComponentEvent e) {
712 handleComponentEvent(e);
713 }
714
715 public void componentShown(ComponentEvent e) {
716 }
717
718 private void handleComponentEvent(ComponentEvent e) {
719 Component c = e.getComponent();
720 if (c instanceof JFrame) {
721 if (Main.windowState == JFrame.NORMAL) {
722 Main.bounds = ((JFrame) c).getBounds();
723 // Main.debug("Main window: new geometry " + Main.bounds);
724 } else {
725 // Main.debug("Main window state is " + Main.windowState);
726 }
727 }
728 }
729
730 }
731 public static void addListener() {
732 parent.addComponentListener(new WindowPositionSizeListener());
733 ((JFrame)parent).addWindowStateListener(new WindowPositionSizeListener());
734 }
735
736 public static void checkJava6() {
737 String version = System.getProperty("java.version");
738 if (version != null) {
739 if (version.startsWith("1.6") || version.startsWith("6") ||
740 version.startsWith("1.7") || version.startsWith("7"))
741 return;
742 if (version.startsWith("1.5") || version.startsWith("5")) {
743 JLabel ho = new JLabel("<html>"+
744 tr("<h2>JOSM requires Java version 6.</h2>"+
745 "Detected Java version: {0}.<br>"+
746 "You can <ul><li>update your Java (JRE) or</li>"+
747 "<li>use an earlier (Java 5 compatible) version of JOSM.</li></ul>"+
748 "More Info:", version)+"</html>");
749 JTextArea link = new JTextArea("http://josm.openstreetmap.de/wiki/Help/SystemRequirements");
750 link.setEditable(false);
751 link.setBackground(panel.getBackground());
752 JPanel panel = new JPanel(new GridBagLayout());
753 GridBagConstraints gbc = new GridBagConstraints();
754 gbc.gridwidth = GridBagConstraints.REMAINDER;
755 gbc.anchor = GridBagConstraints.WEST;
756 gbc.weightx = 1.0;
757 panel.add(ho, gbc);
758 panel.add(link, gbc);
759 final String EXIT = tr("Exit JOSM");
760 final String CONTINUE = tr("Continue, try anyway");
761 int ret = JOptionPane.showOptionDialog(null, panel, tr("Error"), JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE, null, new String[] {EXIT, CONTINUE}, EXIT);
762 if (ret == 0) {
763 System.exit(0);
764 }
765 return;
766 }
767 }
768 System.err.println("Error: Could not recognize Java Version: "+version);
769 }
770}
Note: See TracBrowser for help on using the repository browser.