class OutlineTree extends JTree implements TreeSelectionListener, Observer {

    /**
     * A serial version uid.
     */
    private static final long serialVersionUID = 5646572654823301007L;
    /**
     * Nodes in the FormTree correspond with nodes in the main PdfTree.
     */
    protected PdfReaderController controller;

    /**
     * Creates a new outline tree.
     *
     * @param controller The renderer that will render an object when selected in the table.
     */
    public OutlineTree(PdfReaderController controller) {
        super();
        this.controller = controller;
        setCellRenderer(new IconTreeCellRenderer());
        setModel(new DefaultTreeModel(new OutlineTreeNode()));
        addTreeSelectionListener(this);
    }

    /**
     * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
     */
    public void update(Observable observable, Object obj) {
        if (obj == null) {
            setModel(new DefaultTreeModel(new OutlineTreeNode()));
            repaint();
            return;
        }
        if (obj instanceof ObjectLoader) {
            ObjectLoader loader = (ObjectLoader) obj;
            TreeNodeFactory factory = loader.getNodes();
            PdfTrailerTreeNode trailer = controller.getPdfTree().getRoot();
            PdfObjectTreeNode catalog = factory.getChildNode(trailer, PdfName.ROOT);
            PdfObjectTreeNode outline = factory.getChildNode(catalog, PdfName.OUTLINES);
            if (outline == null) {
                return;
            }
            OutlineTreeNode root = new OutlineTreeNode();
            loadOutline(factory, root, factory.getChildNode(outline, PdfName.FIRST));
            setModel(new DefaultTreeModel(root));
        }
    }

    /**
     * Method that can be used recursively to load the outline hierarchy into the tree.
     */
    private void loadOutline(TreeNodeFactory factory, OutlineTreeNode parent, PdfObjectTreeNode child) {
        OutlineTreeNode childnode = new OutlineTreeNode(child);
        parent.add(childnode);
        PdfObjectTreeNode first = factory.getChildNode(child, PdfName.FIRST);
        if (first != null) {
            loadOutline(factory, childnode, first);
        }
        PdfObjectTreeNode next = factory.getChildNode(child, PdfName.NEXT);
        if (next != null) {
            loadOutline(factory, parent, next);
        }
    }

    /**
     * @see javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event.TreeSelectionEvent)
     */
    public void valueChanged(TreeSelectionEvent evt) {<FILL_FUNCTION_BODY>}

}

        if (controller == null) {
            return;
        }
        OutlineTreeNode selectednode = (OutlineTreeNode) this.getLastSelectedPathComponent();
        PdfObjectTreeNode node = selectednode.getCorrespondingPdfObjectNode();
        if (node != null) {
            controller.selectNode(node);
        }
    
