Index: trunk/src/org/openstreetmap/josm/Main.java
===================================================================
--- trunk/src/org/openstreetmap/josm/Main.java	(revision 7184)
+++ trunk/src/org/openstreetmap/josm/Main.java	(revision 7185)
@@ -88,4 +88,5 @@
 import org.openstreetmap.josm.gui.util.RedirectInputMap;
 import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
+import org.openstreetmap.josm.io.FileWatcher;
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
@@ -198,4 +199,9 @@
      */
     public OsmValidator validator;
+
+    /**
+     * The file watcher service.
+     */
+    public static final FileWatcher fileWatcher = new FileWatcher();
 
     /**
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/MapPaintDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/MapPaintDialog.java	(revision 7184)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/MapPaintDialog.java	(revision 7185)
@@ -3,5 +3,4 @@
 
 import static org.openstreetmap.josm.tools.I18n.tr;
-import static org.openstreetmap.josm.tools.I18n.trn;
 
 import java.awt.Component;
@@ -66,5 +65,4 @@
 import org.openstreetmap.josm.gui.SideButton;
 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
-import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.MapPaintStyleLoader;
 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.MapPaintSylesUpdateListener;
 import org.openstreetmap.josm.gui.mappaint.StyleSource;
@@ -83,5 +81,5 @@
 import org.openstreetmap.josm.tools.Utils;
 
-public class MapPaintDialog extends ToggleDialog implements Main.WindowSwitchListener {
+public class MapPaintDialog extends ToggleDialog {
 
     protected StylesTable tblStyles;
@@ -191,36 +189,7 @@
 
     @Override
-    public void toOtherApplication() {
-        // nothing
-    }
-
-    @Override
-    public void fromOtherApplication() {
-        // Reload local styles when they have been changed in an external editor.
-        // Checks file modification time.
-        List<StyleSource> toReload = new ArrayList<>();
-        for (StyleSource s : MapPaintStyles.getStyles().getStyleSources()) {
-            if (s.isLocal()) {
-                File f = new File(s.url);
-                long mtime = f.lastModified();
-                if (mtime > s.getLastMTime()) {
-                    toReload.add(s);
-                    s.setLastMTime(mtime);
-                }
-            }
-        }
-        if (!toReload.isEmpty()) {
-            Main.info(trn("Reloading {0} map style.", "Reloading {0} map styles.", toReload.size(), toReload.size()));
-            Main.worker.submit(new MapPaintStyleLoader(toReload));
-        }
-    }
-
-    @Override
     public void showNotify() {
         MapPaintStyles.addMapPaintSylesUpdateListener(model);
         Main.main.menu.wireFrameToggleAction.addButtonModel(cbWireframe.getModel());
-        if (Main.pref.getBoolean("mappaint.auto_reload_local_styles", true)) {
-            Main.addWindowSwitchListener(this);
-        }
     }
 
@@ -229,7 +198,4 @@
         Main.main.menu.wireFrameToggleAction.removeButtonModel(cbWireframe.getModel());
         MapPaintStyles.removeMapPaintSylesUpdateListener(model);
-        if (Main.pref.getBoolean("mappaint.auto_reload_local_styles", true)) {
-            Main.removeWindowSwitchListener(this);
-        }
     }
 
@@ -296,8 +262,4 @@
             tblStyles.repaint();
         }
-
-        /**
-         * MapPaintSylesUpdateListener interface
-         */
 
         @Override
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(revision 7184)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(revision 7185)
@@ -4,5 +4,4 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
@@ -206,16 +205,23 @@
         }
         for (StyleSource source : styles.getStyleSources()) {
-            final long startTime = System.currentTimeMillis();
-            source.loadStyleSource();
-            if (Main.pref.getBoolean("mappaint.auto_reload_local_styles", true) && source.isLocal()) {
-                File f = new File(source.url);
-                source.setLastMTime(f.lastModified());
-            }
-            if (Main.isDebugEnabled()) {
-                final long elapsedTime = System.currentTimeMillis() - startTime;
-                Main.debug("Initializing map style " + source.url + " completed in " + Utils.getDurationString(elapsedTime));
-            }
+            loadStyleForFirstTime(source);
         }
         fireMapPaintSylesUpdated();
+    }
+
+    private static void loadStyleForFirstTime(StyleSource source) {
+        final long startTime = System.currentTimeMillis();
+        source.loadStyleSource();
+        if (Main.pref.getBoolean("mappaint.auto_reload_local_styles", true) && source.isLocal()) {
+            try {
+                Main.fileWatcher.registerStyleSource(source);
+            } catch (IOException e) {
+                Main.error(e);
+            }
+        }
+        if (Main.isDebugEnabled()) {
+            final long elapsedTime = System.currentTimeMillis() - startTime;
+            Main.debug("Initializing map style " + source.url + " completed in " + Utils.getDurationString(elapsedTime));
+        }
     }
 
