/*
 * Copyright (c) 1998, 2000, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 */

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.tree.*;
import javax.swing.undo.*;
import java.awt.*;
import java.beans.*;
import java.util.*;

/**
 * Displays a tree showing all the elements in a text Document. Selecting
 * a node will result in reseting the selection of the JTextComponent.
 * This also becomes a CaretListener to know when the selection has changed
 * in the text to update the selected item in the tree.
 *
 * @author Scott Violet
 */
public class ElementTreePanel extends JPanel implements CaretListener, DocumentListener, PropertyChangeListener, TreeSelectionListener {
    /** Tree showing the documents element structure. */
    protected JTree             tree;
    /** Text component showing elemenst for. */
    protected JTextComponent    editor;
    /** Model for the tree. */
    protected ElementTreeModel  treeModel;
    /** Set to true when updatin the selection. */
    protected boolean           updatingSelection;

    public ElementTreePanel(JTextComponent editor) {
        this.editor = editor;

        Document document = editor.getDocument();

        // Create the tree.
        treeModel = new ElementTreeModel(document);
        tree = new JTree(treeModel) {
            public String convertValueToText(Object value, boolean selected,
                                             boolean expanded, boolean leaf,
                                             int row, boolean hasFocus) {
                // Should only happen for the root
                if(!(value instanceof Element))
                    return value.toString();

                Element        e = (Element)value;
                AttributeSet   as = e.getAttributes().copyAttributes();
                String         asString;

                if(as != null) {
                    StringBuffer       retBuffer = new StringBuffer("[");
                    Enumeration        names = as.getAttributeNames();

                    while(names.hasMoreElements()) {
                        Object        nextName = names.nextElement();

                        if(nextName != StyleConstants.ResolveAttribute) {
                            retBuffer.append(" ");
                            retBuffer.append(nextName);
                            retBuffer.append("=");
                            retBuffer.append(as.getAttribute(nextName));
                        }
                    }
                    retBuffer.append(" ]");
                    asString = retBuffer.toString();
                }
                else
                    asString = "[ ]";

                if(e.isLeaf())
                    return e.getName() + " [" + e.getStartOffset() +
                        ", " + e.getEndOffset() +"] Attributes: " + asString;
                return e.getName() + " [" + e.getStartOffset() +
                    ", " + e.getEndOffset() + "] Attributes: " +
                        asString;
            }
        };
        tree.addTreeSelectionListener(this);
        tree.setDragEnabled(true);
        // Don't show the root, it is fake.
        tree.setRootVisible(false);
        // Since the display value of every node after the insertion point
        // changes every time the text changes and we don't generate a change
        // event for all those nodes the display value can become off.
        // This can be seen as '...' instead of the complete string value.
        // This is a temporary workaround, increase the needed size by 15,
        // hoping that will be enough.
        tree.setCellRenderer(new DefaultTreeCellRenderer() {
            public Dimension getPreferredSize() {
                Dimension retValue = super.getPreferredSize();
                if(retValue != null)
                    retValue.width += 15;
                return retValue;
            }
        });
        // become a listener on the document to update the tree.
        document.addDocumentListener(this);

        // become a PropertyChangeListener to know when the Document has
        // changed.
        editor.addPropertyChangeListener(this);

        // Become a CaretListener
        editor.addCaretListener(this);

        // configure the panel and frame containing it.
        setLayout(new BorderLayout());
        add(new JScrollPane(tree), BorderLayout.CENTER);

        // Add a label above tree to describe what is being shown
        JLabel     label = new JLabel("Elements that make up the current document", SwingConstants.CENTER);

        label.setFont(new Font("Dialog", Font.BOLD, 14));
        add(label, BorderLayout.NORTH);

        setPreferredSize(new Dimension(400, 400));
    }

