package bibliothek.help.javadoc.inspection; import java.awt.BorderLayout; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.HashMap; import java.util.Map; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; import bibliothek.extension.gui.dock.theme.FlatTheme; import bibliothek.gui.DockFrontend; import bibliothek.gui.dock.DefaultDockable; import bibliothek.gui.dock.SplitDockStation; import bibliothek.gui.dock.station.split.SplitDockGrid; import bibliothek.gui.dock.themes.NoStackTheme; import bibliothek.help.javadoc.Entryable; import bibliothek.help.model.Entry; /** * A class that shows the structure of a tree of {@link Entryable}s. This * object also creates an {@link InspectionPanel} which will be updated whenever * the user selects another {@link Node node} of the tree. * @author Benjamin Sigg * */ public class InspectionTree extends JTree{ /** the panel showing the contents of the currently selected {@link Entryable} */ private InspectionPanel panel; /** shows which {@link Node} to select for a given link */ private Map<String, Node> links = new HashMap<String, Node>(); /** * Opens a frame showing the tree that has <code>entryable</code> as root, * and additionally an {@link InspectionPanel}. This method blocks until * the frame has been closed. * @param entryable the root of the tree */ public static void inspect( Entryable entryable ){ DockFrontend frontend = new DockFrontend(); frontend.getController().setTheme( new NoStackTheme( new FlatTheme() ) ); SplitDockStation station = new SplitDockStation(); frontend.addRoot( "station", station ); final JFrame frame = new JFrame( "Inspect" ); InspectionTree tree = new InspectionTree( entryable ); SplitDockGrid grid = new SplitDockGrid(); grid.addDockable( 0, 0, 1, 1, new DefaultDockable( new JScrollPane( tree ), "Tree" )); grid.addDockable( 1, 0, 1, 1, new DefaultDockable( new JScrollPane( tree.getPanel() ), "Entry" )); station.dropTree( grid.toTree() ); frame.add( station, BorderLayout.CENTER ); frame.setBounds( 20, 20, 500, 300 ); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); final Object LOCK = new Object(); frame.setVisible( true ); frame.addWindowListener( new WindowAdapter(){ @Override public void windowClosing( WindowEvent e ) { frame.setVisible( false ); synchronized( LOCK ){ LOCK.notify(); } } }); while( frame.isVisible() ){ synchronized( LOCK ){ try { LOCK.wait( 1000 ); } catch( InterruptedException e ) { e.printStackTrace(); } } } } /** * Creates a new tree, using <code>entryable</code> as root. * @param entryable the root */ public InspectionTree( Entryable entryable ){ panel = new InspectionPanel(); panel.inspect( null ); DefaultTreeModel model = new DefaultTreeModel( new Node( entryable )); setModel( model ); addTreeSelectionListener( new TreeSelectionListener(){ public void valueChanged( TreeSelectionEvent e ) { Node node = (Node)getLastSelectedPathComponent(); if( node != null ) panel.inspect( node.getEntry() ); else panel.inspect( null ); } }); } /** * Gets the panel that shows the contents of the currently selected node * of this tree. * @return the panel */ public InspectionPanel getPanel() { return panel; } /** * Selects the {@link Entry} which has the name <code>link</code>. * @param link the name of the <code>Entry</code> */ public void select( String link ){ Node node = links.get( link ); if( node != null ){ setSelectionPath( new TreePath( node.getPath() ) ); } } /** * A wrapper of an {@link Entryable} used to easily combine * <code>Entryable</code> and {@link JTree}. * @author Benjamin Sigg */ private class Node extends DefaultMutableTreeNode{ /** the data of this node */ private Entry entry; /** * Creates a new node * @param entryable the content of this node */ public Node( Entryable entryable ){ this.entry = entryable.toEntry(); String link = entry.getType() + ":" + entry.getId(); setUserObject( link ); links.put( link, this ); for( Entryable child : entryable.children() ) add( new Node( child ) ); } /** * Gets the content of this node. * @return the content */ public Entry getEntry() { return entry; } } }