changeset 381:f36f0f189064

6571802: 'Shared Documents' listed in-between C,D drives in the JFileChooser, does not match with native Summary: now sun.awt.shell.ShellFolder#sort uses system sorting instead of alphabetical Reviewed-by: loneid, peterz
author rupashka
date Wed, 04 Jun 2008 18:48:42 +0400
parents af37dad9022d
children e26917dd7b7c
files src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java src/share/classes/sun/awt/shell/ShellFolder.java src/share/classes/sun/awt/shell/ShellFolderManager.java src/windows/classes/sun/awt/shell/Win32ShellFolder2.java src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java
diffstat 5 files changed, 186 insertions(+), 209 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java	Tue Jun 03 18:00:04 2008 +0400
+++ b/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java	Wed Jun 04 18:48:42 2008 +0400
@@ -196,7 +196,7 @@
     }
 
     protected void sort(Vector<? extends File> v){
-        ShellFolder.sortFiles(v);
+        ShellFolder.sort(v);
     }
 
     // Obsolete - not used
--- a/src/share/classes/sun/awt/shell/ShellFolder.java	Tue Jun 03 18:00:04 2008 +0400
+++ b/src/share/classes/sun/awt/shell/ShellFolder.java	Wed Jun 04 18:48:42 2008 +0400
@@ -25,6 +25,7 @@
 
 package sun.awt.shell;
 
+import javax.swing.*;
 import java.awt.Image;
 import java.awt.Toolkit;
 import java.io.*;
@@ -37,6 +38,10 @@
  */
 
 public abstract class ShellFolder extends File {
+    private static final String COLUMN_NAME = "FileChooser.fileNameHeaderText";
+    private static final String COLUMN_SIZE = "FileChooser.fileSizeHeaderText";
+    private static final String COLUMN_DATE = "FileChooser.fileDateHeaderText";
+
     protected ShellFolder parent;
 
     /**
@@ -268,8 +273,45 @@
 
     // Override File methods
 
-    public static void sortFiles(List files) {
-        shellFolderManager.sortFiles(files);
+    public static void sort(List<? extends File> files) {
+        if (files == null || files.size() <= 1) {
+            return;
+        }
+
+        // Check that we can use the ShellFolder.sortChildren() method:
+        //   1. All files have the same non-null parent
+        //   2. All files is ShellFolders
+        File commonParent = null;
+
+        for (File file : files) {
+            File parent = file.getParentFile();
+
+            if (parent == null || !(file instanceof ShellFolder)) {
+                commonParent = null;
+
+                break;
+            }
+
+            if (commonParent == null) {
+                commonParent = parent;
+            } else {
+                if (commonParent != parent && !commonParent.equals(parent)) {
+                    commonParent = null;
+
+                    break;
+                }
+            }
+        }
+
+        if (commonParent instanceof ShellFolder) {
+            ((ShellFolder) commonParent).sortChildren(files);
+        } else {
+            Collections.sort(files, FILE_COMPARATOR);
+        }
+    }
+
+    public void sortChildren(List<? extends File> files) {
+        Collections.sort(files, FILE_COMPARATOR);
     }
 
     public boolean isAbsolute() {
@@ -356,18 +398,131 @@
     }
 
     public static ShellFolderColumnInfo[] getFolderColumns(File dir) {
-        return shellFolderManager.getFolderColumns(dir);
-    }
+        ShellFolderColumnInfo[] columns = null;
 
-    public static Object getFolderColumnValue(File file, int column) {
-        return shellFolderManager.getFolderColumnValue(file, column);
+        if (dir instanceof ShellFolder) {
+            columns = ((ShellFolder) dir).getFolderColumns();
+        }
+
+        if (columns == null) {
+            columns = new ShellFolderColumnInfo[]{
+                    new ShellFolderColumnInfo(COLUMN_NAME, 150,
+                            SwingConstants.LEADING, true, null,
+                            FILE_COMPARATOR),
+                    new ShellFolderColumnInfo(COLUMN_SIZE, 75,
+                            SwingConstants.RIGHT, true, null,
+                            DEFAULT_COMPARATOR, true),
+                    new ShellFolderColumnInfo(COLUMN_DATE, 130,
+                            SwingConstants.LEADING, true, null,
+                            DEFAULT_COMPARATOR, true)
+            };
+        }
+
+        return columns;
     }
 
     public ShellFolderColumnInfo[] getFolderColumns() {
         return null;
     }
 
+    public static Object getFolderColumnValue(File file, int column) {
+        if (file instanceof ShellFolder) {
+            Object value = ((ShellFolder)file).getFolderColumnValue(column);
+            if (value != null) {
+                return value;
+            }
+        }
+
+        if (file == null || !file.exists()) {
+            return null;
+        }
+
+        switch (column) {
+            case 0:
+                // By default, file name will be rendered using getSystemDisplayName()
+                return file;
+
+            case 1: // size
+                return file.isDirectory() ? null : Long.valueOf(file.length());
+
+            case 2: // date
+                if (isFileSystemRoot(file)) {
+                    return null;
+                }
+                long time = file.lastModified();
+                return (time == 0L) ? null : new Date(time);
+
+            default:
+                return null;
+        }
+    }
+
     public Object getFolderColumnValue(int column) {
         return null;
     }
+
+    /**
+     * Provides a default comparator for the default column set
+     */
+    private static final Comparator DEFAULT_COMPARATOR = new Comparator() {
+        public int compare(Object o1, Object o2) {
+            int gt;
+
+            if (o1 == null && o2 == null) {
+                gt = 0;
+            } else if (o1 != null && o2 == null) {
+                gt = 1;
+            } else if (o1 == null && o2 != null) {
+                gt = -1;
+            } else if (o1 instanceof Comparable) {
+                gt = ((Comparable) o1).compareTo(o2);
+            } else {
+                gt = 0;
+            }
+
+            return gt;
+        }
+    };
+
+    private static final Comparator<File> FILE_COMPARATOR = new Comparator<File>() {
+        public int compare(File f1, File f2) {
+            ShellFolder sf1 = null;
+            ShellFolder sf2 = null;
+
+            if (f1 instanceof ShellFolder) {
+                sf1 = (ShellFolder) f1;
+                if (sf1.isFileSystem()) {
+                    sf1 = null;
+                }
+            }
+            if (f2 instanceof ShellFolder) {
+                sf2 = (ShellFolder) f2;
+                if (sf2.isFileSystem()) {
+                    sf2 = null;
+                }
+            }
+
+            if (sf1 != null && sf2 != null) {
+                return sf1.compareTo(sf2);
+            } else if (sf1 != null) {
+                // Non-file shellfolders sort before files
+                return -1;
+            } else if (sf2 != null) {
+                return 1;
+            } else {
+                String name1 = f1.getName();
+                String name2 = f2.getName();
+
+                // First ignore case when comparing
+                int diff = name1.compareToIgnoreCase(name2);
+                if (diff != 0) {
+                    return diff;
+                } else {
+                    // May differ in case (e.g. "mail" vs. "Mail")
+                    // We need this test for consistent sorting
+                    return name1.compareTo(name2);
+                }
+            }
+        }
+    };
 }
