Index: trunk/src/org/openstreetmap/josm/actions/DiskAccessAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/DiskAccessAction.java	(revision 2701)
+++ trunk/src/org/openstreetmap/josm/actions/DiskAccessAction.java	(revision 2702)
@@ -35,7 +35,8 @@
         }
 
+        fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
         fc.setMultiSelectionEnabled(multiple);
         fc.setAcceptAllFileFilterUsed(false);
-        System.out.println("opening fc for extension " + extension);
+        //System.out.println("opening fc for extension " + extension);
         ExtensionFileFilter.applyChoosableImportFileFilters(fc, extension);
 
Index: trunk/src/org/openstreetmap/josm/actions/ExtensionFileFilter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/ExtensionFileFilter.java	(revision 2701)
+++ trunk/src/org/openstreetmap/josm/actions/ExtensionFileFilter.java	(revision 2702)
@@ -15,15 +15,7 @@
 import javax.swing.filechooser.FileFilter;
 
+import org.openstreetmap.josm.io.AllFormatsImporter;
 import org.openstreetmap.josm.io.FileExporter;
 import org.openstreetmap.josm.io.FileImporter;
-import org.openstreetmap.josm.io.GpxExporter;
-import org.openstreetmap.josm.io.GpxImporter;
-import org.openstreetmap.josm.io.NMEAImporter;
-import org.openstreetmap.josm.io.OsmBzip2Exporter;
-import org.openstreetmap.josm.io.OsmBzip2Importer;
-import org.openstreetmap.josm.io.OsmExporter;
-import org.openstreetmap.josm.io.OsmGzipExporter;
-import org.openstreetmap.josm.io.OsmGzipImporter;
-import org.openstreetmap.josm.io.OsmImporter;
 
 /**
@@ -55,4 +47,5 @@
             "org.openstreetmap.josm.io.NMEAImporter",
             "org.openstreetmap.josm.io.OsmBzip2Importer",
+            "org.openstreetmap.josm.io.JpgImporter",
             "org.openstreetmap.josm.io.AllFormatsImporter"
         };
@@ -110,7 +103,4 @@
         LinkedList<ExtensionFileFilter> filters = new LinkedList<ExtensionFileFilter>();
         for (FileImporter importer : importers) {
-            if (filters.contains(importer.filter)) {
-                continue;
-            }
             filters.add(importer.filter);
         }
@@ -225,18 +215,4 @@
     public String getDefaultExtension() {
         return defaultExtension;
-    }
-
-    /**
-     * Dummy importer that adds the "All Formats"-Filter when opening files
-     */
-    public static class AllFormatsImporter extends FileImporter {
-        public AllFormatsImporter() {
-            super(
-                    new ExtensionFileFilter("osm,xml,osm.gz,osm.bz2,osm.bz,gpx,gpx.gz,nmea,nme,nma,txt,wms", "", tr("All Formats")
-                            + " (*.gpx *.osm *.nmea ...)"));
-        }
-        @Override public boolean acceptFile(File pathname) {
-            return false;
-        }
     }
 
Index: trunk/src/org/openstreetmap/josm/actions/OpenFileAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/OpenFileAction.java	(revision 2701)
+++ trunk/src/org/openstreetmap/josm/actions/OpenFileAction.java	(revision 2702)
@@ -9,15 +9,20 @@
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 import javax.swing.JFileChooser;
 import javax.swing.JOptionPane;
+import javax.swing.filechooser.FileFilter;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
+import org.openstreetmap.josm.io.AllFormatsImporter;
 import org.openstreetmap.josm.io.FileImporter;
 import org.openstreetmap.josm.io.IllegalDataException;
 import org.openstreetmap.josm.io.OsmTransferException;
+import org.openstreetmap.josm.tools.MultiMap;
 import org.openstreetmap.josm.tools.Shortcut;
 import org.xml.sax.SAXException;
@@ -46,5 +51,5 @@
             return;
         File[] files = fc.getSelectedFiles();
-        OpenFileTask task = new OpenFileTask(Arrays.asList(files));
+        OpenFileTask task = new OpenFileTask(Arrays.asList(files), fc.getFileFilter());
         Main.worker.submit(task);
     }
@@ -55,18 +60,13 @@
     }
 
