Changeset 5538 in josm for trunk/src/org/openstreetmap/josm


Ignore:
Timestamp:
2012-10-20T09:08:17+02:00 (12 years ago)
Author:
bastiK
Message:

move window switch listener to Main class, because it is needed in a plugin

Location:
trunk/src/org/openstreetmap/josm
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/Main.java

    r5519 r5538  
    77import java.awt.GridBagConstraints;
    88import java.awt.GridBagLayout;
     9import java.awt.Window;
    910import java.awt.event.ComponentEvent;
    1011import java.awt.event.ComponentListener;
     
    1819import java.text.MessageFormat;
    1920import java.util.ArrayList;
     21import java.util.Arrays;
    2022import java.util.Collection;
    2123import java.util.Iterator;
     
    912914            synchronized(Main.class) {
    913915                Iterator<WeakReference<ProjectionChangeListener>> it = listeners.iterator();
    914                 while(it.hasNext()){
     916                while (it.hasNext()){
    915917                    WeakReference<ProjectionChangeListener> wr = it.next();
    916918                    ProjectionChangeListener listener = wr.get();
     
    930932
    931933    /**
    932      * Register a projection change listener
     934     * Register a projection change listener.
    933935     *
    934936     * @param listener the listener. Ignored if <code>null</code>.
     
    946948
    947949    /**
    948      * Removes a projection change listener
     950     * Removes a projection change listener.
    949951     *
    950952     * @param listener the listener. Ignored if <code>null</code>.
     
    954956        synchronized(Main.class){
    955957            Iterator<WeakReference<ProjectionChangeListener>> it = listeners.iterator();
    956             while(it.hasNext()){
     958            while (it.hasNext()){
    957959                WeakReference<ProjectionChangeListener> wr = it.next();
    958                 // remove the listener - and any other listener which god garbage
     960                // remove the listener - and any other listener which got garbage
    959961                // collected in the meantime
    960962                if (wr.get() == null || wr.get() == listener) {
     
    964966        }
    965967    }
     968
     969    /**
     970     * Listener for window switch events.
     971     *
     972     * These are events, when the user activates a window of another application
     973     * or comes back to JOSM. Window switches from one JOSM window to another
     974     * are not reported.
     975     */
     976    public static interface WindowSwitchListener {
     977        /**
     978         * Called when the user activates a window of another application.
     979         */
     980        void toOtherApplication();
     981        /**
     982         * Called when the user comes from a window of another application
     983         * back to JOSM.
     984         */
     985        void fromOtherApplication();
     986    }
     987
     988    private static final ArrayList<WeakReference<WindowSwitchListener>> windowSwitchListeners = new ArrayList<WeakReference<WindowSwitchListener>>();
     989
     990    /**
     991     * Register a window switch listener.
     992     *
     993     * @param listener the listener. Ignored if <code>null</code>.
     994     */
     995    public static void addWindowSwitchListener(WindowSwitchListener listener) {
     996        if (listener == null) return;
     997        synchronized (Main.class) {
     998            for (WeakReference<WindowSwitchListener> wr : windowSwitchListeners) {
     999                // already registered ? => abort
     1000                if (wr.get() == listener) return;
     1001            }
     1002            boolean wasEmpty = windowSwitchListeners.isEmpty();
     1003            windowSwitchListeners.add(new WeakReference<WindowSwitchListener>(listener));
     1004            if (wasEmpty) {
     1005                // The following call will have no effect, when there is no window
     1006                // at the time. Therefore, MasterWindowListener.setup() will also be
     1007                // called, as soon as the main window is shown.
     1008                MasterWindowListener.setup();
     1009            }
     1010        }
     1011    }
     1012
     1013    /**
     1014     * Removes a window switch listener.
     1015     *
     1016     * @param listener the listener. Ignored if <code>null</code>.
     1017     */
     1018    public static void removeWindowSwitchListener(WindowSwitchListener listener) {
     1019        if (listener == null) return;
     1020        synchronized (Main.class){
     1021            Iterator<WeakReference<WindowSwitchListener>> it = windowSwitchListeners.iterator();
     1022            while (it.hasNext()){
     1023                WeakReference<WindowSwitchListener> wr = it.next();
     1024                // remove the listener - and any other listener which got garbage
     1025                // collected in the meantime
     1026                if (wr.get() == null || wr.get() == listener) {
     1027                    it.remove();
     1028                }
     1029            }
     1030            if (windowSwitchListeners.isEmpty()) {
     1031                MasterWindowListener.teardown();
     1032            }
     1033        }
     1034    }
     1035
     1036    /**
     1037     * WindowListener, that is registered on all Windows of the application.
     1038     *
     1039     * Its purpose is to notify WindowSwitchListeners, that the user switches to
     1040     * another application, e.g. a browser, or back to JOSM.
     1041     *
     1042     * When changing from JOSM to another application and back (e.g. two times
     1043     * alt+tab), the active Window within JOSM may be different.
     1044     * Therefore, we need to register listeners to <strong>all</strong> (visible)
     1045     * Windows in JOSM, and it does not suffice to monitor the one that was
     1046     * deactivated last.
     1047     *
     1048     * This class is only "active" on demand, i.e. when there is at least one
     1049     * WindowSwitchListener registered.
     1050     */
     1051    protected static class MasterWindowListener extends WindowAdapter {
     1052
     1053        private static MasterWindowListener INSTANCE;
     1054
     1055        public static MasterWindowListener getInstance() {
     1056            if (INSTANCE == null) {
     1057                INSTANCE = new MasterWindowListener();
     1058            }
     1059            return INSTANCE;
     1060        }
     1061
     1062        /**
     1063         * Register listeners to all non-hidden windows.
     1064         *
     1065         * Windows that are created later, will be cared for in {@link #windowDeactivated(WindowEvent)}.
     1066         */
     1067        public static void setup() {
     1068            if (!windowSwitchListeners.isEmpty()) {
     1069                for (Window w : Window.getWindows()) {
     1070                    if (w.isShowing()) {
     1071                        if (!Arrays.asList(w.getWindowListeners()).contains(getInstance())) {
     1072                            w.addWindowListener(getInstance());
     1073                        }
     1074                    }
     1075                }
     1076            }
     1077        }
     1078
     1079        /**
     1080         * Unregister all listeners.
     1081         */
     1082        public static void teardown() {
     1083            for (Window w : Window.getWindows()) {
     1084                w.removeWindowListener(getInstance());
     1085            }
     1086        }
     1087
     1088        @Override
     1089        public void windowActivated(WindowEvent e) {
     1090            if (e.getOppositeWindow() == null) { // we come from a window of a different application
     1091                // fire WindowSwitchListeners
     1092                synchronized (Main.class) {
     1093                    Iterator<WeakReference<WindowSwitchListener>> it = windowSwitchListeners.iterator();
     1094                    while (it.hasNext()){
     1095                        WeakReference<WindowSwitchListener> wr = it.next();
     1096                        WindowSwitchListener listener = wr.get();
     1097                        if (listener == null) {
     1098                            it.remove();
     1099                            continue;
     1100                        }
     1101                        listener.fromOtherApplication();
     1102                    }
     1103                }
     1104            }
     1105        }
     1106
     1107        @Override
     1108        public void windowDeactivated(WindowEvent e) {
     1109            // set up windows that have been created in the meantime
     1110            for (Window w : Window.getWindows()) {
     1111                if (!w.isShowing()) {
     1112                    w.removeWindowListener(getInstance());
     1113                } else {
     1114                    if (!Arrays.asList(w.getWindowListeners()).contains(getInstance())) {
     1115                        w.addWindowListener(getInstance());
     1116                    }
     1117                }
     1118            }
     1119            if (e.getOppositeWindow() == null) { // we go to a window of a different application
     1120                // fire WindowSwitchListeners
     1121                synchronized (Main.class) {
     1122                    Iterator<WeakReference<WindowSwitchListener>> it = windowSwitchListeners.iterator();
     1123                    while (it.hasNext()){
     1124                        WeakReference<WindowSwitchListener> wr = it.next();
     1125                        WindowSwitchListener listener = wr.get();
     1126                        if (listener == null) {
     1127                            it.remove();
     1128                            continue;
     1129                        }
     1130                        listener.toOtherApplication();
     1131                    }
     1132                }
     1133            }
     1134        }
     1135    }
     1136
    9661137}
  • trunk/src/org/openstreetmap/josm/gui/MainApplication.java

    r5365 r5538  
    351351        splash.dispose();
    352352        mainFrame.setVisible(true);
     353        Main.MasterWindowListener.setup();
    353354
    354355        boolean maximized = Boolean.parseBoolean(Main.pref.get("gui.maximized"));
  • trunk/src/org/openstreetmap/josm/gui/dialogs/MapPaintDialog.java

    r5463 r5538  
    7878import org.openstreetmap.josm.tools.Utils;
    7979
    80 public class MapPaintDialog extends ToggleDialog {
     80public class MapPaintDialog extends ToggleDialog implements Main.WindowSwitchListener {
    8181
    8282    protected StylesTable tblStyles;
     
    178178    }
    179179
    180     /**
    181      * Reload local styles when they have been changed in an external editor.
    182      *
    183      * Checks file modification time when an WindowEvent is invoked. Because
    184      * any dialog window can get activated, when switching to another app and back,
    185      * we have to register listeners to all windows in JOSM.
    186      */
    187     protected static class ReloadWindowListener extends WindowAdapter {
    188 
    189         private static ReloadWindowListener INSTANCE;
    190 
    191         public static ReloadWindowListener getInstance() {
    192             if (INSTANCE == null) {
    193                 INSTANCE = new ReloadWindowListener();
    194             }
    195             return INSTANCE;
    196         }
    197 
    198         public static void setup() {
    199             for (Window w : Window.getWindows()) {
    200                 if (w.isShowing()) {
    201                     w.addWindowListener(getInstance());
     180    @Override
     181    public void toOtherApplication() {
     182        // nothing
     183    }
     184
     185    @Override
     186    public void fromOtherApplication() {
     187        // Reload local styles when they have been changed in an external editor.
     188        // Checks file modification time.
     189        List<StyleSource> toReload = new ArrayList<StyleSource>();
     190        for (StyleSource s : MapPaintStyles.getStyles().getStyleSources()) {
     191            if (s.isLocal()) {
     192                File f = new File(s.url);
     193                long mtime = f.lastModified();
     194                if (mtime > s.getLastMTime()) {
     195                    toReload.add(s);
     196                    s.setLastMTime(mtime);
    202197                }
    203198            }
    204199        }
    205 
    206         public static void teardown() {
    207             for (Window w : Window.getWindows()) {
    208                 w.removeWindowListener(getInstance());
    209             }
    210         }
    211 
    212         @Override
    213         public void windowActivated(WindowEvent e) {
    214             if (e.getOppositeWindow() == null) { // we come from a native window, e.g. editor
    215                 // reload local styles, if necessary
    216                 List<StyleSource> toReload = new ArrayList<StyleSource>();
    217                 for (StyleSource s : MapPaintStyles.getStyles().getStyleSources()) {
    218                     if (s.isLocal()) {
    219                         File f = new File(s.url);
    220                         long mtime = f.lastModified();
    221                         if (mtime > s.getLastMTime()) {
    222                             toReload.add(s);
    223                             s.setLastMTime(mtime);
    224                         }
    225                     }
    226                 }
    227                 if (!toReload.isEmpty()) {
    228                     System.out.println(trn("Reloading {0} map style.", "Reloading {0} map styles.", toReload.size(), toReload.size()));
    229                     Main.worker.submit(new MapPaintStyleLoader(toReload));
    230                 }
    231             }
    232         }
    233 
    234         @Override
    235         public void windowDeactivated(WindowEvent e) {
    236             // set up windows that have been created in the meantime
    237             for (Window w : Window.getWindows()) {
    238                 w.removeWindowListener(getInstance());
    239                 if (w.isShowing()) {
    240                     w.addWindowListener(getInstance());
    241                 }
    242             }
     200        if (!toReload.isEmpty()) {
     201            System.out.println(trn("Reloading {0} map style.", "Reloading {0} map styles.", toReload.size(), toReload.size()));
     202            Main.worker.submit(new MapPaintStyleLoader(toReload));
    243203        }
    244204    }
     
    249209        Main.main.menu.wireFrameToggleAction.addButtonModel(cbWireframe.getModel());
    250210        if (Main.pref.getBoolean("mappaint.auto_reload_local_styles", true)) {
    251             ReloadWindowListener.setup();
     211            Main.addWindowSwitchListener(this);
    252212        }
    253213    }
     
    258218        MapPaintStyles.removeMapPaintSylesUpdateListener(model);
    259219        if (Main.pref.getBoolean("mappaint.auto_reload_local_styles", true)) {
    260             ReloadWindowListener.teardown();
     220            Main.removeWindowSwitchListener(this);
    261221        }
    262222    }
Note: See TracChangeset for help on using the changeset viewer.