--- a/src/share/classes/sun/awt/shell/ShellFolderManager.java	Tue Jun 03 18:00:04 2008 +0400
+++ b/src/share/classes/sun/awt/shell/ShellFolderManager.java	Wed Jun 04 18:48:42 2008 +0400
@@ -27,8 +27,6 @@
 
 import java.io.File;
 import java.io.FileNotFoundException;
-import java.util.*;
-import javax.swing.SwingConstants;
 
 /**
  * @author Michael Martak
@@ -36,10 +34,6 @@
  */
 
 class ShellFolderManager {
-    private static final String COLUMN_NAME = "FileChooser.fileNameHeaderText";
-    private static final String COLUMN_SIZE = "FileChooser.fileSizeHeaderText";
-    private static final String COLUMN_DATE = "FileChooser.fileDateHeaderText";
-
     /**
      * Create a shell folder from a file.
      * Override to return machine-dependent behavior.
@@ -107,142 +101,4 @@
         }
         return (dir.getParentFile() == null);
     }
-
-    public void sortFiles(List files) {
-        Collections.sort(files, fileComparator);
-    }
-
-    private Comparator fileComparator = new Comparator() {
-        public int compare(Object a, Object b) {
-            return compare((File)a, (File)b);
-        }
-
-        public int compare(File f1, File f2) {
-            ShellFolder sf1 = null;
-            ShellFolder sf2 = null;
-
-            if (f1 instanceof ShellFolder) {
-                sf1 = (ShellFolder)f1;
-                if (sf1.isFileSystem()) {
-                    sf1 = null;
-                }
-            }
-            if (f2 instanceof ShellFolder) {
-                sf2 = (ShellFolder)f2;
-                if (sf2.isFileSystem()) {
-                    sf2 = null;
-                }
-            }
-
-            if (sf1 != null && sf2 != null) {
-                return sf1.compareTo(sf2);
-            } else if (sf1 != null) {
-                return -1;      // Non-file shellfolders sort before files
-            } else if (sf2 != null) {
-                return 1;
-            } else {
-                String name1 = f1.getName();
-                String name2 = f2.getName();
-
-                // First ignore case when comparing
-                int diff = name1.toLowerCase().compareTo(name2.toLowerCase());
-                if (diff != 0) {
-                    return diff;
-                } else {
-                    // May differ in case (e.g. "mail" vs. "Mail")
-                    // We need this test for consistent sorting
-                    return name1.compareTo(name2);
-                }
-            }
-        }
-    };
-
-    public ShellFolderColumnInfo[] getFolderColumns(File dir) {
-        ShellFolderColumnInfo[] columns = null;
-
-        if (dir instanceof ShellFolder) {
-            columns = ((ShellFolder)dir).getFolderColumns();
-        }
-
-        if (columns == null) {
-            columns = new ShellFolderColumnInfo[]{
-                new ShellFolderColumnInfo(COLUMN_NAME, 150,
-                        SwingConstants.LEADING, true, null,
-                        fileComparator),
-                new ShellFolderColumnInfo(COLUMN_SIZE, 75,
-                        SwingConstants.RIGHT, true, null,
-                        ComparableComparator.getInstance(), true),
-                new ShellFolderColumnInfo(COLUMN_DATE, 130,
-                        SwingConstants.LEADING, true, null,
-                        ComparableComparator.getInstance(), true)
-            };
-        }
-
-        return columns;
-    }
-
-    public Object getFolderColumnValue(File file, int column) {
-        if (file instanceof ShellFolder) {
-            Object value = ((ShellFolder)file).getFolderColumnValue(column);
-            if (value != null) {
-                return value;
-            }
-        }
-
-        if (file == null || !file.exists()) {
-            return null;
-        }
-
-        switch (column) {
-            case 0:
-                // By default, file name will be rendered using getSystemDisplayName()
-                return file;
-
-            case 1: // size
-                return file.isDirectory() ? null : new Long(file.length());
-
-            case 2: // date
-                if (isFileSystemRoot(file)) {
-                    return null;
-                }
-                long time = file.lastModified();
-                return (time == 0L) ? null : new Date(time);
-
-            default:
-                return null;
-        }
-    }
-
-    /**
-     * This class provides a default comparator for the default column set
-     */
-    private static class ComparableComparator implements Comparator {
-        private static Comparator instance;
-
-        public static Comparator getInstance() {
-            if (instance == null) {
-                instance = new ComparableComparator();
-            }
-            return instance;
-        }
-
-        public int compare(Object o1, Object o2) {
-            int gt;
-
-            if (o1 == null && o2 == null) {
-                gt = 0;
-            } else if (o1 != null && o2 == null) {
-                gt = 1;
-            } else if (o1 == null && o2 != null) {
-                gt = -1;
-            } else if (o1 instanceof Comparable) {
-                gt = ((Comparable) o1).compareTo(o2);
-            } else {
-                gt = 0;
-            }
-
-            return gt;
-        }
-    }
-
 }
--- a/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java	Tue Jun 03 18:00:04 2008 +0400
+++ b/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java	Wed Jun 04 18:48:42 2008 +0400
@@ -306,7 +306,7 @@
      * <code>java.io.File</code> instead. If not, then the object depends
      * on native PIDL state and should not be serialized.
      *
-     * @returns a <code>java.io.File</code> replacement object. If the folder
+     * @return a <code>java.io.File</code> replacement object. If the folder
      * is a not a normal directory, then returns the first non-removable
      * drive (normally "C:\").
      */
@@ -605,10 +605,10 @@
         // parent so we have an IShellFolder to query.
         long pIShellFolder = getIShellFolder();
         // Now we can enumerate the objects in this folder.
-        ArrayList list = new ArrayList();
+        ArrayList<Win32ShellFolder2> list = new ArrayList<Win32ShellFolder2>();
         long pEnumObjects = getEnumObjects(pIShellFolder, includeHiddenFiles);
         if (pEnumObjects != 0) {
-            long childPIDL = 0;
+            long childPIDL;
             int testedAttrs = ATTRIB_FILESYSTEM | ATTRIB_FILESYSANCESTOR;
             do {
                 if (Thread.currentThread().isInterrupted()) {
@@ -635,7 +635,7 @@
             } while (childPIDL != 0);
             releaseEnumObjects(pEnumObjects);
         }
-        return (ShellFolder[])list.toArray(new ShellFolder[list.size()]);
+        return list.toArray(new ShellFolder[list.size()]);
     }
 
 
@@ -648,7 +648,7 @@
         long pIShellFolder = getIShellFolder();
         long pEnumObjects =  getEnumObjects(pIShellFolder, true);
         Win32ShellFolder2 child = null;
-        long childPIDL = 0;
+        long childPIDL;
 
         while ((childPIDL = getNextChild(pEnumObjects)) != 0) {
             if (getAttributes0(pIShellFolder, childPIDL, ATTRIB_FILESYSTEM) != 0) {
@@ -983,7 +983,7 @@
                             ? SwingConstants.CENTER
                                 : SwingConstants.LEADING);
 
-                    column.setComparator(new ColumnComparator(i));
+                    column.setComparator(new ColumnComparator(getIShellFolder(), i));
 
                     notNullColumns.add(column);
                 }
@@ -1002,22 +1002,29 @@
 
     private native Object doGetColumnValue(long parentIShellFolder2, long childPIDL, int columnIdx);
 
-    private native int compareIDsByColumn(long pParentIShellFolder, long pidl1, long pidl2, int columnIdx);
+    private static native int compareIDsByColumn(long pParentIShellFolder, long pidl1, long pidl2, int columnIdx);
 
 
-    private class ColumnComparator implements Comparator {
+    public void sortChildren(List<? extends File> files) {
+        Collections.sort(files, new ColumnComparator(getIShellFolder(), 0));
+    }
+
+    private static class ColumnComparator implements Comparator<File> {
+        private final long parentIShellFolder;
+
         private final int columnIdx;
 
-        public ColumnComparator(int columnIdx) {
+        public ColumnComparator(long parentIShellFolder, int columnIdx) {
+            this.parentIShellFolder = parentIShellFolder;
             this.columnIdx = columnIdx;
         }
 
         // compares 2 objects within this folder by the specified column
-        public int compare(Object o, Object o1) {
+        public int compare(File o, File o1) {
             if (o instanceof Win32ShellFolder2
                     && o1 instanceof Win32ShellFolder2) {
                 // delegates comparison to native method
-                return compareIDsByColumn(getIShellFolder(),
+                return compareIDsByColumn(parentIShellFolder,
                         ((Win32ShellFolder2) o).getRelativePIDL(),
                         ((Win32ShellFolder2) o1).getRelativePIDL(),
                         columnIdx);
--- a/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java	Tue Jun 03 18:00:04 2008 +0400
+++ b/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java	Wed Jun 04 18:48:42 2008 +0400
@@ -234,11 +234,11 @@
                         // Add third level for "My Computer"
                         if (folder.equals(drives)) {
                             File[] thirdLevelFolders = folder.listFiles();
-                            if (thirdLevelFolders != null) {
-                                Arrays.sort(thirdLevelFolders, driveComparator);
-                                for (File thirdLevelFolder : thirdLevelFolders) {
-                                    folders.add(thirdLevelFolder);
-                                }
+                            if (thirdLevelFolders != null && thirdLevelFolders.length > 0) {
+                                List<File> thirdLevelFoldersList = Arrays.asList(thirdLevelFolders);
+
+                                folder.sortChildren(thirdLevelFoldersList);
+                                folders.addAll(thirdLevelFoldersList);
                             }
                         }
                     }
@@ -362,27 +362,6 @@
         return false;
     }
 
-    private Comparator driveComparator = new Comparator() {
-        public int compare(Object o1, Object o2) {
-            Win32ShellFolder2 shellFolder1 = (Win32ShellFolder2) o1;
-            Win32ShellFolder2 shellFolder2 = (Win32ShellFolder2) o2;
-
-            // Put drives at first
-            boolean isDrive1 = shellFolder1.getPath().endsWith(":\\");
-
-            if (isDrive1 ^ shellFolder2.getPath().endsWith(":\\")) {
-                return isDrive1 ? -1 : 1;
-            } else {
-                return shellFolder1.getPath().compareTo(shellFolder2.getPath());
-            }
-        }
-    };
-
-
-    public void sortFiles(List files) {
-        Collections.sort(files, fileComparator);
-    }
-
     private static List topFolderList = null;
     static int compareShellFolders(Win32ShellFolder2 sf1, Win32ShellFolder2 sf2) {
         boolean special1 = sf1.isSpecial();
@@ -418,19 +397,9 @@
         return compareNames(sf1.getAbsolutePath(), sf2.getAbsolutePath());
     }
 
-    static int compareFiles(File f1, File f2) {
-        if (f1 instanceof Win32ShellFolder2) {
-            return f1.compareTo(f2);
-        }
-        if (f2 instanceof Win32ShellFolder2) {
-            return -1 * f2.compareTo(f1);
-        }
-        return compareNames(f1.getName(), f2.getName());
-    }
-
     static int compareNames(String name1, String name2) {
         // First ignore case when comparing
-        int diff = name1.toLowerCase().compareTo(name2.toLowerCase());
+        int diff = name1.compareToIgnoreCase(name2);
         if (diff != 0) {
             return diff;
         } else {
@@ -439,14 +408,4 @@
             return name1.compareTo(name2);
         }
     }
-
-    private Comparator fileComparator = new Comparator() {
-        public int compare(Object a, Object b) {
-            return compare((File)a, (File)b);
-        }
-
-        public int compare(File f1, File f2) {
-            return compareFiles(f1, f2);
-        }
-    };
 }