package ca.janeg.cb; import java.awt.Dimension; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.ListIterator; import java.util.StringTokenizer; import java.util.TreeMap; import javax.swing.JPanel; 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.TreeNode; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; /** * Builds and contains the JTree used to display the class heirarchy. * * @author Jane Griscti jane@janeg.ca * @created January 26, 2002 */ class CBTreePanel extends JPanel { private ClassBrowser parent; private JTree tree = new JTree(); private DefaultMutableTreeNode classTree; private DefaultMutableTreeNode pkgTree; private CBClassGroup classGroup; private Collection sortedClasses = new ArrayList(); /** * Constructs a CBTreePanel object. * * @param frame the ClassBrowser object to contain the panel * @param cbcg the CBClassGroup to be displayed */ CBTreePanel( final ClassBrowser frame, final CBClassGroup cbcg ) { super(); parent = frame; classGroup = cbcg; buildPkgTree(); buildClassTree(); switchToPkgTree(); tree.putClientProperty( "JTree.lineStyle", "Angled" ); tree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION ); tree.addTreeSelectionListener( new CBTreeListener() ); JScrollPane jsp = new JScrollPane( tree ); jsp.setPreferredSize( new Dimension( 300, 500 ) ); jsp.setMinimumSize( jsp.getPreferredSize() ); add( jsp ); } /** Builds a tree model based on the class package names. */ private void buildPkgTree() { DefaultMutableTreeNode top = new DefaultMutableTreeNode( classGroup.getGroupName() ); DefaultMutableTreeNode prevNode; DefaultMutableTreeNode node; String element; String key = ""; StringBuffer keyBuf = new StringBuffer( "" ); String keyBufStr; TreeMap map = new TreeMap(); prevNode = top; String[] pkgs = classGroup.getByPackageName(); // build tree nodes for( int i = 0; i < pkgs.length; i++ ) { element = pkgs[i]; keyBuf = new StringBuffer( element.length() ); keyBufStr = ""; StringTokenizer stok = new StringTokenizer( element, "/" ); ClassInfo data = null; int tokenCount = 0; while( stok.hasMoreTokens() ) { key = stok.nextToken(); tokenCount++; keyBuf.append( key + '.' ); keyBufStr = keyBuf.toString(); if( map.containsKey( keyBufStr ) ) { prevNode = (DefaultMutableTreeNode)map.get( keyBufStr ); } else { data = new ClassInfo( keyBufStr, key ); node = new DefaultMutableTreeNode( data ); // check for top level package names if( tokenCount == 1 ) { top.add( node ); } else { prevNode.add( node ); } prevNode = node; map.put( keyBufStr, node ); sortedClasses.add( data ); } } } pkgTree = top; } /* * Builds a tree model based on the class names.<p> * * Note: This is not built by using the CBClassGroup sorted classes. It * uses the same ClassInfo objects created for the package tree. */ private void buildClassTree() { Collections.sort( (ArrayList)sortedClasses, CBNameComparator.getInstance() ); ListIterator liter = ( (ArrayList)sortedClasses ).listIterator(); DefaultMutableTreeNode classTop = new DefaultMutableTreeNode( classGroup.getGroupName() ); DefaultMutableTreeNode node; ClassInfo element; while( liter.hasNext() ) { element = (ClassInfo)liter.next(); node = new DefaultMutableTreeNode( element ); classTop.add( node ); } sortedClasses = null; // finished with sorted classes classTree = classTop; } /** * Switches the JTree model to the sorted class tree model. * The display is automatically updated. */ void switchToClassTree() { DefaultTreeModel model = (DefaultTreeModel)tree.getModel(); model.setRoot( classTree ); model.reload(); } /** * Switches the JTree model to the package name tree model. * The display is automatically updated. */ void switchToPkgTree() { DefaultTreeModel model = (DefaultTreeModel)tree.getModel(); model.setRoot( pkgTree ); model.reload(); } /** * The listener for the JTree contained in CBTreePanel. * * @author Jane Griscti jane@janeg.ca * @created January 26, 2002 */ private class CBTreeListener implements TreeSelectionListener { public void valueChanged( TreeSelectionEvent e ) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); if( node == null ) { return; } if( node.isLeaf() ) { ClassInfo classInfo = (ClassInfo)node.getUserObject(); parent.displayClassInfo( classInfo.qualifiedName ); } } } /** * Separates the class name from the package name and stores them * separately. A ClassInfo object acts as a leaf node in the JTree. * * @author Jane Griscti jane@janeg.ca * @created January 5, 2002 */ class ClassInfo { String qualifiedName; String className; /** * Constructs a new ClassInfo object * * @param fullpath the fully qualifed class name * @param name the simple class name */ ClassInfo( String fullpath, String name ) { fullpath = fullpath.substring( 0, fullpath.length() - 1 ); qualifiedName = fullpath; className = name; } public String getQualifiedName() { return qualifiedName; } /** * Overrides Object.toString() to provide each node with a display * name; that of the class it represents. * *@return Description of the Returned Value */ public String toString() { return className; } } }