8182043: Access to Windows Large Icons

Reviewed-by: aivanov, azvegint, prr
This commit is contained in:
Alexander Zuev 2021-05-27 21:49:20 +00:00
parent 8a31c07598
commit 7f52c50ba3
6 changed files with 370 additions and 81 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,6 +26,7 @@
package javax.swing.filechooser;
import java.awt.Image;
import java.awt.image.AbstractMultiResolutionImage;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileNotFoundException;
@ -225,7 +226,7 @@ public abstract class FileSystemView {
* Icon for a file, directory, or folder as it would be displayed in
* a system file browser. Example from Windows: the "M:\" directory
* displays a CD-ROM icon.
*
* <p>
* The default implementation gets information from the ShellFolder class.
*
* @param f a <code>File</code> object
@ -255,6 +256,67 @@ public abstract class FileSystemView {
}
}
/**
* Returns an icon for a file, directory, or folder as it would be displayed
* in a system file browser for the requested size.
* <p>
* Example: <pre>
* FileSystemView fsv = FileSystemView.getFileSystemView();
* Icon icon = fsv.getSystemIcon(new File("application.exe"), 64, 64);
* JLabel label = new JLabel(icon);
* </pre>
*
* @implSpec The available icons may be platform specific and so the
* available sizes determined by the platform. Therefore an exact match
* for the requested size may not be possible.
*
* The icon returned may be a multi-resolution icon image,
* which allows better support for High DPI environments
* with different scaling factors.
*
* @param f a {@code File} object for which the icon will be retrieved
* @param width width of the icon in user coordinate system.
* @param height height of the icon in user coordinate system.
* @return an icon as it would be displayed by a native file chooser
* or null for a non-existent or inaccessible file.
* @throws IllegalArgumentException if an invalid parameter such
* as a negative size or a null file reference is passed.
* @see JFileChooser#getIcon
* @see AbstractMultiResolutionImage
* @see FileSystemView#getSystemIcon(File)
* @since 17
*/
public Icon getSystemIcon(File f, int width, int height) {
if (height < 1 || width < 1) {
throw new IllegalArgumentException("Icon size can not be below 1");
}
if (f == null) {
throw new IllegalArgumentException("The file reference should not be null");
}
if(!f.exists()) {
return null;
}
ShellFolder sf;
try {
sf = ShellFolder.getShellFolder(f);
} catch (FileNotFoundException e) {
return null;
}
Image img = sf.getIcon(width, height);
if (img != null) {
return new ImageIcon(img, sf.getFolderType());
} else {
return UIManager.getIcon(f.isDirectory() ? "FileView.directoryIcon"
: "FileView.fileIcon");
}
}
/**
* On Windows, a file can appear in multiple folders, other than its
* parent directory in the filesystem. Folder could for example be the

View File

@ -207,6 +207,16 @@ public abstract class ShellFolder extends File {
return null;
}
/**
* Returns the icon of the specified size used to display this shell folder.
*
* @param width width of the icon > 0
* @param height height of the icon > 0
* @return The icon of the specified size used to display this shell folder
*/
public Image getIcon(int width, int height) {
return null;
}
// Static

View File

