Here is the run down on my program
Lists all folders, subfolders, and files of X extension from a specified directory. You can view, edit, copy, etc the contents of the files. Each file has a .dat file associated with it that contains information such as keywords and last use date.
Right now I'm creating a filter. The way it should filter is take the inputted text and return any folders and files with the filter in its name, files which keywords contain and files which contents contain.
Easy enough, right?
My only problem is that it will do one of the following (based on location of File
)
if folder matches
-> only lists to that folder, but not contents
if file matches
-> only lists file if its in JTree root
if file matches but is in a folder which doesnt match
-> doesnt display
I apologize if that is hard to understand. Below is functional code, copied and cleaned up from my real program. Uses apache commons 2.4
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.io.File;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.border.LineBorder;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeSelectionModel;
import org.apache.commons.io.FileUtils;
public class NGui {
JFrame frame;
private JTree tree;
private JTextField jtf;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager
.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
new NGui();
}
});
}
public NGui() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.getContentPane().setLayout(null);
frame.setSize(250, 400);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(10, 50, 200, 300);
frame.getContentPane().add(scrollPane);
tree = new JTree(addNodes(new File(getWorkPath())));
tree.setRootVisible(true);
tree.setShowsRootHandles(true);
tree.setBorder(new LineBorder(new Color(0, 0, 0)));
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
scrollPane.setViewportView(tree);
tree.getSelectionModel().addTreeSelectionListener(
new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
treeValueChanged(e);
}
});
tree.setCellRenderer(new FileTreeCellRenderer());
jtf = new JTextField();
jtf.setBorder(new LineBorder(new Color(0, 0, 0)));
jtf.setBounds(10, 10, 150, 25);
Object actionKey = jtf.getInputMap(JComponent.WHEN_FOCUSED).get(
KeyStroke.getKeyStroke("ENTER"));
jtf.getActionMap().put(actionKey, new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent ae) {
try {
filterResults(ae);
} catch (Exception e) {
e.printStackTrace();
}
}
});
frame.getContentPane().add(jtf);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void treeValueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
.getLastSelectedPathComponent();
log("Selected Node: " + node);
}
private void log(Object o) {
System.out.println(o);
}
private String getWorkPath() {
return ".";
}
public void filterResults(ActionEvent ae) throws Exception {
final String str = jtf.getText();
reloadTree("."); // refreshes from any previous searches
DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel()
.getRoot();
reloadTree(root.toString(), str);
}
public DefaultMutableTreeNode addNodes(File dir, String filter)
throws Exception {
DefaultMutableTreeNode node = new DefaultMutableTreeNode(dir);
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
if (file.getPath().contains(filter)) {
log("adding: " + file.toString());
node.add(addNodes(file));
}
} else {
// apache commons 2.4
String tmpContent = FileUtils.readFileToString(file);
if (file.getPath().contains(filter)
|| tmpContent.contains(filter)) {
log("adding: " + file.toString());
node.add(new DefaultMutableTreeNode(file));
}
}
}
return node;
}
public DefaultMutableTreeNode addNodes(File dir) {
DefaultMutableTreeNode node = new DefaultMutableTreeNode(dir);
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
node.add(addNodes(file));
} else {
node.add(new DefaultMutableTreeNode(file));
}
}
return node;
}
public void reloadTree(final String path) {
DefaultMutableTreeNode dn = addNodes(new File(path));
tree.setModel(new DefaultTreeModel(dn));
}
public void reloadTree(final String path, final String filter)
throws Exception {
DefaultMutableTreeNode dn = addNodes(new File(path), filter);
tree.setModel(new DefaultTreeModel(dn));
}
public class FileTreeCellRenderer extends DefaultTreeCellRenderer {
private static final long serialVersionUID = 1L;
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean sel, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
if (value instanceof DefaultMutableTreeNode) {
value = ((DefaultMutableTreeNode) value).getUserObject();
if (value instanceof File) {
value = ((File) value).getName();
}
}
return super.getTreeCellRendererComponent(tree, value, sel,
expanded, leaf, row, hasFocus);
}
}
}
The problem lies in the filtering algorithm.
You missed out to call the filter on the subcomponents again (instead of addNodes(file) you have to call addNodes(file, filter)).
Directory nodes where only added if they match, not if subcomponents match.
A quick hack to make your code working looks like this (replace the addNodes method):
public DefaultMutableTreeNode addNodes(File dir, String filter)
throws Exception {
DefaultMutableTreeNode node = new DefaultMutableTreeNode(dir);
//true iff any subcomponent matches
boolean matchFound = false;
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
if (file.getName().contains(filter)) {
matchFound = true;
}
//always call addNodes on directories, because subcomponents may match
//null return value indicates no match (with Java 8 use Optional for this)
DefaultMutableTreeNode maybeNode = addNodes(file, filter);
if(maybeNode != null) {
matchFound = true;
node.add(maybeNode);
}
} else {
// apache commons 2.4
String tmpContent = FileUtils.readFileToString(file);
if (file.getName().contains(filter)
|| tmpContent.contains(filter)) {
matchFound = true;
log("adding file: " + file.toString());
node.add(new DefaultMutableTreeNode(file));
}
}
}
//only return node if node itself or subcomponent matches
if(matchFound || dir.getName().contains(filter)) {
return node;
}
//return null otherwise
return null;
}