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

Last change on this file since 3734 was 3715, checked in by Upliner, 13 years ago

Added imagery plugin to josm core. Imagery plugin is union of wmsplugin and slippymap plugins. It includes code by Tim Waters, Petr Dlouhý, Frederik Ramm and others. Also enables the remotecontol which was integrated in [3707].

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