All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jidesoft.plaf.basic.BasicFolderChooserUI Maven / Gradle / Ivy

/*
 * @(#)BasicFolderChooserUI.java 4/12/2006
 *
 * Copyright 2002 - 2006 JIDE Software Inc. All rights reserved.
 */
package com.jidesoft.plaf.basic;

import com.jidesoft.dialog.ButtonPanel;
import com.jidesoft.plaf.FolderChooserUI;
import com.jidesoft.swing.FolderChooser;
import com.jidesoft.utils.SystemInfo;
import sun.awt.shell.ShellFolder;

import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.filechooser.FileSystemView;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicFileChooserUI;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.text.MessageFormat;
import java.util.*;
import java.util.List;

public class BasicFolderChooserUI extends BasicFileChooserUI implements FolderChooserUI {
    private FolderChooser _folderChooser;

    private FolderToolBar _toolbar;
    private JTree _fileSystemTree;
    private JScrollPane _treeScrollPane;

    private JButton _approveButton;
    private JButton _cancelButton;
    private JPanel _buttonPanel;

    private Action _approveSelectionAction = new ApproveSelectionAction();
    public BasicFolderChooserUI.FolderChooserSelectionListener _selectionListener;

    public BasicFolderChooserUI(FolderChooser chooser) {
        super(chooser);
        BasicFileSystemTreeNode.clearCache();
    }

    public static ComponentUI createUI(JComponent c) {
        return new BasicFolderChooserUI((FolderChooser) c);
    }

