package de.uni_passau.fim.infosun.prophet.plugin.plugins.codeViewerPlugin.fileTree;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JTree;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
/**
* A <code>JTree</code> displaying the filesystem directory structure under a given <code>File</code>.
* Fires <code>FileEvent</code>s when files are double clicked.
*
* @author Georg Seibt
* @author Andreas Hasselberg
* @author Markus Koeppen
*/
public class FileTree extends JTree {
private List<FileListener> fileListeners;
private FileTreeModel model;
/**
* Constructs a new <code>FileTree</code> displaying the directory structure under <code>rootDir</code>.
*
* @param rootDir
* the root directory for the <code>FileTree</code>
*/
public FileTree(File rootDir) {
super(new FileTreeModel(rootDir != null && rootDir.exists() ? new FileTreeNode(rootDir) : null));
this.fileListeners = new ArrayList<>();
this.model = getModel();
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
TreePath selPath = getPathForLocation(e.getX(), e.getY());
if (e.getClickCount() == 2 && selPath != null) {
FileTreeNode lastPathComponent = (FileTreeNode) selPath.getLastPathComponent();
if (lastPathComponent.isFile()) {
fireFileOpenedEvent(lastPathComponent.getFile());
}
}
}
});
getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
}
/**
* Adds the given <code>FileListener</code> to this <code>FileTree</code>s listeners.
*
* @param listener
* the <code>FileListener</code> to add
*/
public void addFileListener(FileListener listener) {
fileListeners.add(listener);
}
/**
* Removes the given <code>FileListener</code> from this <code>FileTree</code>s listeners.
*
* @param listener
* the <code>FileListener</code> to remove
*/
public void removeFileListener(FileListener listener) {
fileListeners.remove(listener);
}
/**
* Fires a <code>FileEvent</code> indicating that the given <code>File</code> was opened.
*
* @param file
* the <code>File</code> that was opened
*/
private void fireFileOpenedEvent(File file) {
FileEvent event = new FileEvent(this, FileEvent.FILE_OPENED, file);
fileListeners.forEach(listener -> listener.fileEventOccurred(event));
}
/**
* Selects the tree node representing the given <code>File</code> if it is in the directory structure that is
* currently being displayed.
*
* @param file
* the file to be selected
*/
public void selectFile(File file) {
FileTreeNode[] path = model.buildPath(file);
TreePath treePath;
if (path != null) {
treePath = new TreePath(path);
setSelectionPath(treePath);
makeVisible(treePath);
}
}
/**
* Sets the <code>TreeModel</code> that will provide the data. <code>FileTree</code> only accepts non-null models
* of type <code>FileTreeModel</code>.
* <p>
* This is a bound property.
*
* @param newModel
* the <code>TreeModel</code> that is to provide the data
* @throws IllegalArgumentException
* if <code>newModel</code> is not of type <code>FileTreeModel</code>
*/
@Override
public void setModel(TreeModel newModel) {
if (newModel instanceof FileTreeModel) {
model = (FileTreeModel) newModel;
super.setModel(newModel);
} else {
throw new IllegalArgumentException("newModel must be of type " + FileTreeModel.class.getSimpleName());
}
}
@Override
public FileTreeModel getModel() {
return (FileTreeModel) super.getModel();
}
}