application embedded icons in windows

This commit is contained in:
rdavidek 2026-03-10 20:30:43 +01:00
parent 0cee7ad05e
commit 5841d45b4c
2 changed files with 92 additions and 15 deletions

View File

@ -7,10 +7,12 @@ import cz.kamma.kfmanager.service.ClipboardService;
import cz.kamma.kfmanager.service.FileOperations;
import javax.swing.*;
import javax.swing.filechooser.FileSystemView;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.datatransfer.DataFlavor;
@ -3059,8 +3061,8 @@ public class FilePanelTab extends JPanel {
fileTable.getColumnModel().getColumn(i).setCellRenderer(renderer);
}
}
private final java.util.Map<String, Icon> iconCache = new java.util.HashMap<>();
private final FileSystemView fileSystemView = FileSystemView.getFileSystemView();
private Icon getItemIcon(FileItem item) {
if (item == null) return null;
@ -3068,29 +3070,76 @@ public class FilePanelTab extends JPanel {
if (name.equals("..")) {
return new UpArrowIcon(getForeground());
}
String key;
if (item.isDirectory()) {
Color folderColor = (persistedConfig != null) ? persistedConfig.getFolderColor() : new Color(255, 203, 111);
key = "DIR_" + folderColor.getRGB();
} else {
key = "FILE_" + FileSpecificIcon.getFileType(name);
FileSpecificIcon.Type fileType = FileSpecificIcon.getFileType(name);
if (isExecutableWithEmbeddedIcon(item, fileType)) {
File file = item.getFile();
key = "FILE_EMBEDDED_" + file.getAbsolutePath() + "_" + file.lastModified();
} else {
key = "FILE_" + fileType;
}
}
Icon cached = iconCache.get(key);
if (cached != null) return cached;
Icon icon;
if (item.isDirectory()) {
Color folderColor = (persistedConfig != null) ? persistedConfig.getFolderColor() : new Color(255, 203, 111);
icon = new ColoredFolderIcon(folderColor);
} else {
icon = new FileSpecificIcon(FileSpecificIcon.getFileType(name));
icon = getExecutableEmbeddedIcon(item);
if (icon == null) {
icon = new FileSpecificIcon(FileSpecificIcon.getFileType(name));
}
}
iconCache.put(key, icon);
return icon;
}
private boolean isExecutableWithEmbeddedIcon(FileItem item, FileSpecificIcon.Type fileType) {
if (MainApp.CURRENT_OS != MainApp.OS.WINDOWS || item == null || fileType != FileSpecificIcon.Type.EXEC) {
return false;
}
File file = item.getFile();
return file != null && file.isFile() && file.exists();
}
private Icon getExecutableEmbeddedIcon(FileItem item) {
if (!isExecutableWithEmbeddedIcon(item, FileSpecificIcon.getFileType(item.getName()))) {
return null;
}
try {
Icon systemIcon = fileSystemView.getSystemIcon(item.getFile());
return normalizeIconSize(systemIcon, 16, 16);
} catch (Exception ignored) {
return null;
}
}
private Icon normalizeIconSize(Icon icon, int width, int height) {
if (icon == null) return null;
if (icon.getIconWidth() == width && icon.getIconHeight() == height) {
return icon;
}
BufferedImage image = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = image.createGraphics();
try {
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
icon.paintIcon(null, g2, 0, 0);
} finally {
g2.dispose();
}
Image scaled = image.getScaledInstance(width, height, Image.SCALE_SMOOTH);
return new ImageIcon(scaled);
}
private int calculateCurrentColumnWidth() {
if (tableModel.items == null || tableModel.items.isEmpty()) return 0;
@ -3766,3 +3815,4 @@ public class FilePanelTab extends JPanel {
}
}
}

View File

@ -8,7 +8,9 @@ import cz.kamma.kfmanager.service.FileOperations;
import cz.kamma.kfmanager.service.FileOperationQueue;
import javax.swing.*;
import javax.swing.filechooser.FileSystemView;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.datatransfer.DataFlavor;
import java.awt.event.*;
import java.io.File;
@ -575,16 +577,10 @@ public class MainWindow extends JFrame {
if (target.isDirectory()) {
customIcon = new ColoredFolderIcon(config.getFolderColor(), s.label);
} else {
customIcon = new FileSpecificIcon(FileSpecificIcon.getFileType(target.getName()));
customIcon = getToolbarShortcutIcon(target);
}
// Scale custom icon to toolbar size
java.awt.image.BufferedImage img = new java.awt.image.BufferedImage(
customIcon.getIconWidth(), customIcon.getIconHeight(), java.awt.image.BufferedImage.TYPE_INT_ARGB);
java.awt.Graphics g = img.getGraphics();
customIcon.paintIcon(null, g, 0, 0);
g.dispose();
btn.setIcon(new ImageIcon(img.getScaledInstance(iconSize, iconSize, Image.SCALE_SMOOTH)));
btn.setIcon(scaleIcon(customIcon, iconSize, iconSize));
hasIcon = true;
}
} catch (Exception ignore) {}
@ -668,6 +664,37 @@ public class MainWindow extends JFrame {
toolBar.repaint();
}
private Icon getToolbarShortcutIcon(File target) {
FileSpecificIcon.Type fileType = FileSpecificIcon.getFileType(target.getName());
if (MainApp.CURRENT_OS == MainApp.OS.WINDOWS && fileType == FileSpecificIcon.Type.EXEC && target.isFile()) {
try {
Icon systemIcon = FileSystemView.getFileSystemView().getSystemIcon(target);
if (systemIcon != null) {
return systemIcon;
}
} catch (Exception ignored) {
// Fallback to default file-type icon
}
}
return new FileSpecificIcon(fileType);
}
private Icon scaleIcon(Icon icon, int width, int height) {
if (icon == null) return null;
if (icon.getIconWidth() == width && icon.getIconHeight() == height) {
return icon;
}
BufferedImage img = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics g = img.getGraphics();
try {
icon.paintIcon(null, g, 0, 0);
} finally {
g.dispose();
}
return new ImageIcon(img.getScaledInstance(width, height, Image.SCALE_SMOOTH));
}
private void setupMainToolbarButton(JButton btn, String tooltip, Color color) {
int btnSize = config != null ? config.getToolbarButtonSize() : 35;
if (btnSize < 35) btnSize = 35;