From 03078b2fdc351c86a7fc6efb71909143f75bad91 Mon Sep 17 00:00:00 2001 From: rupashka Date: Wed, 4 Jun 2008 18:48:42 +0400 Subject: [PATCH] 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 --- .../swing/plaf/basic/BasicDirectoryModel.java | 2 +- .../classes/sun/awt/shell/ShellFolder.java | 167 +++++++++++++++++- .../sun/awt/shell/ShellFolderManager.java | 144 --------------- .../sun/awt/shell/Win32ShellFolder2.java | 29 +-- .../awt/shell/Win32ShellFolderManager2.java | 53 +----- 5 files changed, 186 insertions(+), 209 deletions(-) diff --git a/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java b/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java index 06b4dc5b6..6bc400f97 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java @@ -196,7 +196,7 @@ public class BasicDirectoryModel extends AbstractListModel implements PropertyCh } protected void sort(Vector v){ - ShellFolder.sortFiles(v); + ShellFolder.sort(v); } // Obsolete - not used diff --git a/src/share/classes/sun/awt/shell/ShellFolder.java b/src/share/classes/sun/awt/shell/ShellFolder.java index fe891c6ca..21c2d129d 100644 --- a/src/share/classes/sun/awt/shell/ShellFolder.java +++ b/src/share/classes/sun/awt/shell/ShellFolder.java @@ -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 @@ import java.util.*; */ 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 @@ public abstract class ShellFolder extends File { // Override File methods - public static void sortFiles(List files) { - shellFolderManager.sortFiles(files); + public static void sort(List 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 files) { + Collections.sort(files, FILE_COMPARATOR); } public boolean isAbsolute() { @@ -356,18 +398,131 @@ public abstract class ShellFolder extends File { } 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_COMPARATOR = new Comparator() { + 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); + } + } + } + }; } diff --git a/src/share/classes/sun/awt/shell/ShellFolderManager.java b/src/share/classes/sun/awt/shell/ShellFolderManager.java index 592fa1b58..aea1bae22 100644 --- a/src/share/classes/sun/awt/shell/ShellFolderManager.java +++ b/src/share/classes/sun/awt/shell/ShellFolderManager.java @@ -27,8 +27,6 @@ package sun.awt.shell; import java.io.File; import java.io.FileNotFoundException; -import java.util.*; -import javax.swing.SwingConstants; /** * @author Michael Martak @@ -36,10 +34,6 @@ import javax.swing.SwingConstants; */ 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 @@ class ShellFolderManager { } 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; - } - } - } diff --git a/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java b/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java index 74aecd443..0ae33818b 100644 --- a/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java +++ b/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java @@ -306,7 +306,7 @@ final class Win32ShellFolder2 extends ShellFolder { * java.io.File instead. If not, then the object depends * on native PIDL state and should not be serialized. * - * @returns a java.io.File replacement object. If the folder + * @return a java.io.File replacement object. If the folder * is a not a normal directory, then returns the first non-removable * drive (normally "C:\"). */ @@ -605,10 +605,10 @@ final class Win32ShellFolder2 extends ShellFolder { // 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 list = new ArrayList(); 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 @@ final class Win32ShellFolder2 extends ShellFolder { } while (childPIDL != 0); releaseEnumObjects(pEnumObjects); } - return (ShellFolder[])list.toArray(new ShellFolder[list.size()]); + return list.toArray(new ShellFolder[list.size()]); } @@ -648,7 +648,7 @@ final class Win32ShellFolder2 extends ShellFolder { 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 @@ final class Win32ShellFolder2 extends ShellFolder { ? SwingConstants.CENTER : SwingConstants.LEADING); - column.setComparator(new ColumnComparator(i)); + column.setComparator(new ColumnComparator(getIShellFolder(), i)); notNullColumns.add(column); } @@ -1002,22 +1002,29 @@ final class Win32ShellFolder2 extends ShellFolder { 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 files) { + Collections.sort(files, new ColumnComparator(getIShellFolder(), 0)); + } + + private static class ColumnComparator implements Comparator { + 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); diff --git a/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java b/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java index ef3dfa6a4..0c7acf32f 100644 --- a/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java +++ b/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java @@ -234,11 +234,11 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { // 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 thirdLevelFoldersList = Arrays.asList(thirdLevelFolders); + + folder.sortChildren(thirdLevelFoldersList); + folders.addAll(thirdLevelFoldersList); } } } @@ -362,27 +362,6 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { 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 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { 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 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { 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); - } - }; } -- GitLab