@ -82,6 +82,16 @@ import javax.swing.SwingConstants;
@SuppressWarnings("serial") // JDK-implementation class
final class Win32ShellFolder2 extends ShellFolder {
static final int SMALL_ICON_SIZE = 16;
static final int LARGE_ICON_SIZE = 32;
static final int MIN_QUALITY_ICON = 16;
static final int MAX_QUALITY_ICON = 256;
private final static int[] ICON_RESOLUTIONS
= {16, 24, 32, 48, 64, 72, 96, 128, 256};
static final int FILE_ICON_ID = 1;
static final int FOLDER_ICON_ID = 4;
private static native void initIDs();
static {
@ -991,14 +1001,15 @@ final class Win32ShellFolder2 extends ShellFolder {
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
private static native long extractIcon(long parentIShellFolder, long relativePIDL,
boolean getLargeIcon, boolean getDefaultIcon);
int size, boolean getDefaultIcon);
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
private static native boolean hiResIconAvailable(long parentIShellFolder, long relativePIDL);
// Returns an icon from the Windows system icon list in the form of an HICON
private static native long getSystemIcon(int iconID);
private static native long getIconResource(String libName, int iconID,
int cxDesired, int cyDesired,
boolean useVGAColors);
// Note: useVGAColors is ignored on XP and later
int cxDesired, int cyDesired);
// Return the bits from an HICON. This has a side effect of setting
// the imageHash variable for efficient caching / comparing.
@ -1018,20 +1029,17 @@ final class Win32ShellFolder2 extends ShellFolder {
return pIShellIcon;
}
private static Image makeIcon(long hIcon, boolean getLargeIcon) {
private static Image makeIcon(long hIcon) {
if (hIcon != 0L && hIcon != -1L) {
// Get the bits. This has the side effect of setting the imageHash value for this object.
final int[] iconBits = getIconBits(hIcon);
if (iconBits != null) {
// icons are always square
final int size = (int) Math.sqrt(iconBits.length);
final int baseSize = getLargeIcon ? 32 : 16;
final int iconSize = (int) Math.sqrt(iconBits.length);
final BufferedImage img =
new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
img.setRGB(0, 0, size, size, iconBits, 0, size);
return size == baseSize
? img
: new MultiResolutionIconImage(baseSize, img);
new BufferedImage(iconSize, iconSize, BufferedImage.TYPE_INT_ARGB);
img.setRGB(0, 0, iconSize, iconSize, iconBits, 0, iconSize);
return img;
}
}
return null;
@ -1043,11 +1051,13 @@ final class Win32ShellFolder2 extends ShellFolder {
*/
public Image getIcon(final boolean getLargeIcon) {
Image icon = getLargeIcon ? largeIcon : smallIcon;
int size = getLargeIcon ? LARGE_ICON_SIZE : SMALL_ICON_SIZE;
if (icon == null) {
icon =
invoke(new Callable<Image>() {
public Image call() {
Image newIcon = null;
Image newIcon2 = null;
if (isLink()) {
Win32ShellFolder2 folder = getLinkLocation(false);
if (folder != null && folder.isLibrary()) {
@ -1072,33 +1082,40 @@ final class Win32ShellFolder2 extends ShellFolder {
newIcon = imageCache.get(Integer.valueOf(index));
if (newIcon == null) {
long hIcon = getIcon(getAbsolutePath(), getLargeIcon);
newIcon = makeIcon(hIcon, getLargeIcon);
newIcon = makeIcon(hIcon);
disposeIcon(hIcon);
if (newIcon != null) {
imageCache.put(Integer.valueOf(index), newIcon);
}
}
if (newIcon != null) {
if (isLink()) {
imageCache = getLargeIcon ? smallLinkedSystemImages
: largeLinkedSystemImages;
} else {
imageCache = getLargeIcon ? smallSystemImages : largeSystemImages;
}
newIcon2 = imageCache.get(index);
if (newIcon2 == null) {
long hIcon = getIcon(getAbsolutePath(), !getLargeIcon);
newIcon2 = makeIcon(hIcon);
disposeIcon(hIcon);
}
}
if (newIcon2 != null) {
Map<Integer, Image> bothIcons = new HashMap<>(2);
bothIcons.put(getLargeIcon ? LARGE_ICON_SIZE : SMALL_ICON_SIZE, newIcon);
bothIcons.put(getLargeIcon ? SMALL_ICON_SIZE : LARGE_ICON_SIZE, newIcon2);
newIcon = new MultiResolutionIconImage(getLargeIcon ? LARGE_ICON_SIZE
: SMALL_ICON_SIZE, bothIcons);
}
}
}
if (newIcon == null) {
// These are only cached per object
long hIcon = extractIcon(getParentIShellFolder(),
getRelativePIDL(), getLargeIcon, false);
// E_PENDING: loading can take time so get the default
if(hIcon <= 0) {
hIcon = extractIcon(getParentIShellFolder(),
getRelativePIDL(), getLargeIcon, true);
if(hIcon <= 0) {
if (isDirectory()) {
return getShell32Icon(4, getLargeIcon);
} else {
return getShell32Icon(1, getLargeIcon);
}
}
}
newIcon = makeIcon(hIcon, getLargeIcon);
disposeIcon(hIcon);
if (hiResIconAvailable(getParentIShellFolder(), getRelativePIDL()) || newIcon == null) {
int size = getLargeIcon ? LARGE_ICON_SIZE : SMALL_ICON_SIZE;
newIcon = getIcon(size, size);
}
if (newIcon == null) {
@ -1107,21 +1124,68 @@ final class Win32ShellFolder2 extends ShellFolder {
return newIcon;
}
});
if (getLargeIcon) {
largeIcon = icon;
} else {
smallIcon = icon;
}
}
return icon;
}
/**
* @return The icon image of specified size used to display this shell folder
*/
public Image getIcon(int width, int height) {
int size = Math.max(width, height);
return invoke(() -> {
Image newIcon = null;
if (isLink()) {
Win32ShellFolder2 folder = getLinkLocation(false);
if (folder != null && folder.isLibrary()) {
return folder.getIcon(size, size);
}
}
Map<Integer, Image> multiResolutionIcon = new HashMap<>();
int start = size > MAX_QUALITY_ICON ? ICON_RESOLUTIONS.length - 1 : 0;
int increment = size > MAX_QUALITY_ICON ? -1 : 1;
int end = size > MAX_QUALITY_ICON ? -1 : ICON_RESOLUTIONS.length;
for (int i = start; i != end; i += increment) {
int s = ICON_RESOLUTIONS[i];
if (size < MIN_QUALITY_ICON || size > MAX_QUALITY_ICON
|| (s >= size && s <= size*2)) {
long hIcon = extractIcon(getParentIShellFolder(),
getRelativePIDL(), s, false);
// E_PENDING: loading can take time so get the default
if (hIcon <= 0) {
hIcon = extractIcon(getParentIShellFolder(),
getRelativePIDL(), s, true);
if (hIcon <= 0) {
if (isDirectory()) {
return getShell32Icon(FOLDER_ICON_ID, size);
} else {
return getShell32Icon(FILE_ICON_ID, size);
}
}
}
newIcon = makeIcon(hIcon);
disposeIcon(hIcon);
multiResolutionIcon.put(s, newIcon);
if (size < MIN_QUALITY_ICON || size > MAX_QUALITY_ICON) {
break;
}
}
}
return new MultiResolutionIconImage(size, multiResolutionIcon);
});
}
/**
* Gets an icon from the Windows system icon list as an {@code Image}
*/
static Image getSystemIcon(SystemIcon iconType) {
long hIcon = getSystemIcon(iconType.getIconID());
Image icon = makeIcon(hIcon, true);
Image icon = makeIcon(hIcon);
if (LARGE_ICON_SIZE != icon.getWidth(null)) {
icon = new MultiResolutionIconImage(LARGE_ICON_SIZE, icon);
}
disposeIcon(hIcon);
return icon;
}
@ -1129,20 +1193,13 @@ final class Win32ShellFolder2 extends ShellFolder {
/**
* Gets an icon from the Windows system icon list as an {@code Image}
*/
static Image getShell32Icon(int iconID, boolean getLargeIcon) {
boolean useVGAColors = true; // Will be ignored on XP and later
int size = getLargeIcon ? 32 : 16;
Toolkit toolkit = Toolkit.getDefaultToolkit();
String shellIconBPP = (String)toolkit.getDesktopProperty("win.icon.shellIconBPP");
if (shellIconBPP != null) {
useVGAColors = shellIconBPP.equals("4");
}
long hIcon = getIconResource("shell32.dll", iconID, size, size, useVGAColors);
static Image getShell32Icon(int iconID, int size) {
long hIcon = getIconResource("shell32.dll", iconID, size, size);
if (hIcon != 0) {
Image icon = makeIcon(hIcon, getLargeIcon);
Image icon = makeIcon(hIcon);
if (size != icon.getWidth(null)) {
icon = new MultiResolutionIconImage(size, icon);
}
disposeIcon(hIcon);
return icon;
}
@ -1325,13 +1382,17 @@ final class Win32ShellFolder2 extends ShellFolder {
}
static class MultiResolutionIconImage extends AbstractMultiResolutionImage {
final int baseSize;
final Image resolutionVariant;
final Map<Integer, Image> resolutionVariants = new HashMap<>();
public MultiResolutionIconImage(int baseSize, Image resolutionVariant) {
public MultiResolutionIconImage(int baseSize, Map<Integer, Image> resolutionVariants) {
this.baseSize = baseSize;
this.resolutionVariant = resolutionVariant;
this.resolutionVariants.putAll(resolutionVariants);
}
public MultiResolutionIconImage(int baseSize, Image image) {
this.baseSize = baseSize;
this.resolutionVariants.put(baseSize, image);
}
@Override
@ -1346,17 +1407,34 @@ final class Win32ShellFolder2 extends ShellFolder {
@Override
protected Image getBaseImage() {
return resolutionVariant;
return getResolutionVariant(baseSize, baseSize);
}
@Override
public Image getResolutionVariant(double width, double height) {
return resolutionVariant;
int dist = 0;
Image retVal = null;
// We only care about width since we don't support non-rectangular icons
int w = (int) width;
int retindex = 0;
for (Integer i : resolutionVariants.keySet()) {
if (retVal == null || dist > Math.abs(i - w)
|| (dist == Math.abs(i - w) && i > retindex)) {
retindex = i;
dist = Math.abs(i - w);
retVal = resolutionVariants.get(i);
if (i == w) {
break;
}
}
}
return retVal;
}
@Override
public List<Image> getResolutionVariants() {
return Arrays.asList(resolutionVariant);
return Collections.unmodifiableList(
new ArrayList<Image>(resolutionVariants.values()));
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -53,10 +53,12 @@ import sun.util.logging.PlatformLogger;
import static sun.awt.shell.Win32ShellFolder2.DESKTOP;
import static sun.awt.shell.Win32ShellFolder2.DRIVES;
import static sun.awt.shell.Win32ShellFolder2.Invoker;
import static sun.awt.shell.Win32ShellFolder2.LARGE_ICON_SIZE;
import static sun.awt.shell.Win32ShellFolder2.MultiResolutionIconImage;
import static sun.awt.shell.Win32ShellFolder2.NETWORK;
import static sun.awt.shell.Win32ShellFolder2.PERSONAL;
import static sun.awt.shell.Win32ShellFolder2.RECENT;
import static sun.awt.shell.Win32ShellFolder2.SMALL_ICON_SIZE;
// NOTE: This class supersedes Win32ShellFolderManager, which was removed
// from distribution after version 1.4.2.
@ -144,9 +146,9 @@ final class Win32ShellFolderManager2 extends ShellFolderManager {
new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
img.setRGB(0, 0, size, size, iconBits, 0, size);
STANDARD_VIEW_BUTTONS[iconIndex] = (size == 16)
STANDARD_VIEW_BUTTONS[iconIndex] = (size == SMALL_ICON_SIZE)
? img
: new MultiResolutionIconImage(16, img);
: new MultiResolutionIconImage(SMALL_ICON_SIZE, img);
}
return STANDARD_VIEW_BUTTONS[iconIndex];
@ -408,7 +410,8 @@ final class Win32ShellFolderManager2 extends ShellFolderManager {
try {
int i = Integer.parseInt(name);
if (i >= 0) {
return Win32ShellFolder2.getShell32Icon(i, key.startsWith("shell32LargeIcon "));
return Win32ShellFolder2.getShell32Icon(i,
key.startsWith("shell32LargeIcon ") ? LARGE_ICON_SIZE : SMALL_ICON_SIZE);
}
} catch (NumberFormatException ex) {
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -880,7 +880,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIcon
LPCTSTR pathStr = JNU_GetStringPlatformChars(env, absolutePath, NULL);
JNU_CHECK_EXCEPTION_RETURN(env, 0);
if (fn_SHGetFileInfo(pathStr, 0L, &fileInfo, sizeof(fileInfo),
SHGFI_ICON | (getLargeIcon ? 0 : SHGFI_SMALLICON)) != 0) {
SHGFI_ICON | (getLargeIcon ? SHGFI_LARGEICON : SHGFI_SMALLICON)) != 0) {
hIcon = fileInfo.hIcon;
}
JNU_ReleaseStringPlatformChars(env, absolutePath, pathStr);
@ -912,15 +912,54 @@ JNIEXPORT jint JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconIndex
return (jint)index;
}
/*
* Class: sun.awt.shell.Win32ShellFolder2
* Method: hiResIconAvailable
* Signature: (JJ)Z
*/
JNIEXPORT jboolean JNICALL Java_sun_awt_shell_Win32ShellFolder2_hiResIconAvailable
(JNIEnv* env, jclass cls, jlong pIShellFolderL, jlong relativePIDL)
{
IShellFolder* pIShellFolder = (IShellFolder*)pIShellFolderL;
LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL;
if (pIShellFolder == NULL || pidl == NULL) {
return FALSE;
}
HRESULT hres;
IExtractIconW* pIcon;
hres = pIShellFolder->GetUIObjectOf(NULL, 1, const_cast<LPCITEMIDLIST*>(&pidl),
IID_IExtractIconW, NULL, (void**)&pIcon);
if (SUCCEEDED(hres)) {
WCHAR szBuf[MAX_PATH];
INT index;
UINT flags;
UINT uFlags = GIL_FORSHELL | GIL_ASYNC;
hres = pIcon->GetIconLocation(uFlags, szBuf, MAX_PATH, &index, &flags);
if (SUCCEEDED(hres)) {
pIcon->Release();
return wcscmp(szBuf, L"*") != 0;
} else if (hres == E_PENDING) {
uFlags = GIL_DEFAULTICON;
hres = pIcon->GetIconLocation(uFlags, szBuf, MAX_PATH, &index, &flags);
if (SUCCEEDED(hres)) {
pIcon->Release();
return wcscmp(szBuf, L"*") != 0;
}
}
pIcon->Release();
}
return FALSE;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: extractIcon
* Signature: (JJZZ)J
* Signature: (JJIZ)J
*/
JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_extractIcon
(JNIEnv* env, jclass cls, jlong pIShellFolderL, jlong relativePIDL,
jboolean getLargeIcon, jboolean getDefaultIcon)
jint size, jboolean getDefaultIcon)
{
IShellFolder* pIShellFolder = (IShellFolder*)pIShellFolderL;
LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL;
@ -941,16 +980,10 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_extractIcon
UINT uFlags = getDefaultIcon ? GIL_DEFAULTICON : GIL_FORSHELL | GIL_ASYNC;
hres = pIcon->GetIconLocation(uFlags, szBuf, MAX_PATH, &index, &flags);
if (SUCCEEDED(hres)) {
HICON hIconLarge;
hres = pIcon->Extract(szBuf, index, &hIconLarge, &hIcon, (16 << 16) + 32);
if (SUCCEEDED(hres)) {
if (getLargeIcon) {
fn_DestroyIcon((HICON)hIcon);
hIcon = hIconLarge;
} else {
fn_DestroyIcon((HICON)hIconLarge);
}
if (size < 24) {
size = 16;
}
hres = pIcon->Extract(szBuf, index, &hIcon, NULL, size);
} else if (hres == E_PENDING) {
pIcon->Release();
return E_PENDING;
@ -980,7 +1013,7 @@ JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_disposeIcon
JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconBits
(JNIEnv* env, jclass cls, jlong hicon)
{
const int MAX_ICON_SIZE = 128;
const int MAX_ICON_SIZE = 256;
int iconSize = 0;
jintArray iconBits = NULL;
@ -1121,11 +1154,11 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getSystemIcon
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getIconResource
* Signature: (Ljava/lang/String;IIIZ)J
* Signature: (Ljava/lang/String;III)J
*/
JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconResource
(JNIEnv* env, jclass cls, jstring libName, jint iconID,
jint cxDesired, jint cyDesired, jboolean useVGAColors)
jint cxDesired, jint cyDesired)
{
const char *pLibName = env->GetStringUTFChars(libName, NULL);
JNU_CHECK_EXCEPTION_RETURN(env, 0);
@ -1134,10 +1167,9 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconResource
env->ReleaseStringUTFChars(libName, pLibName);
}
if (libHandle != NULL) {
UINT fuLoad = (useVGAColors && !IS_WINXP) ? LR_VGACOLOR : 0;
return ptr_to_jlong(LoadImage(libHandle, MAKEINTRESOURCE(iconID),
IMAGE_ICON, cxDesired, cyDesired,
fuLoad));
0));
}
return 0;
}

View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8182043
* @summary Access to Windows Large Icons
* @run main SystemIconTest
*/
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.filechooser.FileSystemView;
import java.awt.image.MultiResolutionImage;
import java.io.File;
public class SystemIconTest {
static final FileSystemView fsv = FileSystemView.getFileSystemView();
public static void main(String[] args) {
testSystemIcon();
negativeTests();
}
static void testSystemIcon() {
String os = System.getProperty("os.name");
if (os.startsWith("Windows")) {
String windir = System.getenv("windir");
testSystemIcon(new File(windir), true);
testSystemIcon(new File(windir + "/explorer.exe"),
true);
} else {
String homedir = System.getProperty("user.home");
testSystemIcon(new File(homedir), false);
}
}
static void negativeTests() {
Icon icon;
try {
icon = fsv.getSystemIcon(new File("."), -1, 16);
throw new RuntimeException("Negative size icon should throw invalid argument exception");
} catch (IllegalArgumentException iae) {
// Expected
}
icon = fsv.getSystemIcon(new File("thereisdefinitelynosuchfile.why"),
16, 16);
if (icon != null) {
throw new RuntimeException("Icons for files with invalid names should be null");
}
}
static void testSystemIcon(File file, boolean implComplete) {
int[] sizes = new int[] {16, 32, 48, 64, 128};
for (int size : sizes) {
ImageIcon icon = (ImageIcon) fsv.getSystemIcon(file, size, size);
//Enable below to see the icon
//JLabel label = new JLabel(icon);
//JOptionPane.showMessageDialog(null, label);
if (icon == null) {
throw new RuntimeException("icon is null!!!");
}
if (implComplete && icon.getIconWidth() != size) {
throw new RuntimeException("Wrong icon size " +
icon.getIconWidth() + " when requested " + size);
}
if (icon.getImage() instanceof MultiResolutionImage) {
MultiResolutionImage mri = (MultiResolutionImage) icon.getImage();
if (mri.getResolutionVariant(size, size) == null) {
throw new RuntimeException("There is no suitable variant for the size "
+ size + " in the multi resolution icon");
}
} else {
if (implComplete) {
throw new RuntimeException("icon is supposed to be multi-resolution but it is not");
}
}
}
}
}