<methods>public void <init>() ,public void <init>(java.lang.Object[]) ,public void <init>(Vector<?>) ,public void <init>(Hashtable<?,?>) ,public void <init>(javax.swing.tree.TreeNode) ,public void <init>(javax.swing.tree.TreeModel) ,public void <init>(javax.swing.tree.TreeNode, boolean) ,public void addSelectionInterval(int, int) ,public void addSelectionPath(javax.swing.tree.TreePath) ,public void addSelectionPaths(javax.swing.tree.TreePath[]) ,public void addSelectionRow(int) ,public void addSelectionRows(int[]) ,public void addTreeExpansionListener(javax.swing.event.TreeExpansionListener) ,public void addTreeSelectionListener(javax.swing.event.TreeSelectionListener) ,public void addTreeWillExpandListener(javax.swing.event.TreeWillExpandListener) ,public void cancelEditing() ,public void clearSelection() ,public void collapsePath(javax.swing.tree.TreePath) ,public void collapseRow(int) ,public java.lang.String convertValueToText(java.lang.Object, boolean, boolean, boolean, int, boolean) ,public void expandPath(javax.swing.tree.TreePath) ,public void expandRow(int) ,public void fireTreeCollapsed(javax.swing.tree.TreePath) ,public void fireTreeExpanded(javax.swing.tree.TreePath) ,public void fireTreeWillCollapse(javax.swing.tree.TreePath) throws javax.swing.tree.ExpandVetoException,public void fireTreeWillExpand(javax.swing.tree.TreePath) throws javax.swing.tree.ExpandVetoException,public javax.accessibility.AccessibleContext getAccessibleContext() ,public javax.swing.tree.TreePath getAnchorSelectionPath() ,public javax.swing.tree.TreeCellEditor getCellEditor() ,public javax.swing.tree.TreeCellRenderer getCellRenderer() ,public javax.swing.tree.TreePath getClosestPathForLocation(int, int) ,public int getClosestRowForLocation(int, int) ,public boolean getDragEnabled() ,public final javax.swing.JTree.DropLocation getDropLocation() ,public final javax.swing.DropMode getDropMode() ,public javax.swing.tree.TreePath getEditingPath() ,public Enumeration<javax.swing.tree.TreePath> getExpandedDescendants(javax.swing.tree.TreePath) ,public boolean getExpandsSelectedPaths() ,public boolean getInvokesStopCellEditing() ,public java.lang.Object getLastSelectedPathComponent() ,public javax.swing.tree.TreePath getLeadSelectionPath() ,public int getLeadSelectionRow() ,public int getMaxSelectionRow() ,public int getMinSelectionRow() ,public javax.swing.tree.TreeModel getModel() ,public javax.swing.tree.TreePath getNextMatch(java.lang.String, int, javax.swing.text.Position.Bias) ,public java.awt.Rectangle getPathBounds(javax.swing.tree.TreePath) ,public javax.swing.tree.TreePath getPathForLocation(int, int) ,public javax.swing.tree.TreePath getPathForRow(int) ,public java.awt.Dimension getPreferredScrollableViewportSize() ,public java.awt.Rectangle getRowBounds(int) ,public int getRowCount() ,public int getRowForLocation(int, int) ,public int getRowForPath(javax.swing.tree.TreePath) ,public int getRowHeight() ,public int getScrollableBlockIncrement(java.awt.Rectangle, int, int) ,public boolean getScrollableTracksViewportHeight() ,public boolean getScrollableTracksViewportWidth() ,public int getScrollableUnitIncrement(java.awt.Rectangle, int, int) ,public boolean getScrollsOnExpand() ,public int getSelectionCount() ,public javax.swing.tree.TreeSelectionModel getSelectionModel() ,public javax.swing.tree.TreePath getSelectionPath() ,public javax.swing.tree.TreePath[] getSelectionPaths() ,public int[] getSelectionRows() ,public boolean getShowsRootHandles() ,public int getToggleClickCount() ,public java.lang.String getToolTipText(java.awt.event.MouseEvent) ,public javax.swing.event.TreeExpansionListener[] getTreeExpansionListeners() ,public javax.swing.event.TreeSelectionListener[] getTreeSelectionListeners() ,public javax.swing.event.TreeWillExpandListener[] getTreeWillExpandListeners() ,public javax.swing.plaf.TreeUI getUI() ,public java.lang.String getUIClassID() ,public int getVisibleRowCount() ,public boolean hasBeenExpanded(javax.swing.tree.TreePath) ,public boolean isCollapsed(javax.swing.tree.TreePath) ,public boolean isCollapsed(int) ,public boolean isEditable() ,public boolean isEditing() ,public boolean isExpanded(javax.swing.tree.TreePath) ,public boolean isExpanded(int) ,public boolean isFixedRowHeight() ,public boolean isLargeModel() ,public boolean isPathEditable(javax.swing.tree.TreePath) ,public boolean isPathSelected(javax.swing.tree.TreePath) ,public boolean isRootVisible() ,public boolean isRowSelected(int) ,public boolean isSelectionEmpty() ,public boolean isVisible(javax.swing.tree.TreePath) ,public void makeVisible(javax.swing.tree.TreePath) ,public void removeSelectionInterval(int, int) ,public void removeSelectionPath(javax.swing.tree.TreePath) ,public void removeSelectionPaths(javax.swing.tree.TreePath[]) ,public void removeSelectionRow(int) ,public void removeSelectionRows(int[]) ,public void removeTreeExpansionListener(javax.swing.event.TreeExpansionListener) ,public void removeTreeSelectionListener(javax.swing.event.TreeSelectionListener) ,public void removeTreeWillExpandListener(javax.swing.event.TreeWillExpandListener) ,public void scrollPathToVisible(javax.swing.tree.TreePath) ,public void scrollRowToVisible(int) ,public void setAnchorSelectionPath(javax.swing.tree.TreePath) ,public void setCellEditor(javax.swing.tree.TreeCellEditor) ,public void setCellRenderer(javax.swing.tree.TreeCellRenderer) ,public void setDragEnabled(boolean) ,public final void setDropMode(javax.swing.DropMode) ,public void setEditable(boolean) ,public void setExpandsSelectedPaths(boolean) ,public void setInvokesStopCellEditing(boolean) ,public void setLargeModel(boolean) ,public void setLeadSelectionPath(javax.swing.tree.TreePath) ,public void setModel(javax.swing.tree.TreeModel) ,public void setRootVisible(boolean) ,public void setRowHeight(int) ,public void setScrollsOnExpand(boolean) ,public void setSelectionInterval(int, int) ,public void setSelectionModel(javax.swing.tree.TreeSelectionModel) ,public void setSelectionPath(javax.swing.tree.TreePath) ,public void setSelectionPaths(javax.swing.tree.TreePath[]) ,public void setSelectionRow(int) ,public void setSelectionRows(int[]) ,public void setShowsRootHandles(boolean) ,public void setToggleClickCount(int) ,public void setUI(javax.swing.plaf.TreeUI) ,public void setVisibleRowCount(int) ,public void startEditingAtPath(javax.swing.tree.TreePath) ,public boolean stopEditing() ,public void treeDidChange() ,public void updateUI() <variables>static final boolean $assertionsDisabled,public static final java.lang.String ANCHOR_SELECTION_PATH_PROPERTY,public static final java.lang.String CELL_EDITOR_PROPERTY,public static final java.lang.String CELL_RENDERER_PROPERTY,public static final java.lang.String EDITABLE_PROPERTY,public static final java.lang.String EXPANDS_SELECTED_PATHS_PROPERTY,public static final java.lang.String INVOKES_STOP_CELL_EDITING_PROPERTY,public static final java.lang.String LARGE_MODEL_PROPERTY,public static final java.lang.String LEAD_SELECTION_PATH_PROPERTY,public static final java.lang.String ROOT_VISIBLE_PROPERTY,public static final java.lang.String ROW_HEIGHT_PROPERTY,public static final java.lang.String SCROLLS_ON_EXPAND_PROPERTY,public static final java.lang.String SELECTION_MODEL_PROPERTY,public static final java.lang.String SHOWS_ROOT_HANDLES_PROPERTY,private static int TEMP_STACK_SIZE,public static final java.lang.String TOGGLE_CLICK_COUNT_PROPERTY,public static final java.lang.String TREE_MODEL_PROPERTY,public static final java.lang.String VISIBLE_ROW_COUNT_PROPERTY,private javax.swing.tree.TreePath anchorPath,protected transient javax.swing.tree.TreeCellEditor cellEditor,protected transient javax.swing.tree.TreeCellRenderer cellRenderer,private boolean dragEnabled,private transient javax.swing.JTree.DropLocation dropLocation,private javax.swing.DropMode dropMode,private javax.swing.JTree.TreeTimer dropTimer,protected boolean editable,private int expandRow,private transient Stack<Stack<javax.swing.tree.TreePath>> expandedStack,private transient Hashtable<javax.swing.tree.TreePath,java.lang.Boolean> expandedState,private boolean expandsSelectedPaths,protected boolean invokesStopCellEditing,protected boolean largeModel,private javax.swing.tree.TreePath leadPath,protected boolean rootVisible,protected int rowHeight,private boolean rowHeightSet,protected boolean scrollsOnExpand,private boolean scrollsOnExpandSet,protected transient javax.swing.tree.TreeSelectionModel selectionModel,protected transient javax.swing.JTree.TreeSelectionRedirector selectionRedirector,private boolean settingUI,protected boolean showsRootHandles,private boolean showsRootHandlesSet,protected int toggleClickCount,protected transient javax.swing.tree.TreeModel treeModel,protected transient javax.swing.event.TreeModelListener treeModelListener,private static final java.lang.String uiClassID,private transient javax.swing.event.TreeExpansionListener uiTreeExpansionListener,private transient boolean updateInProgress,protected int visibleRowCount