From 20c6751824f426162355a772fc5d63a4068cf5f1 Mon Sep 17 00:00:00 2001 From: Stephan Janssen Date: Tue, 25 Jun 2024 15:49:38 +0200 Subject: [PATCH] Feat #115: Restored FileTypeIconUtil using Executor and runReadAction --- .../ui/component/FileEntryComponent.java | 5 +- .../ui/panel/FileSelectionPanelFactory.java | 29 +++++++- .../genie/ui/util/FileTypeIconUtil.java | 69 ++++++++++--------- 3 files changed, 65 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/devoxx/genie/ui/component/FileEntryComponent.java b/src/main/java/com/devoxx/genie/ui/component/FileEntryComponent.java index a7ccfb97..e4cff5e1 100644 --- a/src/main/java/com/devoxx/genie/ui/component/FileEntryComponent.java +++ b/src/main/java/com/devoxx/genie/ui/component/FileEntryComponent.java @@ -1,6 +1,7 @@ package com.devoxx.genie.ui.component; import com.devoxx.genie.ui.listener.FileRemoveListener; +import com.devoxx.genie.ui.util.FileTypeIconUtil; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; @@ -38,8 +39,8 @@ public FileEntryComponent(Project project, setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); - // Icon fileTypeIcon = FileTypeIconUtil.getFileTypeIcon(project, virtualFile); - JButton fileNameButton = new JButton(virtualFile.getName()); + Icon fileTypeIcon = FileTypeIconUtil.getFileTypeIcon(project, virtualFile); + JButton fileNameButton = new JButton(virtualFile.getName(), fileTypeIcon); JButton fileNameBtn = createButton(fileNameButton); fileNameBtn.addActionListener(e -> openFileWithSelectedCode(project, virtualFile)); diff --git a/src/main/java/com/devoxx/genie/ui/panel/FileSelectionPanelFactory.java b/src/main/java/com/devoxx/genie/ui/panel/FileSelectionPanelFactory.java index 9a7b9ed5..81a4150e 100644 --- a/src/main/java/com/devoxx/genie/ui/panel/FileSelectionPanelFactory.java +++ b/src/main/java/com/devoxx/genie/ui/panel/FileSelectionPanelFactory.java @@ -1,7 +1,7 @@ package com.devoxx.genie.ui.panel; import com.devoxx.genie.service.FileListManager; -import com.devoxx.genie.ui.renderer.FileListCellRenderer; +import com.devoxx.genie.ui.util.FileTypeIconUtil; import com.intellij.ide.util.gotoByName.GotoFileModel; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadAction; @@ -99,7 +99,10 @@ private static void debounceSearch(Project project, debounceTimer.get().start(); } - private static void searchFiles(Project project, String searchText, DefaultListModel listModel, JBList resultList) { + private static void searchFiles(Project project, + String searchText, + DefaultListModel listModel, + JBList resultList) { new Task.Backgroundable(project, "Searching Files", true) { private final List foundFiles = new ArrayList<>(); @@ -155,4 +158,26 @@ private static void addSelectedFile(@NotNull JBList resultList) { FileListManager.getInstance().addFile(selectedFile); } } + + private static class FileListCellRenderer extends DefaultListCellRenderer { + private final Project project; + + public FileListCellRenderer(Project project) { + this.project = project; + } + + @Override + public Component getListCellRendererComponent(JList list, + Object value, + int index, boolean isSelected, boolean cellHasFocus) { + JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + if (value instanceof VirtualFile file) { + label.setIcon(FileTypeIconUtil.getFileTypeIcon(project, file)); + label.setText(file.getName()); + } + + return label; + } + } } diff --git a/src/main/java/com/devoxx/genie/ui/util/FileTypeIconUtil.java b/src/main/java/com/devoxx/genie/ui/util/FileTypeIconUtil.java index 32682f00..1ad7525f 100644 --- a/src/main/java/com/devoxx/genie/ui/util/FileTypeIconUtil.java +++ b/src/main/java/com/devoxx/genie/ui/util/FileTypeIconUtil.java @@ -2,58 +2,59 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiJavaFile; import com.intellij.psi.PsiManager; +import com.intellij.util.concurrency.AppExecutorUtil; +import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import static com.devoxx.genie.ui.util.DevoxxGenieIcons.*; -/** - * Utility class for getting the icon for a file type - * - * @link IDEA icons - */ public class FileTypeIconUtil { private FileTypeIconUtil() { } - /** - * Returns the icon for the file type, currently only Java files are supported - * - * @param project The current project - * @param virtualFile The file - * @return The icon - */ public static Icon getFileTypeIcon(Project project, VirtualFile virtualFile) { - final Icon[] icon = new Icon[1]; - ApplicationManager.getApplication().invokeAndWait(() -> { - PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile); - if (psiFile instanceof PsiJavaFile javaFile) { - PsiClass[] psiClasses = javaFile.getClasses(); - if (psiClasses.length > 0) { - // Assuming the file contains only one top-level class - PsiClass psiClass = psiClasses[0]; - if (psiClass.isInterface()) { - icon[0] = InterfaceIcon; - } else if (psiClass.isEnum()) { - icon[0] = EnumIcon; - } else { - icon[0] = ClassIcon; - } - } - } else { - if (virtualFile.getFileType().getName().equals("UNKNOWN")) { - icon[0] = CodeSnippetIcon; + Future iconFuture = AppExecutorUtil.getAppExecutorService().submit(() -> + ApplicationManager.getApplication().runReadAction((Computable) () -> { + Icon interfaceIcon = getIcon(project, virtualFile); + if (interfaceIcon != null) return interfaceIcon; + return virtualFile.getFileType().getName().equals("UNKNOWN") ? CodeSnippetIcon : ClassIcon; + })); + + try { + return iconFuture.get(100, TimeUnit.MILLISECONDS); // Adjust timeout as needed + } catch (InterruptedException | ExecutionException | TimeoutException e) { + // Log the error if needed + return ClassIcon; // Return a default icon in case of any error + } + } + + private static @Nullable Icon getIcon(Project project, VirtualFile virtualFile) { + PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile); + if (psiFile instanceof PsiJavaFile javaFile) { + PsiClass[] psiClasses = javaFile.getClasses(); + if (psiClasses.length > 0) { + PsiClass psiClass = psiClasses[0]; + if (psiClass.isInterface()) { + return InterfaceIcon; + } else if (psiClass.isEnum()) { + return EnumIcon; } else { - icon[0] = ClassIcon; + return ClassIcon; } } - }); - return icon[0]; + } + return null; } }