package net.sf.nmedit.nomad.core.swing.explorer;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.io.File;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import net.sf.nmedit.nmutils.io.FileUtils;
import net.sf.nmedit.nomad.core.helpers.RuntimeMenuBuilder;
import net.sf.nmedit.nomad.core.menulayout.MenuBuilder;
import net.sf.nmedit.nomad.core.menulayout.MenuLayout;
public class FileExplorerTree extends ExplorerTree {
/**
*
*/
private static final long serialVersionUID = -1065473531878285689L;
private boolean popupVisible = false;
private boolean popupMadeInvisible = false;
private FETPopupMenuListener popupMenuListener = new FETPopupMenuListener();
public FileExplorerTree() {
super();
setEditable(true);
getModel().addTreeModelListener(new FileExplorerModelListener(this));
enableEvents(MouseEvent.MOUSE_EVENT_MASK);
}
protected DefaultTreeModel createTreeModel(RootNode root, boolean asksAllowsChildren)
{
return new FileTreeModel(root, asksAllowsChildren);
}
private class FileTreeModel extends DefaultTreeModel
{
public FileTreeModel(TreeNode root, boolean asksAllowsChildren)
{
super(root, asksAllowsChildren);
}
public void valueForPathChanged(TreePath path, Object newValue)
{
Object aNode = path.getLastPathComponent();
if (aNode instanceof FileNode)
{
String name = (String) newValue;
if (name == null || name.length() == 0)
return;
FileNode fileNode = (FileNode) aNode;
File oldFile = fileNode.getFile();
if (name.equals(oldFile.getName()))
return;
File newFile = new File(oldFile.getParent(), name);
File realNewFile;
if (oldFile.isDirectory()) {
realNewFile = newFile;
} else {
realNewFile = FileUtils.getNameWithExtension(oldFile, newFile);
}
if (realNewFile.exists()) {
startEditingAtPath(new TreePath(fileNode.getPath()));
return;
} else {
fileNode.renameTo(FileExplorerTree.this, realNewFile);
}
TreeNode parent = fileNode.getParent();
if (parent instanceof FileNode)
{
((FileNode)parent).updateChildrenNodes(true);
}
FileExplorerTree.this.fireNodeStructureChanged(fileNode.getParent());
}
else
{
super.valueForPathChanged(path, newValue);
}
}
}
public void startEditingAtPath(TreePath path) {
if (popupVisible) return; // no
if (popupMadeInvisible)
{
popupMadeInvisible = false;
return;
}
super.startEditingAtPath(path);
}
protected void processMouseEvent(MouseEvent e)
{
// update the cursor location
switch (e.getID())
{
case MouseEvent.MOUSE_PRESSED:
case MouseEvent.MOUSE_RELEASED:
case MouseEvent.MOUSE_CLICKED:
if (popupVisible)
updateSelectionAndPopupForLocation(e.getX(), e.getY());
break;
default:
break;
}
super.processMouseEvent(e);
}
private void updateSelectionAndPopupForLocation(int x, int y)
{
// select node at cursor
int row = getClosestRowForLocation(x, y);
if (!isRowSelected(row))
setSelectionRow(row);
updatePopupForSelection(row<0);
}
private void updatePopupForSelection(boolean setDisabled)
{
FileExplorerTree tree = FileExplorerTree.this;
Object last = tree.getLastSelectedPathComponent();
if (last != null && last instanceof ETreeNode && (!setDisabled))
{
ETreeNode node = (ETreeNode) last;
enableAction(node, ACTION_REFRESH);
enableAction(node, ACTION_ENTRY_REMOVE);
enableAction(node, ACTION_RENAME);
enableAction(node, ACTION_DIR_NEWDIR);
enableAction(node, ACTION_ITEM_DELETE);
enableAction(node, ACTION_ITEM_OPEN);
return;
}
else
{
disableAction(ACTION_REFRESH);
disableAction(ACTION_ENTRY_REMOVE);
disableAction(ACTION_RENAME);
disableAction(ACTION_DIR_NEWDIR);
disableAction(ACTION_ITEM_DELETE);
disableAction(ACTION_ITEM_OPEN);
}
}
private MenuLayout menuLayout;
public void createPopup(MenuBuilder menuBuilder)
{
// TODO this currently supports only a single FileExplorer
// we have to clone the layout entry point
MenuLayout l = menuBuilder.getLayout();
this.menuLayout = l;
JPopupMenu popup = menuBuilder.createPopup("nomad.fileexplorer");
createAction(l, ACTION_REFRESH);
createAction(l, ACTION_ENTRY_REMOVE);
createAction(l, ACTION_RENAME);
createAction(l, ACTION_DIR_NEWDIR);
createAction(l, ACTION_ITEM_DELETE);
createAction(l, ACTION_ITEM_OPEN);
// new location
popup.add(new JMenuItem((RuntimeMenuBuilder.getNewLocationAction(menuLayout))));
popup.addSeparator();
popup.add(createCollapseAllAction());
popup.addPopupMenuListener(popupMenuListener);
setComponentPopupMenu(popup);
}
private void createAction(MenuLayout l, String entryPoint)
{
l.getEntry(entryPoint).addActionListener(new ETActionListener(entryPoint));
}
public static final String ACTION_REFRESH =
"nomad.fileexplorer.entry.refresh";
public static final String ACTION_ENTRY_REMOVE =
"nomad.fileexplorer.entry.remove";
public static final String ACTION_RENAME =
"nomad.fileexplorer.rename";
public static final String ACTION_DIR_NEWDIR =
"nomad.fileexplorer.dir.newdir";
public static final String ACTION_ITEM_DELETE =
"nomad.fileexplorer.item.delete";
public static final String ACTION_ITEM_OPEN =
"nomad.fileexplorer.item.open";
private class FETPopupMenuListener implements PopupMenuListener
{
public void popupMenuCanceled(PopupMenuEvent e)
{
popupVisible = false;
popupMadeInvisible = true;
}
public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
{
popupVisible = false;
popupMadeInvisible = true;
}
public void popupMenuWillBecomeVisible(PopupMenuEvent e)
{
popupVisible = true;
updatePopupForSelection(false);
}
}
private void disableAction(String entryPoint)
{
menuLayout.getEntry(entryPoint).setEnabled(false);
}
private void enableAction(ETreeNode node, String entryPoint)
{
boolean enable = node.isActionCommandPossible(FileExplorerTree.this,
entryPoint);
menuLayout.getEntry(entryPoint).setEnabled(enable);
}
private class ETActionListener implements ActionListener
{
private String command;
public ETActionListener(String command)
{
this.command = command;
}
public void actionPerformed(ActionEvent e)
{
FileExplorerTree tree = FileExplorerTree.this;
for (TreePath path : tree.getSelectionPaths()) {
Object last = path.getLastPathComponent();
if (last == null) continue;
if (last instanceof ETreeNode)
{
((ETreeNode)last).actionCommandPerformed(FileExplorerTree.this,
command);
}
}
}
}
public void installUI() {
setUI(new FileExplorerTreeUI());
}
class FileExplorerModelListener implements TreeModelListener {
protected FileExplorerTree tree;
public FileExplorerModelListener(FileExplorerTree fileExplorerTree) {
this.tree = fileExplorerTree;
}
public void treeNodesChanged(TreeModelEvent e) {
Object node;
node = (e.getTreePath().getLastPathComponent());
/*
* If the event lists children, then the changed
* node is the child of the node we have already
* gotten. Otherwise, the changed node and the
* specified node are the same.
*/
try {
int index = e.getChildIndices()[0];
node = ((FileNode)node).getChildAt(index);
} catch (NullPointerException exc) {}
if (node instanceof FileNode) {
FileNode fNode = (FileNode)node;
File oldFile = fNode.getFile();
File newFile = new File(fNode.getFile().getParentFile(),
fNode.getFile().getName());
File realNewFile;
if (oldFile.isDirectory()) {
realNewFile = newFile;
} else {
realNewFile = FileUtils.getNameWithExtension(fNode.getFile(), newFile);
}
if (realNewFile.exists()) {
startEditingAtPath(new TreePath(fNode.getPath()));
return;
} else {
fNode.renameTo(tree, realNewFile);
}
TreeNode parNode = fNode.getParent();
if (parNode instanceof FileNode)
{
((FileNode)parNode).updateChildrenNodes(true);
}
tree.fireNodeStructureChanged(parNode);
}
}
public void treeNodesInserted(TreeModelEvent e) {
// TODO Auto-generated method stub
}
public void treeNodesRemoved(TreeModelEvent e) {
// TODO Auto-generated method stub
}
public void treeStructureChanged(TreeModelEvent e) {
// TODO Auto-generated method stub
}
}
}