StructureView
is an IDE panel called the structure pane that acts as a container for a JComponent
that is optionally provided by the currently active
NodeViewer
. Usually a tree hierarchy displays the file structure and reports syntax errors.
You can't replace the StructureView
with the OpenTools API.
Browser
usually extends the FileNode
class, or it extends TextFileNode
if the file contains text.
If you extend FileNode
, then the createStructureComponent()
method of its
NodeViewer
supplies the Swing-based component for the StructureView
. For example,
public JComponent createStructureComponent() { return null; }
If you extend TextFileNode
, the implementation for a new file type instead customizes the existing JBuilder editor NodeViewer
. You do this indirectly by overriding the getTextStructureClass()
method of TextFileNode
. For example,
public Class getTextStructureClass() { return MyTextStructure.class; }
getTextStructureClass()
returns your class that extends com.borland.primetime.node.TextStructure
and overrides its setTree()
method. The JTree
parameter of setTree()
is the JComponent
that is given to the StructureView
.
For more information about defining your own file types, see "Implementing FileNode and TextFile Node."
JTree
to provide the structure view, however, you might find this section interesting.
For a TextFileNode
, the component provided for the structure view
is a JTree
that is sorted and with the most commonly needed nodes
automatically expanded. The key methods are setTree()
and
updateStructure()
.
The updateStructure()
method is called automatically whenever the source file is modified. Usually the nodes it adds to the tree contain references to positions in the file that are used by the nodeSelected()
method, which scrolls to and points at a line in the source file, and the nodeActivated()
method, which moves the focus to the source file line.
The following is a skeleton of a simple implementation. The mergeChildren()
method is a helper which tries not to collapse any expanded tree nodes as the tree is being updated.
public class MyTextStructure extends TextStructure { public MyTextStructure() { treeModel.setRoot(new MyStructureNode(null)); } class MyStructureNode extends MergeTreeNode { public MyStructureNode(Object userObject) { super(userObject); } public void sortChildren() { MergeTreeNode[] array = getChildrenArray(); if (array == null) return; Arrays.sort(array, new Comparator() { public int compare(Object o1, Object o2) { // Do comparison here between two tree nodes return 0; } }); children = new Vector(Arrays.asList(array)); sortDescendants(); } public void sortDescendants() { if (children != null) { Enumeration e = children.elements(); while (e.hasMoreElements()) { ((MyStructureNode)e.nextElement()).sortChildren(); } } } } private void showProperties() { // Show properties here // Re-sort everything but the top level of the structure tree MyStructureNode root = (MyStructureNode)treeModel.getRoot(); root.sortChildren(); treeModel.nodeStructureChanged(root); } public void setTree(JTree tree) { super.setTree(tree); TreeNode root = (TreeNode)treeModel.getRoot(); int count = root.getChildCount(); for (int index = 0; index < count; index++) { TreeNode node = root.getChildAt(index); tree.expandPath(new TreePath(new Object[] {root, node})); } } public JPopupMenu getPopup() { JPopupMenu menu = new JPopupMenu(); JMenuItem props = new JMenuItem("Properties..."); props.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { showProperties(); } }); menu.add(props); return menu; } public void nodeSelected(DefaultMutableTreeNode node) { // handle selection of a tree node here } public void nodeActivated(DefaultMutableTreeNode node) { // handle activation of a tree node here } public Icon getStructureIcon(Object value) { // return Icon appropriate for Object instance return null; } public void updateStructure(Document doc) { final MyStructureNode newRoot = new MyStructureNode(null); try { // Build a new structure tree using newRoot here // Prepare an object that updates the model Runnable update = new Runnable() { public void run() { MyStructureNode root = (MyStructureNode)treeModel.getRoot(); // Merge the new model into the old so that expansion paths can be // preserved root.mergeChildren(newRoot); // Sort everything including the top level of the structure tree root.sortChildren(); // Update the display treeModel.nodeStructureChanged(root); } }; // Update the model on the main swing thread... if (SwingUtilities.isEventDispatchThread()) update.run(); else SwingUtilities.invokeLater(update); } catch (java.io.IOException ex) { } } }