From ae7cf321325bc1c66dd4597032035afb10d13ec5 Mon Sep 17 00:00:00 2001 From: Radek Davidek Date: Fri, 16 Jan 2026 18:24:33 +0100 Subject: [PATCH] file icons --- .../java/com/kfmanager/ui/FilePanelTab.java | 140 +++++++++++++++++- 1 file changed, 138 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/kfmanager/ui/FilePanelTab.java b/src/main/java/com/kfmanager/ui/FilePanelTab.java index 5d432b9..14f7e05 100644 --- a/src/main/java/com/kfmanager/ui/FilePanelTab.java +++ b/src/main/java/com/kfmanager/ui/FilePanelTab.java @@ -1532,8 +1532,13 @@ public class FilePanelTab extends JPanel { Icon icon = item.getIcon(); if (item.getName().equals("..")) { icon = new UpArrowIcon(getForeground()); - } else if (item.isDirectory() && persistedConfig != null) { - icon = new ColoredFolderIcon(persistedConfig.getFolderColor()); + } else if (item.isDirectory()) { + if (persistedConfig != null) { + icon = new ColoredFolderIcon(persistedConfig.getFolderColor()); + } + } else { + // Use type-specific icon for files + icon = new FileSpecificIcon(getFileType(item.getName())); } if (viewMode == ViewMode.BRIEF) { @@ -2268,6 +2273,137 @@ public class FilePanelTab extends JPanel { } } + /** + * Custom icon for files that provides different visuals for different file types. + */ + private static class FileSpecificIcon implements Icon { + public enum Type { IMAGE, VIDEO, AUDIO, ARCHIVE, CODE, TEXT, DOC, EXEC, OTHER } + private final Type type; + private final Color color; + + public FileSpecificIcon(Type type) { + this.type = type; + switch (type) { + case IMAGE: this.color = new Color(70, 130, 180); break; // SteelBlue + case VIDEO: this.color = new Color(205, 92, 92); break; // IndianRed + case AUDIO: this.color = new Color(147, 112, 219); break; // MediumSlateBlue + case ARCHIVE: this.color = new Color(210, 180, 140); break; // Tan + case CODE: this.color = new Color(60, 179, 113); break; // MediumSeaGreen + case TEXT: this.color = Color.GRAY; break; + case DOC: this.color = new Color(70, 90, 180); break; // Darker blue + case EXEC: this.color = new Color(0, 128, 128); break; // Teal + default: this.color = Color.LIGHT_GRAY; break; + } + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + Graphics2D g2 = (Graphics2D) g.create(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + g2.setColor(color); + // Draw a basic "sheet" shape + g2.fillRect(x + 3, y + 2, 10, 13); + + // Draw a tiny folded corner + g2.setColor(color.darker()); + int[] cx = {x + 10, x + 13, x + 10}; + int[] cy = {y + 2, y + 5, y + 5}; + g2.fillPolygon(cx, cy, 3); + + // Draw a small indicator for the type + g2.setColor(Color.WHITE); + switch (type) { + case IMAGE: + g2.fillOval(x + 5, y + 6, 2, 2); // "Sun" + g2.drawRect(x + 5, y + 9, 4, 3); // Simple mountain + break; + case VIDEO: + int[] vxp = {x + 6, x + 6, x + 10}; + int[] vyp = {y + 5, y + 11, y + 8}; + g2.fillPolygon(vxp, vyp, 3); + break; + case AUDIO: + g2.fillRect(x + 6, y + 5, 3, 2); + g2.fillRect(x + 8, y + 5, 1, 6); + g2.fillOval(x + 5, y + 10, 3, 3); + break; + case ARCHIVE: + g2.drawRect(x + 5, y + 4, 6, 8); + g2.drawLine(x + 5, y + 7, x + 11, y + 7); + g2.drawLine(x + 5, y + 10, x + 11, y + 10); + break; + case CODE: + g2.drawLine(x + 5, y + 9, x + 7, y + 7); // < + g2.drawLine(x + 5, y + 9, x + 7, y + 11); + g2.drawLine(x + 9, y + 7, x + 11, y + 9); // > + g2.drawLine(x + 9, y + 11, x + 11, y + 9); + break; + case TEXT: + case DOC: + g2.drawLine(x + 5, y + 6, x + 11, y + 6); + g2.drawLine(x + 5, y + 9, x + 11, y + 9); + g2.drawLine(x + 5, y + 12, x + 8, y + 12); + break; + case EXEC: + g2.drawOval(x + 5, y + 5, 6, 6); + g2.drawLine(x + 8, y + 4, x + 8, y + 12); + g2.drawLine(x + 4, y + 8, x + 12, y + 8); + break; + default: + break; + } + + g2.dispose(); + } + + @Override + public int getIconWidth() { return 16; } + + @Override + public int getIconHeight() { return 16; } + } + + private FileSpecificIcon.Type getFileType(String fileName) { + String name = fileName.toLowerCase(); + if (name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".png") || + name.endsWith(".gif") || name.endsWith(".bmp") || name.endsWith(".svg") || + name.endsWith(".webp") || name.endsWith(".ico") || name.endsWith(".tif")) return FileSpecificIcon.Type.IMAGE; + + if (name.endsWith(".mp4") || name.endsWith(".mkv") || name.endsWith(".avi") || + name.endsWith(".mov") || name.endsWith(".wmv") || name.endsWith(".flv") || + name.endsWith(".webm") || name.endsWith(".mpg") || name.endsWith(".mpeg")) return FileSpecificIcon.Type.VIDEO; + + if (name.endsWith(".mp3") || name.endsWith(".wav") || name.endsWith(".ogg") || + name.endsWith(".flac") || name.endsWith(".m4a") || name.endsWith(".aac") || + name.endsWith(".wma")) return FileSpecificIcon.Type.AUDIO; + + if (name.endsWith(".zip") || name.endsWith(".rar") || name.endsWith(".7z") || + name.endsWith(".tar") || name.endsWith(".gz") || name.endsWith(".bz2") || + name.endsWith(".xz") || name.endsWith(".jar") || name.endsWith(".deb") || + name.endsWith(".rpm")) return FileSpecificIcon.Type.ARCHIVE; + + if (name.endsWith(".java") || name.endsWith(".c") || name.endsWith(".cpp") || + name.endsWith(".h") || name.endsWith(".py") || name.endsWith(".js") || + name.endsWith(".html") || name.endsWith(".css") || name.endsWith(".ts") || + name.endsWith(".xml") || name.endsWith(".json") || name.endsWith(".sh") || + name.endsWith(".php") || name.endsWith(".kt") || name.endsWith(".cs") || + name.endsWith(".go") || name.endsWith(".rb") || name.endsWith(".sql")) return FileSpecificIcon.Type.CODE; + + if (name.endsWith(".pdf") || name.endsWith(".doc") || name.endsWith(".docx") || + name.endsWith(".odt") || name.endsWith(".xls") || name.endsWith(".xlsx") || + name.endsWith(".ppt") || name.endsWith(".pptx") || name.endsWith(".rtf")) return FileSpecificIcon.Type.DOC; + + if (name.endsWith(".txt") || name.endsWith(".md") || name.endsWith(".log") || + name.endsWith(".conf") || name.endsWith(".ini") || name.endsWith(".csv") || + name.endsWith(".properties")) return FileSpecificIcon.Type.TEXT; + + if (name.endsWith(".exe") || name.endsWith(".bin") || name.endsWith(".com") || + name.endsWith(".bat") || name.endsWith(".msi") || name.endsWith(".appimage")) return FileSpecificIcon.Type.EXEC; + + return FileSpecificIcon.Type.OTHER; + } + private void showAssociationDialog(File file) { String name = file.getName(); String ext = "";