org.fife.rsta.ac.java.tree.JavaOutlineTree Maven / Gradle / Ivy
/*
* 03/21/2010
*
* Copyright (C) 2010 Robert Futrell
* robert_futrell at users.sourceforge.net
* http://fifesoft.com/rsyntaxtextarea
*
* This code is licensed under the LGPL. See the "license.txt" file included
* with this project.
*/
package org.fife.rsta.ac.java.tree;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Iterator;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
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.TreeCellRenderer;
import javax.swing.tree.TreePath;
import org.fife.rsta.ac.LanguageSupport;
import org.fife.rsta.ac.LanguageSupportFactory;
import org.fife.rsta.ac.java.IconFactory;
import org.fife.rsta.ac.java.JavaLanguageSupport;
import org.fife.rsta.ac.java.JavaParser;
import org.fife.rsta.ac.java.rjc.ast.ASTNode;
import org.fife.rsta.ac.java.rjc.ast.CodeBlock;
import org.fife.rsta.ac.java.rjc.ast.CompilationUnit;
import org.fife.rsta.ac.java.rjc.ast.Field;
import org.fife.rsta.ac.java.rjc.ast.ImportDeclaration;
import org.fife.rsta.ac.java.rjc.ast.LocalVariable;
import org.fife.rsta.ac.java.rjc.ast.Member;
import org.fife.rsta.ac.java.rjc.ast.Method;
import org.fife.rsta.ac.java.rjc.ast.Package;
import org.fife.rsta.ac.java.rjc.ast.NormalClassDeclaration;
import org.fife.rsta.ac.java.rjc.ast.NormalInterfaceDeclaration;
import org.fife.rsta.ac.java.rjc.ast.TypeDeclaration;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
/**
* A tree view showing the outline of Java source, similar to the "Outline"
* view in the Eclipse JDT. It also uses Eclipse's icons, just like the rest
* of this code completion library.
*
* You can get this tree automatically updating in response to edits in an
* RSyntaxTextArea with {@link JavaLanguageSupport} installed by
* calling {@link #listenTo(RSyntaxTextArea)}. Note that, if you have an
* application with multiple RSTA editors, you would want to call this method
* each time a new editor is focused.
*
* @author Robert Futrell
* @version 1.0
*/
public class JavaOutlineTree extends /*org.fife.ui.ToolTipTree */JTree {
private DefaultTreeModel model;
private RSyntaxTextArea textArea;
private JavaParser parser;
private Listener listener;
/**
* Constructor.
*/
public JavaOutlineTree() {
setBorder(BorderFactory.createEmptyBorder(0,8,0,8));
setRootVisible(false);
setCellRenderer(new AstTreeCellRenderer());
model = new DefaultTreeModel(new DefaultMutableTreeNode("Nothing"));
setModel(model);
listener = new Listener();
addTreeSelectionListener(listener);
}
/**
* Refreshes this tree.
*
* @param cu The parsed compilation unit. If this is null
* then the tree is cleared.
*/
private void update(CompilationUnit cu) {
JavaTreeNode root = new JavaTreeNode("Remove me!",
IconFactory.SOURCE_FILE_ICON);
if (cu==null) {
model.setRoot(root);
return;
}
Package pkg = cu.getPackage();
if (pkg!=null) {
String iconName = IconFactory.PACKAGE_ICON;
root.add(new JavaTreeNode(pkg, iconName));
}
JavaTreeNode importNode = new JavaTreeNode("Imports",
IconFactory.IMPORT_ROOT_ICON);
for (Iterator i=cu.getImportIterator(); i.hasNext(); ) {
ImportDeclaration idec = (ImportDeclaration)i.next();
JavaTreeNode iNode = new JavaTreeNode(idec,IconFactory.IMPORT_ICON);
importNode.add(iNode);
}
root.add(importNode);
for (Iterator i=cu.getTypeDeclarationIterator(); i.hasNext(); ) {
TypeDeclaration td = (TypeDeclaration)i.next();
TypeDeclarationTreeNode dmtn = createTypeDeclarationNode(td);
root.add(dmtn);
}
model.setRoot(root);
expandInitialNodes();
}
/**
* Refreshes listeners on the text area when its syntax style changes.
*/
private void checkForJavaParsing() {
// Remove possible listener on old Java parser (in case they're just
// changing syntax style AWAY from Java)
if (parser!=null) {
parser.removePropertyChangeListener(
JavaParser.PROPERTY_COMPILATION_UNIT, listener);
parser = null;
}
// Get the Java language support (shared by all RSTA instances editing
// Java that were registered with the LanguageSupportFactory).
LanguageSupportFactory lsf = LanguageSupportFactory.get();
LanguageSupport support = lsf.getSupportFor(SyntaxConstants.
SYNTAX_STYLE_JAVA);
JavaLanguageSupport jls = (JavaLanguageSupport)support;
// Listen for re-parsing of the editor, and update the tree accordingly
parser = jls.getParser(textArea);
if (parser!=null) { // Should always be true
parser.addPropertyChangeListener(
JavaParser.PROPERTY_COMPILATION_UNIT, listener);
// Populate with any already-existing CompilationUnit
CompilationUnit cu = parser.getCompilationUnit();
update(cu);
}
else {
update((CompilationUnit)null); // Clear the tree
}
}
private MemberTreeNode createMemberNode(Member member) {
MemberTreeNode node = null;
if (member instanceof CodeBlock) {
node = new MemberTreeNode((CodeBlock)member);
}
else if (member instanceof Field) {
node = new MemberTreeNode((Field)member);
}
else {
node = new MemberTreeNode((Method)member);
}
CodeBlock body = null;
if (member instanceof CodeBlock) {
body = (CodeBlock)member;
}
else if (member instanceof Method) {
body = ((Method)member).getBody();
}
if (body!=null) {
for (int i=0; i