/*
*
* 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
*
* - 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/**
* 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
*/
@SuppressWarnings("serial")
/** Tree showing the documents element structure. */
/** Text component showing elemenst for. */
/** Model for the tree. */
/** Set to true when updatin the selection. */
protected boolean updatingSelection;
@SuppressWarnings("LeakingThisInConstructor")
// Create the tree.
// Should only happen for the root
}
while (names.hasMoreElements()) {
}
}
} else {
asString = "[ ]";
}
if (e.isLeaf()) {
}
}
};
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.
public Dimension getPreferredSize() {
}
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 a label above tree to describe what is being shown
}
/**
* Resets the JTextComponent to <code>editor</code>. This will update
* the tree accordingly.
*/
return;
}
oldDoc.removeDocumentListener(this);
this.editor.removePropertyChangeListener(this);
this.editor.removeCaretListener(this);
}
} else {
newDoc.addDocumentListener(this);
editor.addPropertyChangeListener(this);
editor.addCaretListener(this);
}
}
// PropertyChangeListener
/**
* Invoked when a property changes. We are only interested in when the
* Document changes to reset the DocumentListener.
*/
"document")) {
// Reset the DocumentListener
oldDoc.removeDocumentListener(this);
newDoc.addDocumentListener(this);
// Recreate the 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
*/
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
*/
updateTree(e);
}
/**
* Gives notification that an attribute or set of attributes changed.
*
* @param e the document event
*/
updateTree(e);
}
// CaretListener
/**
* Messaged when the selection in the editor has changed. Will update
* the selection in the tree.
*/
if (!updatingSelection) {
// Build an array of all the paths to all the character elements
// in the selection.
start++;
} else {
}
}
}
// If a path was found, select it (them).
if (numPaths > 0) {
updatingSelection = true;
try {
} finally {
updatingSelection = false;
}
}
}
}
// TreeSelectionListener
/**
* Called whenever the value of the selection changes.
* @param e the event that characterizes the change.
*/
if (!(lastPathComponent instanceof DefaultMutableTreeNode)) {
updatingSelection = true;
try {
} finally {
updatingSelection = false;
}
}
}
}
// Local methods
/**
* @return tree showing elements.
*/
return tree;
}
/**
* @return JTextComponent showing elements for.
*/
return editor;
}
/**
* @return TreeModel implementation used to represent the elements.
*/
return treeModel;
}
/**
* Updates the tree based on the event type. This will invoke either
* updateTree with the root element, or handleChange.
*/
updatingSelection = true;
try {
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.
*/
// Check for removed.
}
removed);
}
// check for added
}
}
}
// Force checking the previous element.
startIndex--;
}
}
}
} else {
// Element is a leaf, assume it changed
}
}
/**
* Returns a TreePath to the element at <code>position</code>.
*/
position));
}
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.
*/
super(new DefaultMutableTreeNode("root"), false);
}
/**
* 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>
*/
return rootElements[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>
*/
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
*/
return false;
}
}
/**
* Returns the index of child in parent.
*/
counter--) {
return counter;
}
}
return -1;
}
}
/**
* Invoke this method after you've changed how node is to be
* represented in the tree.
*/
}
if (anIndex != -1) {
int[] cIndexs = new int[1];
}
}
}
}
/**
* Returns the path to a particluar node. This is recursive.
*/
/* Check for null, in case someone passed in a null node, or
they passed in an element that isn't rooted at root. */
if (depth == 0) {
return null;
} else {
}
} else {
depth++;
} else {
}
}
}
return retNodes;
}
}
}