@@ -287,7 +293,7 @@
     public static class MapPaintStyleLoader extends PleaseWaitRunnable {
         private boolean canceled;
-        private List<StyleSource> sources;
-
-        public MapPaintStyleLoader(List<StyleSource> sources) {
+        private Collection<StyleSource> sources;
+
+        public MapPaintStyleLoader(Collection<StyleSource> sources) {
             super(tr("Reloading style sources"));
             this.sources = sources;
@@ -385,5 +391,5 @@
         if (source != null) {
             styles.add(source);
-            source.loadStyleSource();
+            loadStyleForFirstTime(source);
             MapPaintPrefHelper.INSTANCE.put(styles.getStyleSources());
             fireMapPaintSylesUpdated();
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSource.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSource.java	(revision 7184)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSource.java	(revision 7185)
@@ -34,5 +34,4 @@
 
     private ImageIcon imageIcon;
-    private long lastMTime = 0L;
 
     /******
@@ -81,5 +80,5 @@
      */
     public abstract InputStream getSourceInputStream() throws IOException;
-    
+
     /**
      * Returns a new {@code MirroredInputStream} to the local file containing style source (can be a text file or an archive).
@@ -156,11 +155,3 @@
         return null;
     }
-
-    public long getLastMTime() {
-        return lastMTime;
-    }
-
-    public void setLastMTime(long lastMTime) {
-        this.lastMTime = lastMTime;
-    }
 }
Index: trunk/src/org/openstreetmap/josm/io/FileWatcher.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/FileWatcher.java	(revision 7185)
+++ trunk/src/org/openstreetmap/josm/io/FileWatcher.java	(revision 7185)
@@ -0,0 +1,134 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.StandardWatchEventKinds;
+import java.nio.file.WatchEvent;
+import java.nio.file.WatchEvent.Kind;
+import java.nio.file.WatchKey;
+import java.nio.file.WatchService;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.MapPaintStyleLoader;
+import org.openstreetmap.josm.gui.mappaint.StyleSource;
+import org.openstreetmap.josm.tools.CheckParameterUtil;
+
+/**
+ * Background thread that monitors certain files and perform relevant actions when they change.
+ * @since 7185
+ */
+public class FileWatcher {
+
+    private WatchService watcher;
+
+    private final Map<Path, StyleSource> styleMap = new HashMap<>();
+
+    /**
+     * Constructs a new {@code FileWatcher}.
+     */
+    public FileWatcher() {
+        try {
+            watcher = FileSystems.getDefault().newWatchService();
+            new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    processEvents();
+                }
+            }, "File Watcher").start();
+        } catch (IOException e) {
+            Main.error(e);
+        }
+    }
+
+    /**
+     * Registers a map paint style for local file changes, allowing dynamic reloading.
+     * @param style The style to watch
+     * @throws IllegalArgumentException if {@code style} is null or if it does not provide a local file
+     * @throws IllegalStateException if the watcher service failed to start
+     * @throws IOException if an I/O error occurs
+     */
+    public void registerStyleSource(StyleSource style) throws IOException {
+        CheckParameterUtil.ensureParameterNotNull(style, "style");
+        if (watcher == null) {
+            throw new IllegalStateException("File watcher is not available");
+        }
+        try (MirroredInputStream mis = style.getMirroredInputStream()) {
+            // Get underlying file
+            File file = mis.getFile();
+            if (file == null) {
+                throw new IllegalArgumentException("Style "+style+" does not have a local file");
+            }
+            // Get parent directory as WatchService allows only to monitor directories, not single files
+            File dir = file.getParentFile();
+            if (dir == null) {
+                throw new IllegalArgumentException("Style "+style+" does not have a parent directory");
+            }
+            synchronized(this) {
+                // Register directory. Can be called several times for a same directory without problem
+                // (it returns the same key so it should not send events several times)
+                dir.toPath().register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
+                styleMap.put(file.toPath(), style);
+            }
+        }
+    }
+
+    /**
+     * Process all events for the key queued to the watcher.
+     */
+    private void processEvents() {
+        if (Main.isDebugEnabled()) {
+            Main.debug("File watcher thread started");
+        }
+        while (true) {
+
+            // wait for key to be signaled
+            WatchKey key;
+            try {
+                key = watcher.take();
+            } catch (InterruptedException x) {
+                return;
+            }
+
+            for (WatchEvent<?> event: key.pollEvents()) {
+                Kind<?> kind = event.kind();
+
+                if (StandardWatchEventKinds.OVERFLOW.equals(kind)) {
+                    continue;
+                }
+
+                // The filename is the context of the event.
+                @SuppressWarnings("unchecked")
+                WatchEvent<Path> ev = (WatchEvent<Path>)event;
+                Path filename = ev.context();
+                if (filename == null) {
+                    continue;
+                }
+
+                // Only way to get full path (http://stackoverflow.com/a/7802029/2257172)
+                Path fullPath = ((Path)key.watchable()).resolve(filename);
+
+                synchronized(this) {
+                    StyleSource style = styleMap.get(fullPath);
+                    if (style != null) {
+                        Main.info("Map style "+style.getDisplayString()+" has been modified. Reloading style...");
+                        //style.loadStyleSource();
+                        Main.worker.submit(new MapPaintStyleLoader(Collections.singleton(style)));
+                    }
+                }
+            }
+
+            // Reset the key -- this step is critical to receive
+            // further watch events. If the key is no longer valid, the directory
+            // is inaccessible so exit the loop.
+            if (!key.reset()) {
+                break;
+            }
+        }
+    }
+}
