package jas2.util.gui;
import javax.swing.*;
import javax.swing.filechooser.*;
import javax.swing.tree.*;
import javax.swing.plaf.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.util.Vector;
/**
* A class which allows a user to select directories or files, similar to JFileChooser,
* except that it display files as a tree, and is better suited to selecting directories
* than the current file chooser (see java bug id 4239219).
*
* TODO: Understand issue with moving mouse between double clicks
* (seems like MOUSE_PRESSED and MOUSE_RELEASED events are generated, but not MOUSE_CLICKED)
* See Bug ID 4218549
*
* @author Tony Johnson (tony_johnson@slac.stanford.edu)
*/
public class JDirectoryChooser extends JComponent
{
/**
* Create a JDirectoryChooser with the default FileSystemView
*/
public JDirectoryChooser()
{
this(FileSystemView.getFileSystemView());
}
/**
* Create a JDirectoryChooser with the default FileSystemView
* @param currentDirectory The directory to which the tree is initially set
*/
public JDirectoryChooser(File currentDirectory)
{
this();
setCurrentDirectory(currentDirectory);
}
/**
* Create a JDirectoryChooser with the default FileSystemView
* @param currentDirectory The directory to which the tree is initially set
*/
public JDirectoryChooser(String currentDirectory)
{
this();
if (currentDirectory != null) setCurrentDirectory(new File(currentDirectory));
}
/**
* Create a JDirectoryChooser
* @param currentDirectory The directory to which the tree is initially set
* @param view The FileSystemView to use
*/
public JDirectoryChooser(File currentDirectory, FileSystemView view)
{
this(view);
setCurrentDirectory(currentDirectory);
}
/**
* Create a JDirectoryChooser
* @param currentDirectory The directory to which the tree is initially set
* @param view The FileSystemView to use
*/
public JDirectoryChooser(String currentDirectory, FileSystemView view)
{
this(view);
setCurrentDirectory(new File(currentDirectory));
}
/**
* Create a JDirectoryChooser
* @param view The FileSystemView to use
*/
public JDirectoryChooser(FileSystemView view)
{
setup(view);
ButtonListener al = new ButtonListener();
tree = new JTree();
tree.setRootVisible(false);
tree.setShowsRootHandles(true);
tree.setCellRenderer(new FileRenderer());
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addTreeSelectionListener(al);
approve.addActionListener(al);
cancel.addActionListener(al);
approve.setEnabled(false);
setLayout(new BorderLayout());
add(new JScrollPane(tree));
JPanel p = new JPanel(new FlowLayout());
p.add(approve);
p.add(cancel);
add(p,BorderLayout.SOUTH);
}
public void addNotify()
{
tree.setModel(model);
makeCurrentDirectoryVisible();
super.addNotify();
}
private void makeCurrentDirectoryVisible()
{
if (currentDirectory != null)
{
File dir = currentDirectory;
FileSystemView view = foo.getFileSystemView();
Vector v = new Vector();
while (true)
{
if (dir == null) return; // Something wrong, ignore dir
v.addElement(dir);
if (view.isRoot(dir)) break;
dir = view.getParentDirectory(dir);
}
Object[] files = new File[v.size()+1];
Object node = model.getRoot();
files[0] = node;
for (int i=1; i 0);
}
}
private class FileRenderer extends DefaultTreeCellRenderer
{
public Component getTreeCellRendererComponent(JTree tree, Object node, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus)
{
Component comp = super.getTreeCellRendererComponent(tree,node,selected,expanded,leaf,row,hasFocus);
if (comp instanceof JLabel && node instanceof File)
{
JLabel label = (JLabel) comp;
File f = (File) node;
label.setText(foo.getName(f));
label.setIcon(foo.getIcon(f));
}
return comp;
}
}
private class FileTreeModel implements TreeModel
{
public Object getChild(Object node, int index)
{
return children(node)[index];
}
public int getChildCount(Object node)
{
return children(node).length;
}
public int getIndexOfChild(Object node, Object child)
{
File[] children = children(node);
for (int i=0; iaddTreeModelListener().
*
* @see #addTreeModelListener
* @param l the listener to remove
*/
public void removeTreeModelListener(TreeModelListener l)
{
listenerList.remove(TreeModelListener.class, l);
}
private File[] children(Object node)
{
for (int i=0; i=0; i-=2)
{
if (listeners[i]==TreeModelListener.class)
{
((TreeModelListener)listeners[i+1]).treeStructureChanged(e);
}
}
}
private EventListenerList listenerList = new EventListenerList();
private final int CACHE_SIZE = 10;
private File[] cachedNode = new File[CACHE_SIZE];
private File[][] cachedChildren = new File[CACHE_SIZE][];
private int nextCache = 0;
}
private static File root = new java.io.File("root");
// Test code
public static void main(String argv[])
{
final JTextField tf = new JTextField(40);
JButton b = new JButton("Show Browser")
{
public void fireActionPerformed(ActionEvent e)
{
JDirectoryChooser dlg = new JDirectoryChooser(tf.getText());
dlg.showDialog(this);
if (dlg.getSelectedFile() != null) tf.setText(dlg.getSelectedFile().toString());
}
};
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.getContentPane().add(b,BorderLayout.CENTER);
frame.getContentPane().add(tf,BorderLayout.SOUTH);
frame.pack();
frame.show();
}
}
Ads help maintain this website.