    @Override
    public void installComponents(JFileChooser chooser) {
        _folderChooser = (FolderChooser) chooser;

        JPanel panel = new JPanel(new BorderLayout(6, 6));
        panel.add(createFileSystemTreePanel(), BorderLayout.CENTER);
        panel.add(createToolbar(), BorderLayout.BEFORE_FIRST_LINE);
        panel.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));
        chooser.add(panel);

        chooser.setLayout(new BorderLayout());

        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

        Component accessory = chooser.getAccessory();
        if (accessory != null) {
            chooser.add(chooser.getAccessory(), BorderLayout.BEFORE_FIRST_LINE);
        }

        chooser.add(panel, BorderLayout.CENTER);
        chooser.add(_buttonPanel = createButtonPanel(), BorderLayout.AFTER_LAST_LINE);

        updateView(chooser);

        Runnable runnable = new Runnable() {
            public void run() {
                _fileSystemTree.requestFocusInWindow();
            }
        };
        SwingUtilities.invokeLater(runnable);
    }

    protected JPanel createButtonPanel() {
        _approveButton = new JButton();
        _approveButton.setAction(getApproveSelectionAction());

        _cancelButton = new JButton();
        _cancelButton.addActionListener(getCancelSelectionAction());

        ButtonPanel buttonPanel = new ButtonPanel();
        buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 6, 6, 6));
        buttonPanel.addButton(_approveButton, ButtonPanel.AFFIRMATIVE_BUTTON);
        buttonPanel.addButton(_cancelButton, ButtonPanel.CANCEL_BUTTON);
        return buttonPanel;
    }

    @Override
    public void rescanCurrentDirectory(JFileChooser fc) {
        super.rescanCurrentDirectory(fc);
    }

    @Override
    public void ensureFileIsVisible(JFileChooser fc, File f) {
        super.ensureFileIsVisible(fc, f);
        ensureFileIsVisible(f, true);
    }

    protected JComponent createToolbar() {
        _toolbar = new FolderToolBar(true, _folderChooser.getRecentList());
        _toolbar.addListener(new FolderToolBarListener() {
            // ------------------------------------------------------------------------------
            // Implementation of FolderToolBarListener
            // ------------------------------------------------------------------------------

            public void deleteFolderButtonClicked() {
                // make sure user really wants to do this
                String text, header;
                TreePath path = _fileSystemTree.getSelectionPaths()[0];
                java.util.List selection = getSelectedFolders(new TreePath[]{path});

                final ResourceBundle resourceBundle = FolderChooserResource.getResourceBundle(Locale.getDefault());
                if (selection.size() > 1) {
                    text = MessageFormat.format(
                            resourceBundle.getString("FolderChooser.delete.message2"), selection.size());
                }
                else {
                    text = resourceBundle.getString("FolderChooser.delete.message1");
                }
                final String title = resourceBundle.getString("FolderChooser.delete.title");

                int result = JOptionPane.showConfirmDialog(_folderChooser, text, title, JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
                if (result == JOptionPane.OK_OPTION) {
                    TreePath parentPath = path.getParentPath();
                    Object parentObject = parentPath.getLastPathComponent();
                    Object deletedObject = path.getLastPathComponent();
                    int index = _fileSystemTree.getModel().getIndexOfChild(parentObject, deletedObject);
                    for (int i = 0; i < selection.size(); i++) {
                        File f = (File) selection.get(i);
                        recursiveDelete(f);
                    }
                    ((BasicFileSystemTreeModel) _fileSystemTree.getModel()).removePath(path, index, deletedObject);
                    TreePath pathToSelect = parentPath;
                    if (index >= ((MutableTreeNode) parentObject).getChildCount()) {
                        index = ((MutableTreeNode) parentObject).getChildCount() - 1;
                    }
                    if (index > 0) {
                        pathToSelect = parentPath.pathByAddingChild(((MutableTreeNode) parentObject).getChildAt(index));
                    }
                    _fileSystemTree.setSelectionPath(pathToSelect);
                    _fileSystemTree.scrollPathToVisible(pathToSelect);
                }

            }

            /**
             * Recursively deletes a file/directory.
             *
             * @param file The file/folder to delete
             * @return true only if the file and all children were successfully deleted.
             */
            public final boolean recursiveDelete(File file) {
                if (isFileSystem(file) && file.isDirectory()) {
                    // delete all children first
                    File[] children = FileSystemView.getFileSystemView().getFiles(file, false);
                    for (int i = 0; i < children.length; i++) {
                        File f = children[i];
                        if (!recursiveDelete(f)) {
                            return false;
                        }
                    }
                    // delete this file.
                    return file.delete();
                }
                else {
                    return false;
                }
            }

            public void newFolderButtonClicked() {
                // get the selected folder
                TreePath[] paths = _fileSystemTree.getSelectionPaths();
                java.util.List selection = getSelectedFolders(paths);
                if (selection.size() > 1 || selection.size() == 0)
                    return; // should never happen

                File parent = (File) selection.get(0);

                final ResourceBundle resourceBundle = FolderChooserResource.getResourceBundle(Locale.getDefault());
                String folderName = JOptionPane.showInputDialog(_folderChooser, resourceBundle.getString("FolderChooser.new.folderName"),
                        resourceBundle.getString("FolderChooser.new.title"), JOptionPane.OK_CANCEL_OPTION | JOptionPane.QUESTION_MESSAGE);

                if (folderName != null) {
                    File newFolder = new File(parent, folderName);
                    boolean success = newFolder.mkdir();

                    TreePath parentPath = paths[0];
                    boolean isExpanded = _fileSystemTree.isExpanded(parentPath);
                    if (!isExpanded) { // expand it first
                        _fileSystemTree.expandPath(parentPath);
                    }

                    LazyMutableTreeNode parentTreeNode = (LazyMutableTreeNode) parentPath.getLastPathComponent();
                    BasicFileSystemTreeNode child = BasicFileSystemTreeNode.createFileSystemTreeNode(newFolder, _folderChooser);
//                    child.setParent(parentTreeNode);
                    if (success) {
                        parentTreeNode.clear();
                        int insertIndex = _fileSystemTree.getModel().getIndexOfChild(parentTreeNode, child);
                        if (insertIndex != -1) {
//                            ((BasicFileSystemTreeModel) _fileSystemTree.getModel()).insertNodeInto(child, parentTreeNode, insertIndex);
                            ((BasicFileSystemTreeModel) _fileSystemTree.getModel()).nodeStructureChanged(parentTreeNode);
//                            ((BasicFileSystemTreeModel) _fileSystemTree.getModel()).addPath(parentPath, insertIndex, child);
                        }
                    }
                    TreePath newPath = parentPath.pathByAddingChild(child);
                    _fileSystemTree.setSelectionPath(newPath);
                    _fileSystemTree.scrollPathToVisible(newPath);
                }
            }

            public void myDocumentsButtonClicked() {
                File myDocuments = FileSystemView.getFileSystemView().getDefaultDirectory();
                ensureFileIsVisible(myDocuments, true);
            }

            public void desktopButtonClicked() {
                File desktop = FileSystemView.getFileSystemView().getHomeDirectory();
                ensureFileIsVisible(desktop, true);
            }

            public void recentFolderSelected(final File file) {
                new Thread(new Runnable() {
                    public void run() {
                        setWaitCursor(true);
                        try {
                            ensureFileIsVisible(file, true);
                        }
                        finally {
                            setWaitCursor(false);
                        }
                    }
                }).start();
            }

            private Cursor m_oldCursor;

            private void setWaitCursor(boolean isWait) {
                Window parentWindow = SwingUtilities.getWindowAncestor(_folderChooser);
                if (isWait) {
                    Cursor hourglassCursor = new Cursor(Cursor.WAIT_CURSOR);
                    m_oldCursor = parentWindow.getCursor();
                    parentWindow.setCursor(hourglassCursor);
                }
                else {
                    if (m_oldCursor != null) {
                        parentWindow.setCursor(m_oldCursor);
                        m_oldCursor = null;
                    }
                }
            }


            public java.util.List getSelectedFolders() {
                TreePath[] paths = _fileSystemTree.getSelectionPaths();
                return getSelectedFolders(paths);
            }

            public java.util.List getSelectedFolders(TreePath[] paths) {
                if (paths == null || paths.length == 0)
                    return new ArrayList();

                List folders = new ArrayList(paths.length);
                for (int i = 0; i < paths.length; i++) {
                    TreePath path = paths[i];
                    BasicFileSystemTreeNode f = (BasicFileSystemTreeNode) path.getLastPathComponent();
                    folders.add(f.getFile());
                }
                return folders;
            }

        });
        updateToolbarButtons();
        return _toolbar;
    }

    /**
     * Updates toolbar button status depending on current selection status
     */
    protected void updateToolbarButtons() {
        // delete folder button
        TreePath[] selectedFiles = _fileSystemTree == null ? new TreePath[0] : _fileSystemTree.getSelectionPaths();
//        System.out.println("selectedFiles.length = " + selectedFiles == null ? 0 : selectedFiles.length);
        if (selectedFiles != null && selectedFiles.length > 0) {
            _toolbar.enableDelete();
        }
        else {
            _toolbar.disableDelete();
        }

        // new folder button (only enable if exactly one folder selected
        if (selectedFiles != null && selectedFiles.length == 1) {
            _toolbar.enableNewFolder();
        }
        else {
            _toolbar.disableNewFolder();
        }
    }

    private JComponent createFileSystemTreePanel() {
        JPanel panel = new JPanel(new BorderLayout());
        _fileSystemTree = new BasicFileSystemTree(_folderChooser);
        updateMultiSelectionEnabled();
        _treeScrollPane = new JScrollPane(_fileSystemTree);
        panel.add(_treeScrollPane);
        return panel;
    }

    private void updateMultiSelectionEnabled() {
        if (_folderChooser.isMultiSelectionEnabled()) {
            _fileSystemTree.getSelectionModel().setSelectionMode(
                    TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
        }
        else {
            _fileSystemTree.getSelectionModel().setSelectionMode(
                    TreeSelectionModel.SINGLE_TREE_SELECTION);
        }
    }

    @Override
    public void uninstallComponents(JFileChooser chooser) {
        chooser.remove(_treeScrollPane);
        chooser.remove(_buttonPanel);
    }

    @Override
    protected void installListeners(JFileChooser fc) {
        super.installListeners(fc);
        _selectionListener = new FolderChooserSelectionListener();
        _fileSystemTree.addTreeSelectionListener(_selectionListener);
    }

    @Override
    protected void uninstallListeners(JFileChooser fc) {
        super.uninstallListeners(fc);
        _fileSystemTree.removeTreeSelectionListener(_selectionListener);
    }

    @Override
    public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) {
        return new FolderChooserPropertyChangeListener();
    }

    private void updateView(JFileChooser chooser) {
        if (chooser.getApproveButtonText() != null) {
            _approveButton.setText(chooser.getApproveButtonText());
            _approveButton.setMnemonic(chooser.getApproveButtonMnemonic());
        }
        else {
            if (JFileChooser.OPEN_DIALOG == chooser.getDialogType()) {
                _approveButton.setText(openButtonText);
                _approveButton.setToolTipText(openButtonToolTipText);
                _approveButton.setMnemonic(openButtonMnemonic);
            }
            else {
                _approveButton.setText(saveButtonText);
                _approveButton.setToolTipText(saveButtonToolTipText);
                _approveButton.setMnemonic(saveButtonMnemonic);
            }
        }

        _cancelButton.setText(cancelButtonText);
        _cancelButton.setMnemonic(cancelButtonMnemonic);

        _buttonPanel.setVisible(chooser.getControlButtonsAreShown());
    }

    /**
     * Checks if f represents a real directory or file as opposed to a
     * special folder such as "Desktop". Used by UI classes to decide if
     * a folder is selectable when doing directory choosing.
     *
     * @param f a File object
     * @return true if f is a real file or directory.
     */
    public static boolean isFileSystem(File f) {
        if (f instanceof ShellFolder) {
            ShellFolder sf = (ShellFolder) f;
            // Shortcuts to directories are treated as not being file system objects,
            // so that they are never returned by JFileChooser.
            return sf.isFileSystem() && !(sf.isLink() && sf.isDirectory());
        }
        else {
            return true;
        }
    }

    private TreePath getTreePathForFile(File file) {
        if (!file.isDirectory()) {
            return null;
        }
        Stack stack = new Stack();
        List list = new ArrayList();
        list.add(_fileSystemTree.getModel().getRoot());
        FileSystemView fsv = _folderChooser.getFileSystemView();
        File[] alternativeRoots = null;
        File root = null;
        if (SystemInfo.isWindows()) {
            File[] roots = fsv.getRoots();
            root = roots[0];
            if (isFileSystem(root) && root.isDirectory()) {
                alternativeRoots = root.listFiles();
            }
        }
        File parent = file;
        outloop:
        do {
            stack.push(parent);
            if (alternativeRoots != null) {
                for (int i = 0; i < alternativeRoots.length; i++) {
                    File r = alternativeRoots[i];
                    if (r.equals(parent)) {
                        stack.push(root);
                        break outloop;
                    }
                }
            }
            parent = _folderChooser.getFileSystemView().getParentDirectory(parent);
        }
        while (parent != null);

        while (!stack.empty()) {
            list.add(BasicFileSystemTreeNode.createFileSystemTreeNode((File) stack.pop(), _folderChooser));
        }
        return new TreePath(list.toArray());
    }

    private void ensureFileIsVisible(File file, boolean scroll) {
        final TreePath path = file == null ? new TreePath(_fileSystemTree.getModel().getRoot()) : getTreePathForFile(file);
        if (path != null) {
            _fileSystemTree.setSelectionPath(path);
            _fileSystemTree.expandPath(path);
            if (scroll) {
                Runnable runnable = new Runnable() {
                    public void run() {
                        _fileSystemTree.scrollPathToVisible(path);
                    }
                };
                SwingUtilities.invokeLater(runnable);
            }
        }
//        getApproveSelectionAction().setEnabled(_fileSystemTree.getSelectionCount() > 0);
    }

    private class FolderChooserPropertyChangeListener implements PropertyChangeListener {
        public void propertyChange(PropertyChangeEvent evt) {
            if (FolderChooser.PROPERTY_RECENTLIST.equals(evt.getPropertyName())) {
                _toolbar.setRecentList((List) evt.getNewValue());
            }
            else if (JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY.equals(evt.getPropertyName())) {
                updateView(_folderChooser);
            }
            else if (JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY.equals(evt.getPropertyName())) {
                updateView(_folderChooser);
            }
            else if (JFileChooser.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY.equals(evt.getPropertyName())) {
                updateMultiSelectionEnabled();
            }
            else if (JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals(evt.getPropertyName())) {
                ensureFileIsVisible(_folderChooser.getCurrentDirectory(), true);
            }
            else if (JFileChooser.ACCESSORY_CHANGED_PROPERTY.equals(evt.getPropertyName())) {
                Component oldValue = (Component) evt.getOldValue();
                Component newValue = (Component) evt.getNewValue();
                if (oldValue != null) {
                    _folderChooser.remove(oldValue);
                }
                if (newValue != null) {
                    _folderChooser.add(newValue, BorderLayout.BEFORE_FIRST_LINE);
                }
                _folderChooser.revalidate();
                _folderChooser.repaint();
            }
            else if (JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY.equals(evt.getPropertyName())) {
                updateView(_folderChooser);
            }
        }
    }

    private class FolderChooserSelectionListener implements TreeSelectionListener {
        public void valueChanged(TreeSelectionEvent e) {
            getApproveSelectionAction().setEnabled(_fileSystemTree.getSelectionCount() > 0);
            if (_toolbar != null) {
                updateToolbarButtons();
            }
        }
    }

    private void setSelectedFiles() {
        TreePath[] selectedPaths = _fileSystemTree.getSelectionPaths();
        if (selectedPaths == null || selectedPaths.length == 0) {
            _folderChooser.setSelectedFile(null);
            return;
        }

        java.util.List files = new ArrayList();
        for (int i = 0, c = selectedPaths.length; i < c; i++) {
            File f = ((BasicFileSystemTreeNode) selectedPaths[i].getLastPathComponent()).getFile();
            files.add(f);
        }

        _folderChooser.setSelectedFiles((File[]) files.toArray(new File[files.size()]));
    }

    @Override
    public Action getApproveSelectionAction() {
        return _approveSelectionAction;
    }

    private class ApproveSelectionAction extends AbstractAction {
        public ApproveSelectionAction() {
            setEnabled(false);
        }

        public void actionPerformed(ActionEvent e) {
            setSelectedFiles();
            _folderChooser.approveSelection();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy