8182043: Access to Windows Large Icons
Reviewed-by: aivanov, azvegint, prr
This commit is contained in:
parent
8a31c07598
commit
7f52c50ba3
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user