package org.oddjob.monitor.view;
import java.awt.BorderLayout;
import javax.swing.DropMode;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.ToolTipManager;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import org.oddjob.arooa.design.designer.ArooaTransferHandler;
import org.oddjob.arooa.design.designer.ArooaTree;
import org.oddjob.arooa.design.designer.TransferEvent;
import org.oddjob.arooa.design.designer.TransferEventListener;
import org.oddjob.arooa.design.view.TreeChangeFollower;
import org.oddjob.arooa.design.view.TreePopup;
import org.oddjob.arooa.parsing.DragPoint;
import org.oddjob.monitor.control.DetailController;
import org.oddjob.monitor.control.NodeControl;
import org.oddjob.monitor.control.PropertyPolling;
import org.oddjob.monitor.model.ConfigContextSearch;
import org.oddjob.monitor.model.DetailModel;
import org.oddjob.monitor.model.ExplorerModel;
import org.oddjob.monitor.model.JobTreeModel;
import org.oddjob.monitor.model.JobTreeNode;
/**
* The tree view.
*
* @author Rob Gordon
*/
public class ExplorerComponent extends JPanel {
private static final long serialVersionUID = 0;
private final JTree tree;
private final JScrollPane treeScroll;
private MonitorMenuBar menuBar;
private final DetailModel detailModel;
private final ExplorerModel explorerModel;
private final PropertyPolling propertyPolling;
private final JSplitPane split;
private final TreeChangeFollower treeChangeFollower;
/**
* Constructor. Create the main Explorer Component.
*
* @param explorerModel The Model for this explorer component.
* @param menuBar The Main Menu Bar.
* @param propertyPolling The property polling.
*/
public ExplorerComponent(ExplorerModel explorerModel,
PropertyPolling propertyPolling) {
this.propertyPolling = propertyPolling;
this.explorerModel = explorerModel;
// create the only detail model. At the moment this component
// can only show the detail on one node at a time but the
// model is written so that this could change.
detailModel = new DetailModel();
DetailView detailView = new DetailView(detailModel);
propertyPolling.setPropertyModel(detailModel.getPropertyModel());
detailModel.addPropertyChangeListener(
propertyPolling);
DetailController detailControl = new DetailController(detailModel, detailView);
JobTreeModel treeModel = new JobTreeModel();
JobTreeNode rootTreeNode = new JobTreeNode(explorerModel, treeModel);
treeModel.setRootTreeNode(rootTreeNode);
tree = new ArooaTree(treeModel) {
private static final long serialVersionUID = 200801150100L;
@Override
public DragPoint getDragPoint(Object treeNode) {
JobTreeNode jobTreeNode = (JobTreeNode) treeNode;
ConfigContextSearch search = new ConfigContextSearch();
return search.dragPointFor(
jobTreeNode.getExplorerContext());
}
};
NodeControl nodeControl = new NodeControl();
tree.addTreeWillExpandListener(nodeControl);
tree.setShowsRootHandles(true);
tree.getSelectionModel().setSelectionMode
(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addTreeSelectionListener(detailControl);
tree.setCellRenderer(new JobTreeCellRenderer());
ToolTipManager.sharedInstance().registerComponent(tree);
tree.setDragEnabled(true);
tree.setDropMode(DropMode.ON_OR_INSERT);
treeChangeFollower = new TreeChangeFollower(tree);
tree.addAncestorListener(new AncestorListener() {
@Override
public void ancestorRemoved(AncestorEvent event) {
tree.removeAncestorListener(this);
}
@Override
public void ancestorMoved(AncestorEvent event) {
}
@Override
public void ancestorAdded(AncestorEvent event) {
// This must happen after the bindTo method has been called.
tree.setSelectionPath(new TreePath(tree.getModel().getRoot()));
tree.requestFocusInWindow();
}
});
ArooaTransferHandler transferHandler = new ArooaTransferHandler();
transferHandler.addTransferEventListener(new TransferEventListener() {
public void transferException(TransferEvent event, String message, Exception exception) {
String text = message + "\n" + "Cause: " + exception.getMessage();
JOptionPane.showMessageDialog(
tree,
text,
"Error",
JOptionPane.ERROR_MESSAGE);
}
});
tree.setTransferHandler(transferHandler);
// Order is important here otherwise the child is show without firing
// the WillExpand listener - Don't know why.
rootTreeNode.setVisible(true);
setLayout(new BorderLayout());
treeScroll = new JScrollPane();
treeScroll.setViewportView(tree);
split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
treeScroll, detailView);
add(split);
}
/**
*
* @param monitorMeuBar
*/
public void bindTo(MonitorMenuBar monitorMenuBar) {
if (this.menuBar != null) {
throw new IllegalStateException("MonitorMenuBar already bound.");
}
this.menuBar = monitorMenuBar;
ExplorerJobActions jobActions = new ExplorerJobActions(
explorerModel.getExplorerActions());
menuBar.setSession(jobActions, detailModel);
jobActions.addKeyStrokes(this);
new TreePopup(tree, menuBar);
}
/**
* Clear up the component.
*
*/
public void destroy() {
detailModel.removePropertyChangeListener(
propertyPolling);
treeChangeFollower.close();
}
public void balance() {
split.setDividerLocation((int) (0.33 * split.getPreferredSize().getWidth()));
}
public JTree getTree() {
return tree;
}
}