package hep.io.root.util;
import hep.io.root.RootClassNotFound;
import hep.io.root.RootFileReader;
import hep.io.root.RootObject;
import hep.io.root.daemon.RootAuthenticator;
import hep.io.root.daemon.xrootd.XrootdURLStreamFactory;
import hep.io.root.interfaces.TKey;
import hep.io.root.interfaces.TNamed;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.net.Authenticator;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
/**
* A simple application for browsing the contents of Root Files
* @author Tony Johnson (tonyj@slac.stanford.edu)
* @version $Id: RootObjectBrowser.java 12934 2007-07-05 18:46:15Z tonyj $
*/
public class RootObjectBrowser extends JPanel implements TreeSelectionListener
{
private final static String aboutMessage = "<HTML>RootObjectBrowser $Id: RootObjectBrowser.java 12934 2007-07-05 18:46:15Z tonyj $<br>Author: Tony Johnson (tonyj@slac.stanford.edu)";
private final static TreeModel emptyTree = null;
private JTree objTree;
private JTree tree;
private RootFileReader reader;
private RootMenuBar menuBar;
public RootObjectBrowser()
{
super(new BorderLayout());
tree = new JTree(emptyTree);
tree.setCellRenderer(new RootDirectoryTreeCellRenderer());
tree.addTreeSelectionListener(this);
objTree = new JTree(emptyTree);
objTree.setCellRenderer(new RootObjectTreeCellRenderer());
ToolTipManager.sharedInstance().registerComponent(objTree);
JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(tree), new JScrollPane(objTree));
add(split, BorderLayout.CENTER);
add(menuBar = new RootMenuBar(), BorderLayout.NORTH);
menuBar.setFileOpen(false);
setPreferredSize(new Dimension(500, 300));
split.setDividerLocation(245);
ToolTipManager.sharedInstance().setEnabled(true);
}
public void setRootFile(File file) throws IOException
{
Cursor old = getCursor();
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try
{
reader = new RootFileReader(file);
TreeModel model = new RootDirectoryTreeModel(reader)
{
public void handleException(IOException x)
{
error(x);
x.printStackTrace();
super.handleException(x);
}
};
tree.setModel(model);
tree.setRowHeight(20);
tree.setLargeModel(true);
menuBar.setFileOpen(true);
}
finally
{
setCursor(old);
}
}
public void setRootFile(URL url) throws IOException
{
Cursor old = getCursor();
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try
{
reader = new RootFileReader(url);
TreeModel model = new RootDirectoryTreeModel(reader)
{
public void handleException(IOException x)
{
error(x);
x.printStackTrace();
super.handleException(x);
}
};
tree.setModel(model);
tree.setRowHeight(20);
tree.setLargeModel(true);
menuBar.setFileOpen(true);
}
finally
{
setCursor(old);
}
}
public static void main(String[] argv) throws IOException
{
if (argv.length > 1)
usage();
if ((argv.length == 1) && argv[0].startsWith("-"))
usage();
URL.setURLStreamHandlerFactory(new XrootdURLStreamFactory());
JFrame frame = new JFrame("Root Object Browser");
RootObjectBrowser browser = new RootObjectBrowser();
Authenticator.setDefault(new RootAuthenticator(browser));
URLConnection.setDefaultAllowUserInteraction(true);
if (argv.length == 1)
{
if (argv[0].startsWith("root:")) browser.setRootFile(new URL(argv[0]));
else browser.setRootFile(new File(argv[0]));
}
frame.setContentPane(browser);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public void valueChanged(TreeSelectionEvent event)
{
if (!event.isAddedPath())
return;
Cursor old = getCursor();
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try
{
TreePath path = tree.getSelectionPath();
if (path == null)
objTree.setModel(emptyTree);
else
{
List save = saveToggledBranches(objTree);
Object node = path.getLastPathComponent();
if (node instanceof BranchEntry)
node = ((BranchEntry) node).getValue();
if (node instanceof TKey)
{
TKey key = (TKey) node;
objTree.setModel(new RootObjectTreeModel(key.getObject(), key.getName()));
}
else if (node instanceof TNamed)
objTree.setModel(new RootObjectTreeModel(node, ((TNamed) node).getName()));
else if (node instanceof RootObject)
objTree.setModel(new RootObjectTreeModel(node, ""));
else if (node.getClass().isArray())
objTree.setModel(new RootObjectTreeModel(node, ""));
else if (node instanceof List)
objTree.setModel(new RootObjectTreeModel(node, ""));
else if (node instanceof Map)
objTree.setModel(new RootObjectTreeModel(node, ""));
else
objTree.setModel(emptyTree);
restoreToggledBranches(objTree, save);
}
}
catch (RootClassNotFound x)
{
objTree.setModel(emptyTree);
x.printStackTrace();
error(x);
}
catch (IOException x)
{
objTree.setModel(emptyTree);
x.printStackTrace();
error(x);
}
finally
{
setCursor(old);
}
}
private static void usage()
{
System.out.println("java RootObjectBrowser [<file>]");
System.exit(0);
}
private void error(Throwable x)
{
x.printStackTrace();
JOptionPane.showMessageDialog(this, x.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
private void restoreToggledBranches(JTree tree, List save)
{
TreeModel model = tree.getModel();
if (model == null)
return;
Object root = model.getRoot();
Iterator iter = save.iterator();
outer: while (iter.hasNext())
{
Object parent = root;
TreePath realPath = new TreePath(root);
TreePath path = (TreePath) iter.next();
Object[] nodes = path.getPath();
for (int i = 1; i < nodes.length; i++)
{
String node = (String) nodes[i];
int pos = node.indexOf(' ');
int index = Integer.parseInt(node.substring(0, pos));
if (index >= model.getChildCount(parent))
continue outer;
Object n = model.getChild(parent, index);
parent = n;
if (n.toString().equals(node.substring(pos + 1)))
realPath = realPath.pathByAddingChild(n);
else
continue outer;
}
tree.expandPath(realPath);
}
}
private List saveToggledBranches(JTree tree)
{
List save = new ArrayList();
TreeModel model = tree.getModel();
if (model == null)
return save;
Object root = model.getRoot();
TreePath rootPath = new TreePath(new Object[] { root });
Enumeration e = tree.getExpandedDescendants(rootPath);
if (e == null)
return save;
while (e.hasMoreElements())
{
Object parent = root;
TreePath path = (TreePath) e.nextElement();
// canonicalize the elements
Object[] nodes = path.getPath();
if (nodes.length < 2)
continue;
for (int i = 0; i < nodes.length; i++)
{
Object node = nodes[i];
int index = model.getIndexOfChild(parent, node);
parent = node;
nodes[i] = String.valueOf(index) + " " + node.toString();
}
TreePath newPath = new TreePath(nodes);
save.add(newPath);
}
return save;
}
private void showStreamerInfo()
{
try
{
Comparator sortByName = new Comparator()
{
public int compare(Object a, Object b)
{
return ((TNamed) a).getName().compareTo(((TNamed) b).getName());
}
public boolean equals(Object o)
{
return o.getClass() == this.getClass();
}
};
List streamerInfo = new ArrayList(reader.streamerInfo());
Collections.sort(streamerInfo, sortByName);
StreamerInfoBrowser browser = new StreamerInfoBrowser(streamerInfo);
JFrame f = new JFrame("Root Streamer Info Browser");
f.setContentPane(browser);
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.pack();
f.setVisible(true);
}
catch (IOException x)
{
error(x);
}
}
private static class RootFileFilter extends FileFilter
{
public String getDescription()
{
return "Root Files (*.root)";
}
public boolean accept(File file)
{
return file.isDirectory() || file.getName().endsWith(".root");
}
}
private class RootFileMenu extends JMenu
{
RootFileMenu()
{
super("File");
add(new JMenuItem("Open File...")
{
public void fireActionPerformed(ActionEvent e)
{
JFileChooser dlg = new JFileChooser("Open Root File...");
dlg.setFileFilter(new RootFileFilter());
int rc = dlg.showOpenDialog(RootObjectBrowser.this);
if (rc == JFileChooser.APPROVE_OPTION)
{
try
{
setRootFile(dlg.getSelectedFile());
}
catch (IOException x)
{
error(x);
}
}
}
});
add(new JMenuItem("Open URL...")
{
public void fireActionPerformed(ActionEvent e)
{
String url = JOptionPane.showInputDialog(RootObjectBrowser.this,"URL","root://");
if (url != null)
{
try
{
setRootFile(new URL(url));
}
catch (IOException x)
{
error(x);
}
}
}
});
add(new JMenuItem("Exit")
{
public void fireActionPerformed(ActionEvent e)
{
System.exit(0);
}
});
}
}
private class RootHelpMenu extends JMenu
{
RootHelpMenu()
{
super("Help");
add(new JMenuItem("About...")
{
public void fireActionPerformed(ActionEvent e)
{
JOptionPane.showMessageDialog(RootObjectBrowser.this, aboutMessage);
}
});
}
}
private class RootMenuBar extends JMenuBar
{
private RootToolsMenu tools;
RootMenuBar()
{
add(new RootFileMenu());
add(tools = new RootToolsMenu());
add(new RootHelpMenu());
}
void setFileOpen(boolean state)
{
tools.setFileOpen(state);
}
}
private class RootToolsMenu extends JMenu
{
private JMenuItem view;
RootToolsMenu()
{
super("Tools");
add(view = new JMenuItem("View Streamer Info...")
{
public void fireActionPerformed(ActionEvent e)
{
showStreamerInfo();
}
});
}
void setFileOpen(boolean state)
{
view.setEnabled(state);
}
}
}