org.domainmath.gui.FileTreePanel.java Source code

Java tutorial

Introduction

Here is the source code for org.domainmath.gui.FileTreePanel.java

Source

/*
 * Copyright (C) 2015 Vinu K.N
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

// FIX ME: same icon for same named file and folder.
package org.domainmath.gui;

import java.awt.Component;
import java.awt.Desktop;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.Icon;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.filechooser.FileSystemView;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import org.apache.commons.io.FileUtils;
import org.domainmath.gui.dialog.Delete;

/**
 * Create a File Tree Panel.
 * This File Tree Panel changes according to changing folder.
 * @author Vinu K.N
 */
public class FileTreePanel extends javax.swing.JPanel {
    private static final long serialVersionUID = -1291143920511369926L;
    private FileSystemModel fileSystemModel;
    private final MainFrame frame;
    java.util.ResourceBundle bundle = java.util.ResourceBundle
            .getBundle("org/domainmath/gui/resources/DomainMath_en");

    // popup menus.
    private JMenuItem openItem;
    private JMenuItem runScriptItem;
    private JMenuItem openOutsideItem;
    private JMenuItem renameItem;
    private JMenuItem deleteItem;
    private JMenuItem refreshItem;
    private JMenuItem newFolderItem;
    private KeyStroke keyDeleteItem;

    private DeleteAction deleteAction;
    private final KeyStroke keyOpenItem;
    private OpenAction openAction;
    private File lastSelectedFile;
    private final KeyStroke keyRenameItem;
    private final KeyStroke keyRefreshItem;
    private RefreshAction refreshAction;

    /**
     * Creates new form FileTreePanel
     * @param frame
     */

    public FileTreePanel(MainFrame frame) {
        initComponents();
        this.frame = frame;
        fileTree.setEditable(true);
        addPopupMenuToFileTree();

        ToolTipManager.sharedInstance().registerComponent(fileTree);

        // handle right click event on File Tree.
        fileTree.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                if (e.getClickCount() == 2) {
                    TreePath path = fileTree.getPathForLocation(e.getX(), e.getY());
                    Rectangle pathBounds = fileTree.getUI().getPathBounds(fileTree, path);
                    if (pathBounds != null && pathBounds.contains(e.getX(), e.getY())) {
                        File file = (File) fileTree.getLastSelectedPathComponent();
                        selectFile(file);
                    }
                }
            }
        });

        keyDeleteItem = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
        keyRenameItem = KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0);
        keyOpenItem = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
        keyRefreshItem = KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0);
    }

    /**
     * Returns selected file(last).
     * @return lastSelectedFile
     */
    public File getLastSelectedFile() {
        fileTree.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                TreePath path = fileTree.getPathForLocation(e.getX(), e.getY());
                Rectangle pathBounds = fileTree.getUI().getPathBounds(fileTree, path);
                if (pathBounds != null && pathBounds.contains(e.getX(), e.getY())) {
                    File file = (File) fileTree.getLastSelectedPathComponent();
                    lastSelectedFile = file;
                }
            }
        });
        return lastSelectedFile;
    }

    /**
     * Set selected file(last).
     * @param lastSelectedFile 
     */
    public void setLastSelectedFile(File lastSelectedFile) {
        this.lastSelectedFile = lastSelectedFile;
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        fileTree = new org.domainmath.gui.FileTree();

        jScrollPane1.setViewportView(fileTree);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE));
        layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 311, Short.MAX_VALUE));
    }// </editor-fold>                        
     // Variables declaration - do not modify                     

    private org.domainmath.gui.FileTree fileTree;
    private javax.swing.JScrollPane jScrollPane1;
    // End of variables declaration                   

    /**
     * Update File Tree according to file f.
     * @param f 
     */
    public void updateFileTree(File f) {
        this.fileTree.setModel(null);
        fileSystemModel = new FileSystemModel(f);

        this.fileTree.setModel(fileSystemModel);
        fileTree.setCellRenderer(new FileTreeCellRenderer());
        fileTree.setSelectionRow(0);
    }

    /**
     * Handle file selection.
     * @param file 
     */
    private void selectFile(File file) {
        if (!file.isDirectory()) {
            String selectedFileToOpen = file.getName();

            // user selected octave script.
            if (selectedFileToOpen.endsWith(".m")) {
                if (!MainFrame.fileNameList.contains(file.getAbsolutePath())) {
                    frame.open(file, MainFrame.FILE_TAB_INDEX);
                    frame.setCurrentDirFileTab(file.getParent());
                } else {
                    System.out.println(file.getAbsolutePath() + " already open!");
                }
            } else {
                loadFile(file);
            }
        } else {

            // change current directory.
            frame.changeDirectory(file);
            updateFileTree(file);
        }
    }

    /**
     * Importing data.
     * @param file 
     */
    private void loadFile(File file) {
        String name;
        name = file.getName();
        if (name.endsWith(".mat")) {
            MainFrame.workspace.load(file, "-mat");
        } else if (name.endsWith(".hdf5")) {
            MainFrame.workspace.load(file, "-hdf5");
        } else if (name.endsWith(".fhdf5")) {
            MainFrame.workspace.load(file, "-float-hdf5");
        } else if (name.endsWith(".txt")) {
            MainFrame.workspace.load(file, "-ascii");
        } else if (name.endsWith(".bin")) {
            MainFrame.workspace.load(file, "-binary");
        } else if (name.endsWith(".fbin")) {
            MainFrame.workspace.load(file, "-float-binary");
        } else if (name.endsWith(".zip")) {
            MainFrame.workspace.load(file, "-zip");
        } else if (name.endsWith(".fis")) {
            MainFrame.octavePanel.eval("pkg load fuzzy-logic-toolkit");
            MainFrame.octavePanel.eval("readfis('" + file.getAbsolutePath() + "');");
        } else if (name.endsWith(".csv")) {
            MainFrame.workspace.loadCSV(file);
        } else if (name.endsWith(".bmp") || name.endsWith(".gif") || name.endsWith(".jpg") || name.endsWith(".jpeg")
                || name.endsWith(".pbm") || name.endsWith(".pcx") || name.endsWith(".pgm") || name.endsWith(".png")
                || name.endsWith(".pnm") || name.endsWith(".ppm") || name.endsWith(".ras") || name.endsWith(".tif")
                || name.endsWith(".tiff") || name.endsWith(".xwd")) {
            MainFrame.workspace.loadImage(file.getAbsolutePath());

        } else if (name.endsWith(".lin")) {
            MainFrame.workspace.loadAudio1(file.getParent() + File.separator + name.substring(0, name.indexOf(".")),
                    "lin");
        } else if (name.endsWith(".raw")) {
            MainFrame.workspace.loadAudio1(file.getParent() + File.separator + name.substring(0, name.indexOf(".")),
                    "raw");
        } else if (name.endsWith(".au")) {
            MainFrame.workspace.loadAudio1(file.getParent() + File.separator + name.substring(0, name.indexOf(".")),
                    "au");
        } else if (name.endsWith(".mu")) {
            MainFrame.workspace.loadAudio1(file.getParent() + File.separator + name.substring(0, name.indexOf(".")),
                    "mu");
        } else if (name.endsWith(".snd")) {
            MainFrame.workspace.loadAudio1(file.getAbsolutePath(), "snd");
        } else if (name.endsWith(".dcm")) {
            MainFrame.workspace.loadDCM(file.getAbsolutePath());
        } else if (name.endsWith(".wav") || name.endsWith(".riff")) {
            MainFrame.workspace.loadAudio2(file.getAbsolutePath());
        }
        MainFrame.reloadWorkspace();
    }

    /**
     * Add popup menu.
     */
    private void addPopupMenuToFileTree() {
        refreshItem = new JMenuItem(bundle.getString("fileTreeRefreshItem.text"));
        fileTree.addMouseListener(new MouseAdapter() {

            @Override
            public void mousePressed(MouseEvent e) {
                addGlobalAction(e);

                if (SwingUtilities.isRightMouseButton(e)) {
                    TreePath path = fileTree.getPathForLocation(e.getX(), e.getY());
                    Rectangle pathBounds = fileTree.getUI().getPathBounds(fileTree, path);

                    if (pathBounds != null && pathBounds.contains(e.getX(), e.getY())) {
                        JPopupMenu menu = new JPopupMenu();
                        File file = (File) fileTree.getLastSelectedPathComponent();
                        openItem = new JMenuItem(bundle.getString("fileTreeOpenItem.text"));
                        runScriptItem = new JMenuItem(bundle.getString("fileTreeRunItem.text"));
                        openOutsideItem = new JMenuItem(bundle.getString("fileTreeOpenOutsideItem.text"));
                        renameItem = new JMenuItem(bundle.getString("fileTreeRenameItem.text"));
                        deleteItem = new JMenuItem(bundle.getString("fileTreeDeleteItem.text"));

                        openItem.setAccelerator(keyOpenItem);
                        renameItem.setAccelerator(keyRenameItem);
                        deleteItem.setAccelerator(keyDeleteItem);
                        refreshItem.setAccelerator(keyRefreshItem);
                        menu.add(openItem);
                        menu.add(runScriptItem);
                        menu.add(openOutsideItem);
                        menu.addSeparator();
                        menu.add(renameItem);
                        menu.add(deleteItem);
                        menu.addSeparator();
                        menu.add(refreshItem);

                        fileTreeOpenItemActionPerformed(file);
                        fileTreeRunItemActionPerformed(file);
                        fileTreeOpenOutsideItemActionPerformed(file);
                        fileTreeRenameItemActionPerformed(fileTree.getSelectionPath());
                        fileTreeDeleteItemActionPerformed(fileTree.getSelectionModel().getSelectionPaths());
                        fileTreeRefreshItemActionPerformed((File) fileTree.getModel().getRoot());

                        if (file.isDirectory()) {
                            runScriptItem.setEnabled(false);
                        } else {
                            String name = file.getName();
                            if (!name.endsWith(".m")) {
                                runScriptItem.setEnabled(false);
                            }
                        }
                        menu.show(fileTree, e.getX(), e.getY());
                    }
                    if (pathBounds == null) {
                        JPopupMenu menu = new JPopupMenu();
                        newFolderItem = new JMenuItem(bundle.getString("fileTreeNewFolderItem.text"));
                        File file = (File) fileTree.getModel().getRoot();
                        menu.add(newFolderItem);
                        menu.add(refreshItem);

                        fileTreeNewFolderItemActionPerformed(file);
                        fileTreeRefreshItemActionPerformed(file);
                        menu.show(fileTree, e.getX(), e.getY());
                    }
                }
            }
        });
    }

    /**
     * Handle key events like F5,DELETE etc.
     * @param e 
     */
    private void addGlobalAction(MouseEvent e) {
        TreePath path2 = fileTree.getPathForLocation(e.getX(), e.getY());
        Rectangle pathBounds2 = fileTree.getUI().getPathBounds(fileTree, path2);
        if (pathBounds2 != null && pathBounds2.contains(e.getX(), e.getY())) {
            TreePath[] selectionPaths = fileTree.getSelectionModel().getSelectionPaths();
            openAction = new OpenAction((File) fileTree.getLastSelectedPathComponent());
            refreshAction = new RefreshAction((File) fileTree.getLastSelectedPathComponent());
            deleteAction = new DeleteAction(selectionPaths);

            InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
            ActionMap actionMap = getRootPane().getActionMap();

            inputMap.put(keyDeleteItem, "DeleteAction");
            actionMap.put("DeleteAction", deleteAction);
            inputMap.put(keyOpenItem, "OpenAction");
            actionMap.put("OpenAction", openAction);
            inputMap.put(keyRefreshItem, "RefreshAction");
            actionMap.put("RefreshAction", refreshAction);
        }
    }

    /**
     * Action for creating a new folder.
     * @param file 
     */
    private void fileTreeNewFolderItemActionPerformed(final File file) {
        newFolderItem.addActionListener((ActionEvent e) -> {
            createUniqueFolder(file);
        });
    }

    /**
     * Create an unique folder.
     * @see fileTreeNewFolderItemActionPerformed
     * @param file 
     */
    private void createUniqueFolder(File file) {
        String name = "New Folder";
        File dir = new File(file.getAbsolutePath() + File.separator + name);
        if (!dir.exists()) {
            dir.mkdir();
            updateFileTree(file);
            int indexOfChild = fileSystemModel.getIndexOfChild(file, dir);
            fileTree.startEditingAtPath(fileTree.getPathForRow(indexOfChild + 1));
        } else {
            File unique = null;
            int n = 1;
            while (unique == null) {
                File d = new File(file.getAbsolutePath() + File.separator + name + "(" + n + ")");
                if (!d.exists()) {
                    d.mkdir();
                    updateFileTree(file);
                    int indexOfChild = fileSystemModel.getIndexOfChild(file, d);
                    fileTree.startEditingAtPath(fileTree.getPathForRow(indexOfChild + 1));
                    unique = d;
                }
                n++;
            }
        }
    }

    /**
     * Action for refreshing File Tree.
     * @param file 
     */
    private void fileTreeRefreshItemActionPerformed(final File file) {
        refreshItem.addActionListener((ActionEvent e) -> {
            updateFileTree(file);
        });
    }

    /**
     * Action for deleting selected contents from File Tree.
     * @param selectionPaths 
     */
    private void fileTreeDeleteItemActionPerformed(final TreePath[] selectionPaths) {
        deleteItem.addActionListener((ActionEvent e) -> {
            confirmDeletion(selectionPaths);
        });
    }

    /**
     * Confirm removal of contents from File Tree.
     * @param selectionPaths 
     */
    private void confirmDeletion(final TreePath[] selectionPaths) {
        final Delete confirmDialog = new Delete(frame);
        JButton yes = new JButton("Yes,Delete");
        JButton no = new JButton("No");
        confirmDialog.setSecondTitle("Are you sure to delete selected contents?");

        yes.addActionListener(new ActionListener() {
            Object[] path1;
            String s = "";

            @Override
            public void actionPerformed(ActionEvent e) {
                for (TreePath path : selectionPaths) {
                    path1 = path.getPath();
                    for (Object path11 : path1) {
                        s += path11 + File.separator;
                    }
                    delete(new File(s));
                    s = "";
                }
                confirmDialog.dispose();
            }

        });

        no.addActionListener((ActionEvent e) -> {
            confirmDialog.dispose();
        });

        confirmDialog.addButton(yes);
        confirmDialog.addButton(no);
        confirmDialog.setVisible(true);
    }

    /**
     * Delete a file or folder.
     * @param file 
     */
    private void delete(File file) {
        try {
            if (file.isDirectory()) {
                File f = file;
                FileUtils.deleteDirectory(file);
                updateFileTree(f.getParentFile());
            } else {
                File f = file;
                file.delete();
                updateFileTree(f.getParentFile());
            }
        } catch (IOException ex) {
        }
    }

    /**
     * Action for renaming selected content.
     * @param selectionPath 
     */
    private void fileTreeRenameItemActionPerformed(final TreePath selectionPath) {
        renameItem.addActionListener((ActionEvent e) -> {
            fileTree.startEditingAtPath(selectionPath);
        });
    }

    /**
     * Action for opening selected contents using external application.
     * @param file 
     */
    private void fileTreeOpenOutsideItemActionPerformed(final File file) {
        openOutsideItem.addActionListener((ActionEvent e) -> {
            openOutSide(file);
        });
    }

    /**
     * Opening selected contents using external application.
     * @param file 
     */
    private void openOutSide(File file) {
        try {
            URI uri = Paths.get(file.getAbsolutePath()).toUri();
            Desktop desktop = Desktop.getDesktop();
            desktop.browse(uri);
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(frame, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * Action for running script.
     * @param file 
     */
    private void fileTreeRunItemActionPerformed(final File file) {
        runScriptItem.addActionListener((ActionEvent e) -> {
            if (!file.isDirectory()) {
                MainFrame.octavePanel.evalWithOutput("run('" + file.getAbsolutePath() + "');");
            }
        });
    }

    /**
     * Action for opening selected file.
     * @param selectionPaths 
     */
    private void fileTreeOpenItemActionPerformed(final File selectionPaths) {
        openItem.addActionListener((ActionEvent e) -> {
            selectFile(selectionPaths);
        });
    }

    /**
     * Construct an Action for handling the key event DELETE.
     */
    class DeleteAction extends AbstractAction {
        private static final long serialVersionUID = 50659681002151117L;
        private final TreePath[] selectionPaths;

        public DeleteAction(TreePath[] selectionPaths) {
            this.selectionPaths = selectionPaths;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (fileTree.hasFocus()) {
                confirmDeletion(selectionPaths);
            } else {
                MainFrame.workspace.delete();
            }

        }
    }

    /**
     * Construct an Action for handling open.
     */
    class OpenAction extends AbstractAction {
        private static final long serialVersionUID = -1569844444197285872L;
        private final File selectionPaths;

        public OpenAction(File selectionPaths) {
            this.selectionPaths = selectionPaths;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (fileTree.hasFocus()) {
                selectFile(selectionPaths);

            } else if (MainFrame.workspace.hasTableFocus()) {
                MainFrame.reloadWorkspace();
            }

        }
    }

    /**
     * Construct an Action for handling refresh.
     */
    class RefreshAction extends AbstractAction {
        private static final long serialVersionUID = 3005626166420504982L;
        private final File selectionPaths;

        public RefreshAction(File selectionPaths) {
            this.selectionPaths = selectionPaths;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (fileTree.hasFocus()) {
                updateFileTree((File) fileTree.getModel().getRoot());

            } else if (MainFrame.workspace.hasTableFocus()) {
                MainFrame.reloadWorkspace();
            }
        }
    }

    /**
     * Construct a File system according to a file.
     */
    class FileSystemModel implements TreeModel {
        private final File root;
        private final Vector listeners = new Vector();

        /**
         * Construct a File System with rootDirectory.
         * @param rootDirectory 
         */
        public FileSystemModel(File rootDirectory) {
            root = rootDirectory;
        }

        /**
         * Returns root of the File System.
         * @return root of the File System.
         */
        @Override
        public Object getRoot() {
            return root;
        }

        /**
         * Get a child from File System.
         * @param parent
         * @param index
         * @return 
         */
        @Override
        public Object getChild(Object parent, int index) {
            File directory = (File) parent;
            String[] children = directory.list();
            return new FileSystemModel.TreeFile(directory, children[index]);
        }

        /**
         * Get total number of children of File System.
         * @param parent
         * @return 
         */
        @Override
        public int getChildCount(Object parent) {
            File file = (File) parent;
            if (file.isDirectory()) {
                String[] fileList = file.list();
                if (fileList != null) {
                    return file.list().length;
                }
            }
            return 0;
        }

        /**
         * Returns true if <code>node</code> is file.
         * @param node
         * @return 
         */
        @Override
        public boolean isLeaf(Object node) {
            File file = (File) node;
            return file.isFile();
        }

        /**
         * Get index of a child.
         * @param parent
         * @param child
         * @return 
         */
        @Override
        public int getIndexOfChild(Object parent, Object child) {
            File directory = (File) parent;
            File file = (File) child;
            String[] children = directory.list();
            for (int i = 0; i < children.length; i++) {
                if (file.getName().equals(children[i])) {
                    return i;
                }
            }
            return -1;
        }

        /**
         * Handle File System event. 
         * @param path
         * @param value 
         */
        @Override
        public void valueForPathChanged(TreePath path, Object value) {
            File oldFile = (File) path.getLastPathComponent();
            String fileParentPath = oldFile.getParent();

            String newFileName = (String) value;
            File targetFile = new File(fileParentPath, newFileName);
            oldFile.renameTo(targetFile);
            File parent = new File(fileParentPath);
            int[] changedChildrenIndices = { getIndexOfChild(parent, targetFile) };
            Object[] changedChildren = { targetFile };
            fireTreeNodesChanged(path.getParentPath(), changedChildrenIndices, changedChildren);
        }

        /**
         * Handle node change.
         * @param parentPath
         * @param indices
         * @param children 
         */
        private void fireTreeNodesChanged(TreePath parentPath, int[] indices, Object[] children) {
            TreeModelEvent event = new TreeModelEvent(this, parentPath, indices, children);
            Iterator iterator = listeners.iterator();
            TreeModelListener listener = null;
            while (iterator.hasNext()) {
                listener = (TreeModelListener) iterator.next();
                listener.treeNodesChanged(event);
            }
        }

        /**
         * Add Tree model Listener.
         * @param listener 
         */
        @Override
        public void addTreeModelListener(TreeModelListener listener) {
            listeners.add(listener);
        }

        /**
         * Remove Tree model Listener.
         * @param listener 
         */
        @Override
        public void removeTreeModelListener(TreeModelListener listener) {
            listeners.remove(listener);
        }

        class TreeFile extends File {
            private static final long serialVersionUID = 4327413058602216070L;

            public TreeFile(File parent, String child) {
                super(parent, child);
            }

            @Override
            public String toString() {
                return getName();
            }
        }
    }

    /**
     * Create Cell Render for File System.
     * It changes the UI of default File Tree.
     */
    class FileTreeCellRenderer extends DefaultTreeCellRenderer {
        private static final long serialVersionUID = -8588733460532093956L;
        private final FileSystemView fsv = FileSystemView.getFileSystemView();
        private final Map<String, Icon> iconCache = new HashMap<>();

        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
                boolean leaf, int row, boolean hasFocus) {
            File file = (File) value;

            String filename = "";
            if (file != null) {
                filename = fsv.getSystemDisplayName(file);

            } else {
                Logger.getLogger(FileTreeCellRenderer.class.getName());
            }

            // each node is a JLabel.
            JLabel result = (JLabel) super.getTreeCellRendererComponent(tree, filename, sel, expanded, leaf, row,
                    hasFocus);

            if (file != null) {
                Icon icon = this.iconCache.get(filename);
                if (icon == null) {

                    // FIX ME: same icon for same named file and folder.
                    icon = fsv.getSystemIcon(file);
                    this.iconCache.put(filename, icon);
                }
                result.setIcon(icon);
            }
            return result;
        }
    }
}