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
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java Tue Jun 03 18:00:04 2008 +0400
+++ b/jdk/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/jdk/src/share/classes/sun/awt/shell/ShellFolder.java Tue Jun 03 18:00:04 2008 +0400
+++ b/jdk/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;
+
+ if (dir instanceof ShellFolder) {
+ columns = ((ShellFolder) dir).getFolderColumns();
+ }
- public static Object getFolderColumnValue(File file, int column) {
- return shellFolderManager.getFolderColumnValue(file, column);
+ 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/jdk/src/share/classes/sun/awt/shell/ShellFolderManager.java Tue Jun 03 18:00:04 2008 +0400
+++ b/jdk/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/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java Tue Jun 03 18:00:04 2008 +0400
+++ b/jdk/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/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Tue Jun 03 18:00:04 2008 +0400
+++ b/jdk/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);
- }
- };
}