    /**
     * Resets the JTextComponent to <code>editor</code>. This will update
     * the tree accordingly.
     */
    public void setEditor(JTextComponent editor) {
        if (this.editor == editor) {
            return;
        }

        if (this.editor != null) {
            Document      oldDoc = this.editor.getDocument();

            oldDoc.removeDocumentListener(this);
            this.editor.removePropertyChangeListener(this);
            this.editor.removeCaretListener(this);
        }
        this.editor = editor;
        if (editor == null) {
            treeModel = null;
            tree.setModel(null);
        }
        else {
            Document   newDoc = editor.getDocument();

            newDoc.addDocumentListener(this);
            editor.addPropertyChangeListener(this);
            editor.addCaretListener(this);
            treeModel = new ElementTreeModel(newDoc);
            tree.setModel(treeModel);
        }
    }

    // PropertyChangeListener

    /**
     * Invoked when a property changes. We are only interested in when the
     * Document changes to reset the DocumentListener.
     */
    public void propertyChange(PropertyChangeEvent e) {
        if (e.getSource() == getEditor() &&
            e.getPropertyName().equals("document")) {
            JTextComponent      editor = getEditor();
            Document            oldDoc = (Document)e.getOldValue();
            Document            newDoc = (Document)e.getNewValue();

            // Reset the DocumentListener
            oldDoc.removeDocumentListener(this);
            newDoc.addDocumentListener(this);

            // Recreate the TreeModel.
            treeModel = new ElementTreeModel(newDoc);
            tree.setModel(treeModel);
        }
    }


    // DocumentListener

    /**
     * Gives notification that there was an insert into the document.  The
     * given range bounds the freshly inserted region.
     *
     * @param e the document event
     */
    public void insertUpdate(DocumentEvent e) {
        updateTree(e);
    }

    /**
     * Gives notification that a portion of the document has been
     * removed.  The range is given in terms of what the view last
     * saw (that is, before updating sticky positions).
     *
     * @param e the document event
     */
    public void removeUpdate(DocumentEvent e) {
        updateTree(e);
    }

    /**
     * Gives notification that an attribute or set of attributes changed.
     *
     * @param e the document event
     */
    public void changedUpdate(DocumentEvent e) {
        updateTree(e);
    }

    // CaretListener

    /**
     * Messaged when the selection in the editor has changed. Will update
     * the selection in the tree.
     */
    public void caretUpdate(CaretEvent e) {
        if(!updatingSelection) {
            JTextComponent     editor = getEditor();
            int                selBegin = Math.min(e.getDot(), e.getMark());
            int                end = Math.max(e.getDot(), e.getMark());
            Vector             paths = new Vector();
            TreeModel          model = getTreeModel();
            Object             root = model.getRoot();
            int                rootCount = model.getChildCount(root);

            // Build an array of all the paths to all the character elements
            // in the selection.
            for(int counter = 0; counter < rootCount; counter++) {
                int            start = selBegin;

                while(start <= end) {
                    TreePath    path = getPathForIndex(start, root,
                                       (Element)model.getChild(root, counter));
                    Element     charElement = (Element)path.
                                               getLastPathComponent();

                    paths.addElement(path);
                    if(start >= charElement.getEndOffset())
                        start++;
                    else
                        start = charElement.getEndOffset();
                }
            }

            // If a path was found, select it (them).
            int               numPaths = paths.size();

            if(numPaths > 0) {
                TreePath[]    pathArray = new TreePath[numPaths];

                paths.copyInto(pathArray);
                updatingSelection = true;
                try {
                    getTree().setSelectionPaths(pathArray);
                    getTree().scrollPathToVisible(pathArray[0]);
                }
                finally {
                    updatingSelection = false;
                }
            }
        }
    }

    // TreeSelectionListener

    /**
      * Called whenever the value of the selection changes.
      * @param e the event that characterizes the change.
      */
    public void valueChanged(TreeSelectionEvent e) {
        JTree       tree = getTree();

        if(!updatingSelection && tree.getSelectionCount() == 1) {
            TreePath      selPath = tree.getSelectionPath();
            Object        lastPathComponent = selPath.getLastPathComponent();

            if(!(lastPathComponent instanceof DefaultMutableTreeNode)) {
                Element       selElement = (Element)lastPathComponent;

                updatingSelection = true;
                try {
                    getEditor().select(selElement.getStartOffset(),
                                       selElement.getEndOffset());
                }
                finally {
                    updatingSelection = false;
                }
            }
        }
    }