-    static public void openFile(File f) throws IOException, IllegalDataException {
-        for (FileImporter importer : ExtensionFileFilter.importers)
-            if (importer.acceptFile(f)) {
-                importer.importData(f);
-            }
-    }
-
     static public class OpenFileTask extends PleaseWaitRunnable {
         private List<File> files;
+        private FileFilter fileFilter;
         private boolean cancelled;
 
-        public OpenFileTask(List<File> files) {
+        public OpenFileTask(List<File> files, FileFilter fileFilter) {
             super(tr("Opening files"), false /* don't ignore exception */);
-            this.files = files;
+            this.files = new ArrayList<File>(files);
+            this.fileFilter = fileFilter;
         }
         @Override
@@ -83,21 +83,85 @@
         protected void realRun() throws SAXException, IOException, OsmTransferException {
             if (files == null || files.isEmpty()) return;
+
+            /**
+             * Find the importer with the chosen file filter
+             */
+            FileImporter chosenImporter = null;
+            for (FileImporter importer : ExtensionFileFilter.importers) {
+                if (fileFilter == importer.filter) {
+                    chosenImporter = importer;
+                }
+            }
+            /**
+             * If the filter wasn't changed in the dialog, chosenImporter is null now.
+             * When the filter was expicitly set to AllFormatsImporter, treat this the same.
+             */
+            if (chosenImporter instanceof AllFormatsImporter) {
+                chosenImporter = null;
+            }
             getProgressMonitor().setTicks(files.size());
-            for (File f : files) {
+
+            if (chosenImporter != null) { // The importer was expicitely chosen, so use it.
+                //System.err.println("Importer: " +chosenImporter.getClass().getName());
+                for (File f : files) {
+                    if (!chosenImporter.acceptFile(f)) {
+                        if (f.isDirectory()) {
+                            JOptionPane.showMessageDialog(
+                                    Main.parent,
+                                    tr("<html>Cannot open directory.<br>Please select a file!"),
+                                    tr("Open file"),
+                                    JOptionPane.INFORMATION_MESSAGE
+                            );
+                            return;
+                        } else
+                            throw new IllegalStateException();
+                    }
+                }
+                importData(chosenImporter, files);
+            }
+            else {    // find apropriate importer
+                MultiMap<FileImporter, File> map = new MultiMap<FileImporter, File>();
+                while (! files.isEmpty()) {
+                    File f = files.get(0);
+                    for (FileImporter importer : ExtensionFileFilter.importers) {
+                        if (importer.acceptFile(f)) {
+                            map.add(importer, f);
+                            files.remove(f);
+                        }
+                    }
+                    if (files.contains(f))
+                        throw new RuntimeException(); // no importer found
+                }
+                List<FileImporter> ims = new ArrayList<FileImporter>(map.keySet());
+                Collections.sort(ims);
+                Collections.reverse(ims);
+                for (FileImporter importer : ims) {
+                    //System.err.println("Using "+importer.getClass().getName());
+                    List<File> files = map.get(importer);
+                    //System.err.println("for files: "+files);
+                    importData(importer, files);
+                }
+            }
+        }
+
+        public void importData(FileImporter importer, List<File> files) {
+            if (importer.isBatchImporter()) {
                 if (cancelled) return;
-                getProgressMonitor().indeterminateSubTask(tr("Opening file ''{0}'' ...", f.getAbsolutePath()));
-                try {
-                    System.out.println("Open file: " + f.getAbsolutePath() + " (" + f.length() + " bytes)");
-                    openFile(f);
-                } catch (Exception e) {
-                    e.printStackTrace();
-                    JOptionPane.showMessageDialog(
-                            Main.parent,
-                            tr("<html>Could not read file ''{0}\''.<br> Error is: <br>{1}</html>", f.getName(), e.getMessage()),
-                            tr("Error"),
-                            JOptionPane.ERROR_MESSAGE
-                    );
+                String msg;
+                if (files.size() == 1) {
+                    msg = tr("Opening 1 file...");
+                } else {
+                    msg = tr("Opening {0} files...", files.size());
                 }
-                getProgressMonitor().worked(1);
+                getProgressMonitor().indeterminateSubTask(msg);
+                importer.importDataHandleExceptions(files);
+                getProgressMonitor().worked(files.size());
+            } else {
+                for (File f : files) {
+                    if (cancelled) return;
+                    getProgressMonitor().indeterminateSubTask(tr("Opening file ''{0}'' ...", f.getAbsolutePath()));
+                    importer.importDataHandleExceptions(f);
+                    getProgressMonitor().worked(1);
+                }
             }
         }
Index: trunk/src/org/openstreetmap/josm/gui/FileDrop.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/FileDrop.java	(revision 2701)
+++ trunk/src/org/openstreetmap/josm/gui/FileDrop.java	(revision 2702)
@@ -77,5 +77,5 @@
                     public void filesDropped( java.io.File[] files ){
                         // start asynchronous loading of files
-                        OpenFileAction.OpenFileTask task = new OpenFileAction.OpenFileTask(Arrays.asList(files));
+                        OpenFileAction.OpenFileTask task = new OpenFileAction.OpenFileTask(Arrays.asList(files), null);
                         Main.worker.submit(task);
                     }
Index: trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 2701)
+++ trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 2702)
@@ -64,8 +64,8 @@
 import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
 import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
-import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
 import org.openstreetmap.josm.gui.layer.markerlayer.AudioMarker;
 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
 import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
+import org.openstreetmap.josm.io.JpgImporter;
 import org.openstreetmap.josm.tools.AudioUtil;
 import org.openstreetmap.josm.tools.DateUtils;
@@ -326,23 +326,13 @@
                 fc.setMultiSelectionEnabled(true);
                 fc.setAcceptAllFileFilterUsed(false);
-                fc.setFileFilter(new FileFilter() {
-                    @Override
-                    public boolean accept(File f) {
-                        return f.isDirectory() || f.getName().toLowerCase().endsWith(".jpg");
-                    }
-
-                    @Override
-                    public String getDescription() {
-                        return tr("JPEG images (*.jpg)");
-                    }
-                });
+                JpgImporter importer = new JpgImporter(GpxLayer.this);
+                fc.setFileFilter(importer.filter);
                 fc.showOpenDialog(Main.parent);
+                LinkedList<File> files = new LinkedList<File>();
                 File[] sel = fc.getSelectedFiles();
                 if (sel == null || sel.length == 0)
                     return;
-                LinkedList<File> files = new LinkedList<File>();
                 addRecursiveFiles(files, sel);
-                Main.pref.put("geoimage.lastdirectory", fc.getCurrentDirectory().getPath());
-                GeoImageLayer.create(files, GpxLayer.this);
+                importer.importDataHandleExceptions(files);
             }
 
Index: trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java	(revision 2701)
+++ trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java	(revision 2702)
@@ -1074,5 +1074,5 @@
         Object item = cbGpx.getSelectedItem();
 
-        if (item == null || ! (item instanceof GpxDataWrapper)) {
+        if (item == null || ((GpxDataWrapper) item).file == null) {
             if (complain) {
                 JOptionPane.showMessageDialog(Main.parent, tr("You should select a GPX track"),
Index: trunk/src/org/openstreetmap/josm/io/AllFormatsImporter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/AllFormatsImporter.java	(revision 2702)
+++ trunk/src/org/openstreetmap/josm/io/AllFormatsImporter.java	(revision 2702)
@@ -0,0 +1,21 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.File;
+
+import org.openstreetmap.josm.actions.ExtensionFileFilter;
+
+/**
+ * Dummy importer that adds the "All Formats"-Filter when opening files
+ */
+public class AllFormatsImporter extends FileImporter {
+    public AllFormatsImporter() {
+        super(new ExtensionFileFilter("osm,xml,osm.gz,osm.bz2,osm.bz,gpx,gpx.gz,nmea,nme,nma,log,txt,wms,jpg", "", tr("All Formats")
+                    + " (*.gpx *.osm *.nmea *.jpg ...)"));
+    }
+    @Override public boolean acceptFile(File pathname) {
+        return false;
+    }
+}
Index: trunk/src/org/openstreetmap/josm/io/FileImporter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/FileImporter.java	(revision 2701)
+++ trunk/src/org/openstreetmap/josm/io/FileImporter.java	(revision 2702)
@@ -6,8 +6,12 @@
 import java.io.File;
 import java.io.IOException;
+import java.util.List;
 
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.ExtensionFileFilter;
 
-public abstract class FileImporter {
+public abstract class FileImporter implements Comparable<FileImporter> {
 
     public ExtensionFileFilter filter;
@@ -21,7 +25,68 @@
     }
 
+    /**
+     * A batch importer is a file importer that preferes to read multiple files at the same time.
+     */
+    public boolean isBatchImporter() {
+        return false;
+    }
+    
+    /**
+     * Needs to be implemented if isBatchImporter() returns false.
+     */
     public void importData(File file) throws IOException, IllegalDataException {
-        throw new IOException(tr("Could not read ''{0}''.", file.getName()));
+        throw new IOException(tr("Could not import ''{0}''.", file.getName()));
     }
 
+    /**
+     * Needs to be implemented if isBatchImporter() returns true.
+     */
+    public void importData(List<File> files) throws IOException, IllegalDataException {
+        throw new IOException(tr("Could not import Files."));
+    }
+
+    /**
+     * Wrapper to give meaningful output if things go wrong.
+     */
+    public void importDataHandleExceptions(File f) {
+        try {
+            System.out.println("Open file: " + f.getAbsolutePath() + " (" + f.length() + " bytes)");
+            importData(f);
+        } catch (Exception e) {
+            e.printStackTrace();
+            JOptionPane.showMessageDialog(
+                    Main.parent,
+                    tr("<html>Could not read file ''{0}\''.<br> Error is: <br>{1}</html>", f.getName(), e.getMessage()),
+                    tr("Error"),
+                    JOptionPane.ERROR_MESSAGE
+            );
+        }
+    }
+    public void importDataHandleExceptions(List<File> files) {
+        try {
+            System.out.println("Open "+files.size()+" files");
+            importData(files);
+        } catch (Exception e) {
+            e.printStackTrace();
+            JOptionPane.showMessageDialog(
+                    Main.parent,
+                    tr("<html>Could not read files.<br> Error is: <br>{0}</html>", e.getMessage()),
+                    tr("Error"),
+                    JOptionPane.ERROR_MESSAGE
+            );
+        }
+    }
+
+    /**
+     * If multiple files (with multiple file formats) are selected, 
+     * they are opened in the order of their priorities.
+     * Highest priority comes first.
+     */
+    public double getPriority() {
+        return 0;
+    }
+
+    public int compareTo(FileImporter other) {
+        return (new Double(this.getPriority())).compareTo(other.getPriority());
+    }
 }
Index: trunk/src/org/openstreetmap/josm/io/JpgImporter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/JpgImporter.java	(revision 2702)
+++ trunk/src/org/openstreetmap/josm/io/JpgImporter.java	(revision 2702)
@@ -0,0 +1,64 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.LinkedList;
+
+import org.openstreetmap.josm.actions.ExtensionFileFilter;
+import org.openstreetmap.josm.gui.layer.GpxLayer;
+import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
+
+public class JpgImporter extends FileImporter {
+    private GpxLayer gpx;
+
+    public JpgImporter() {
+        super(new ExtensionFileFilter("jpg", "jpg", tr("Image Files") + " (*.jpg, "+ tr("folder")+")"));
+    }
+
+    public JpgImporter(GpxLayer gpx) {
+        this();
+        this.gpx = gpx;
+    }
+
+    @Override
+    public boolean acceptFile(File pathname) {
+        return super.acceptFile(pathname) || pathname.isDirectory();
+    }
+
+    @Override
+    public void importData(List<File> sel) throws IOException, IllegalDataException {
+        if (sel == null || sel.size() == 0)
+            return;
+        LinkedList<File> files = new LinkedList<File>();
+        addRecursiveFiles(files, sel);
+        GeoImageLayer.create(files, gpx);
+    }
+
+    private void addRecursiveFiles(LinkedList<File> files, List<File> sel) {
+        for (File f : sel) {
+            if (f.isDirectory()) {
+                addRecursiveFiles(files, Arrays.asList(f.listFiles()));
+            } else if (f.getName().toLowerCase().endsWith(".jpg")) {
+                files.add(f);
+            }
+        }
+    }
+
+    @Override
+    public boolean isBatchImporter() {
+        return true;
+    }
+
+    /**
+     * Needs to be the last, to avoid problems.
+     */
+    @Override
+    public double getPriority() {
+        return -1000;
+    }
+}
Index: trunk/src/org/openstreetmap/josm/tools/MultiMap.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/MultiMap.java	(revision 2702)
+++ trunk/src/org/openstreetmap/josm/tools/MultiMap.java	(revision 2702)
@@ -0,0 +1,20 @@
+// License: GPL. See LICENSE file for details.
+package org.openstreetmap.josm.tools;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.HashMap;
+
+/**
+ * Maps keys to a list of values. Partial implementation. Extend if you need more!
+ */
+public class MultiMap<A, B> extends HashMap<A, List<B>> {
+    public void add(A key, B value) {
+        List<B> vals = get(key);
+        if (vals == null) {
+            vals = new ArrayList<B>();
+            put(key, vals);
+        }
+        vals.add(value);
+    }
+}