    // Local methods

    /**
     * @return tree showing elements.
     */
    protected JTree getTree() {
        return tree;
    }

    /**
     * @return JTextComponent showing elements for.
     */
    protected JTextComponent getEditor() {
        return editor;
    }

    /**
     * @return TreeModel implementation used to represent the elements.
     */
    public DefaultTreeModel getTreeModel() {
        return treeModel;
    }

    /**
     * Updates the tree based on the event type. This will invoke either
     * updateTree with the root element, or handleChange.
     */
    protected void updateTree(DocumentEvent event) {
        updatingSelection = true;
        try {
            TreeModel        model = getTreeModel();
            Object           root = model.getRoot();

            for(int counter = model.getChildCount(root) - 1; counter >= 0;
                counter--) {
                updateTree(event, (Element)model.getChild(root, counter));
            }
        }
        finally {
            updatingSelection = false;
        }
    }

    /**
     * Creates TreeModelEvents based on the DocumentEvent and messages
     * the treemodel. This recursively invokes this method with children
     * elements.
     * @param event indicates what elements in the tree hierarchy have
     * changed.
     * @param element Current element to check for changes against.
     */
    protected void updateTree(DocumentEvent event, Element element) {
        DocumentEvent.ElementChange ec = event.getChange(element);

        if (ec != null) {
            Element[]       removed = ec.getChildrenRemoved();
            Element[]       added = ec.getChildrenAdded();
            int             startIndex = ec.getIndex();

            // Check for removed.
            if(removed != null && removed.length > 0) {
                int[]            indices = new int[removed.length];

                for(int counter = 0; counter < removed.length; counter++) {
                    indices[counter] = startIndex + counter;
                }
                getTreeModel().nodesWereRemoved((TreeNode)element, indices,
                                                removed);
            }
            // check for added
            if(added != null && added.length > 0) {
                int[]            indices = new int[added.length];

                for(int counter = 0; counter < added.length; counter++) {
                    indices[counter] = startIndex + counter;
                }
                getTreeModel().nodesWereInserted((TreeNode)element, indices);
            }
        }
        if(!element.isLeaf()) {
            int        startIndex = element.getElementIndex
                                       (event.getOffset());
            int        elementCount = element.getElementCount();
            int        endIndex = Math.min(elementCount - 1,
                                           element.getElementIndex
                                     (event.getOffset() + event.getLength()));

            if(startIndex > 0 && startIndex < elementCount &&
               element.getElement(startIndex).getStartOffset() ==
               event.getOffset()) {
                // Force checking the previous element.
                startIndex--;
            }
            if(startIndex != -1 && endIndex != -1) {
                for(int counter = startIndex; counter <= endIndex; counter++) {
                    updateTree(event, element.getElement(counter));
                }
            }
        }
        else {
            // Element is a leaf, assume it changed
            getTreeModel().nodeChanged((TreeNode)element);
        }
    }

    /**
     * Returns a TreePath to the element at <code>position</code>.
     */
    protected TreePath getPathForIndex(int position, Object root,
                                       Element rootElement) {
        TreePath         path = new TreePath(root);
        Element          child = rootElement.getElement
                                    (rootElement.getElementIndex(position));

        path = path.pathByAddingChild(rootElement);
        path = path.pathByAddingChild(child);
        while(!child.isLeaf()) {
            child = child.getElement(child.getElementIndex(position));
            path = path.pathByAddingChild(child);
        }
        return path;
    }


    /**
     * ElementTreeModel is an implementation of TreeModel to handle displaying
     * the Elements from a Document. AbstractDocument.AbstractElement is
     * the default implementation used by the swing text package to implement
     * Element, and it implements TreeNode. This makes it trivial to create
     * a DefaultTreeModel rooted at a particular Element from the Document.
     * Unfortunately each Document can have more than one root Element.
     * Implying that to display all the root elements as a child of another
     * root a fake node has be created. This class creates a fake node as
     * the root with the children being the root elements of the Document
     * (getRootElements).
     * <p>This subclasses DefaultTreeModel. The majority of the TreeModel
     * methods have been subclassed, primarily to special case the root.
     */
    public static class ElementTreeModel extends DefaultTreeModel {
        protected Element[]         rootElements;

        public ElementTreeModel(Document document) {
            super(new DefaultMutableTreeNode("root"), false);
            rootElements = document.getRootElements();
        }

        /**
         * Returns the child of <I>parent</I> at index <I>index</I> in
         * the parent's child array.  <I>parent</I> must be a node
         * previously obtained from this data source. This should
         * not return null if <i>index</i> is a valid index for
         * <i>parent</i> (that is <i>index</i> >= 0 && <i>index</i>
         * < getChildCount(<i>parent</i>)).
         *
         * @param   parent  a node in the tree, obtained from this data source
         * @return  the child of <I>parent</I> at index <I>index</I>
         */
        public Object getChild(Object parent, int index) {
            if(parent == root)
                return rootElements[index];
            return super.getChild(parent, index);
        }


        /**
         * Returns the number of children of <I>parent</I>.  Returns 0
         * if the node is a leaf or if it has no children.
         * <I>parent</I> must be a node previously obtained from this
         * data source.
         *
         * @param   parent  a node in the tree, obtained from this data source
         * @return  the number of children of the node <I>parent</I>
         */
        public int getChildCount(Object parent) {
            if(parent == root)
                return rootElements.length;
            return super.getChildCount(parent);
        }


        /**
         * Returns true if <I>node</I> is a leaf.  It is possible for
         * this method to return false even if <I>node</I> has no
         * children.  A directory in a filesystem, for example, may
         * contain no files; the node representing the directory is
         * not a leaf, but it also has no children.
         *
         * @param   node    a node in the tree, obtained from this data source
         * @return  true if <I>node</I> is a leaf
         */
        public boolean isLeaf(Object node) {
            if(node == root)
                return false;
            return super.isLeaf(node);
        }

        /**
         * Returns the index of child in parent.
         */
        public int getIndexOfChild(Object parent, Object child) {
            if(parent == root) {
                for(int counter = rootElements.length - 1; counter >= 0;
                    counter--) {
                    if(rootElements[counter] == child)
                        return counter;
                }
                return -1;
            }
            return super.getIndexOfChild(parent, child);
        }

        /**
         * Invoke this method after you've changed how node is to be
         * represented in the tree.
         */
        public void nodeChanged(TreeNode node) {
            if(listenerList != null && node != null) {
                TreeNode         parent = node.getParent();

                if(parent == null && node != root) {
                    parent = root;
                }
                if(parent != null) {
                    int        anIndex = getIndexOfChild(parent, node);

                    if(anIndex != -1) {
                        int[]        cIndexs = new int[1];

                        cIndexs[0] = anIndex;
                        nodesChanged(parent, cIndexs);
                    }
                }
            }
        }

        /**
         * Returns the path to a particluar node. This is recursive.
         */
        protected TreeNode[] getPathToRoot(TreeNode aNode, int depth) {
            TreeNode[]              retNodes;

            /* Check for null, in case someone passed in a null node, or
               they passed in an element that isn't rooted at root. */
            if(aNode == null) {
                if(depth == 0)
                    return null;
                else
                    retNodes = new TreeNode[depth];
            }
            else {
                depth++;
                if(aNode == root)
                    retNodes = new TreeNode[depth];
                else {
                    TreeNode parent = aNode.getParent();

                    if(parent == null)
                        parent = root;
                    retNodes = getPathToRoot(parent, depth);
                }
                retNodes[retNodes.length - depth] = aNode;
            }
            return retNodes;
        }
    }
}
