/* * ALMA - Atacama Large Millimiter Array * (c) European Southern Observatory, 2002 * Copyright by ESO (in the framework of the ALMA collaboration) * and Cosylab 2002, All rights reserved * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ package com.cosylab.logging.client; import org.w3c.dom.Node; // For creating a TreeModel import javax.swing.tree.*; import javax.swing.event.*; import java.util.*; import javax.swing.*; import java.awt.Component; /** This class wraps a DOM node and returns the text we want to * display in the tree. It also returns children, index values, * and child counts. * * Creation date: (1/30/02 9:57:02 AM) * @author: */ public class DomTree extends javax.swing.JTree { // static Document document; static final int windowHeight = 460; static final int leftWidth = 300; static final int rightWidth = 340; static final int windowWidth = leftWidth + rightWidth; // An array of names for DOM node-types // (Array indexes = nodeType() values.) static final String[] typeName = { "none", "Element", "Attr", "Text", "CDATA", "EntityRef", "Entity", "ProcInstr", "Comment", "Document", "DocType", "DocFragment", "Notation", }; private class AdapterNode { org.w3c.dom.Node domNode; // Construct an Adapter node from a DOM node public AdapterNode(org.w3c.dom.Node node) { domNode = node; } // Return a string that identifies this node in the tree // *** Refer to table at top of org.w3c.dom.Node *** public String toString() { if (domNode == null) return "No additional info"; String s = typeName[domNode.getNodeType()]; String nodeName = domNode.getNodeName(); if (!nodeName.startsWith("#")) { s += ": " + nodeName; } if (domNode.getNodeValue() != null) { if (s.startsWith("ProcInstr")) s += ", "; else s += ": "; // Trim the value to get rid of NL's at the front String t = domNode.getNodeValue().trim(); int x = t.indexOf("\n"); if (x >= 0) t = t.substring(0, x); s += t; } return s; } /* * Return children, index, and count values */ public int index(AdapterNode child) { //System.err.println("Looking for index of " + child); if (domNode == null) return 0; int count = childCount(); for (int i = 0; i < count; i++) { AdapterNode n = this.child(i); if (child.domNode == n.domNode) return i; } return -1; // Should never get here. } public AdapterNode child(int searchIndex) { //Note: JTree index is zero-based. if (domNode == null) return null; org.w3c.dom.Node node = domNode.getChildNodes().item(searchIndex); return new AdapterNode(node); } public int childCount() { if (domNode == null) return 0; return domNode.getChildNodes().getLength(); } } // This adapter converts the current Document (a DOM) into // a JTree model. private class DomToTreeModelAdapter implements javax.swing.tree.TreeModel { private Node document = null; // Basic TreeModel operations public Object getRoot() { return new AdapterNode(document); } public boolean isLeaf(Object aNode) { // Determines whether the icon shows up to the left. // Return true for any node with no children AdapterNode node = (AdapterNode) aNode; if (node == null) return true; if (node.childCount() > 0) return false; return true; } public int getChildCount(Object parent) { AdapterNode node = (AdapterNode) parent; return node.childCount(); } public Object getChild(Object parent, int index) { AdapterNode node = (AdapterNode) parent; return node.child(index); } public int getIndexOfChild(Object parent, Object child) { AdapterNode node = (AdapterNode) parent; return node.index((AdapterNode) child); } public void valueForPathChanged(TreePath path, Object newValue) { // Null. We won't be making changes in the GUI // If we did, we would ensure the new value was really new, // adjust the model, and then fire a TreeNodesChanged event. } /* * Use these methods to add and remove event listeners. * (Needed to satisfy TreeModel interface, but not used.) */ private List listenerList = new ArrayList(); public void addTreeModelListener(TreeModelListener listener) { if (listener != null && !listenerList.contains(listener)) { listenerList.add(listener); } } public void removeTreeModelListener(TreeModelListener listener) { if (listener != null) { listenerList.remove(listener); } } public void setDocument(Node newDocument) { document = newDocument; // fireTreeStructureChanged(new TreeModelEvent(this, (Object[])null)); } public Node getDocument() { return document; } /* * Invoke these methods to inform listeners of changes. * (Not needed for this example.) * Methods taken from TreeModelSupport class described at * http://java.sun.com/products/jfc/tsc/articles/jtree/index.html * That architecture (produced by Tom Santos and Steve Wilson) * is more elegant. I just hacked 'em in here so they are * immediately at hand. */ public void fireTreeNodesChanged(TreeModelEvent e) { Iterator it = listenerList.iterator(); while (it.hasNext()) { TreeModelListener listener = (TreeModelListener) it.next(); listener.treeNodesChanged(e); } } public void fireTreeNodesInserted(TreeModelEvent e) { Iterator it = listenerList.iterator(); while (it.hasNext()) { TreeModelListener listener = (TreeModelListener) it.next(); listener.treeNodesInserted(e); } } public void fireTreeNodesRemoved(TreeModelEvent e) { Iterator it = listenerList.iterator(); while (it.hasNext()) { TreeModelListener listener = (TreeModelListener) it.next(); listener.treeNodesRemoved(e); } } public void fireTreeStructureChanged(TreeModelEvent e) { Iterator it = listenerList.iterator(); while (it.hasNext()) { TreeModelListener listener = (TreeModelListener) it.next(); listener.treeStructureChanged(e); } } } public static class TheCellRenderer extends DefaultTreeCellRenderer { public TheCellRenderer() { super(); } public Component getTreeCellRendererComponent( JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { Component c = super.getTreeCellRendererComponent( tree, value, selected, expanded, leaf, row, hasFocus); return this; } } private TheCellRenderer cellRenderer = new TheCellRenderer(); /** * DomTree constructor comment. */ public DomTree() { super(); setModel(new DomToTreeModelAdapter()); setCellRenderer(cellRenderer); ToolTipManager.sharedInstance().registerComponent(this); } /** * DomTree constructor comment. * @param value java.util.Hashtable */ public DomTree(java.util.Hashtable value) { super(value); setCellRenderer(cellRenderer); ToolTipManager.sharedInstance().registerComponent(this); } /** * Returns the instance of the document displayed by this tree or null if empty. * Creation date: (1/30/02 10:53:29 AM) * @return org.w3c.dom.Document */ public Node getRootNode() { return ((DomToTreeModelAdapter)getModel()).getDocument(); } /** * Insert the method's description here. * Creation date: (1/30/02 10:59:08 AM) * @param args java.lang.String[] */ public static void main(String[] args) { try { JFrame frame = new JFrame(); DomTree dt = new DomTree(); frame.getContentPane().setLayout(new java.awt.FlowLayout()); frame.getContentPane().add(dt); } catch (Exception e) { e.printStackTrace(); } } /** * Sets the new document to be displayed by this tree. Can be null to display empty tree. * Creation date: (1/30/02 10:46:35 AM) * @param newDocument org.w3c.dom.Document */ public void setRootNode(Node newDocument) { ((DomToTreeModelAdapter)getModel()).setDocument(newDocument); setCellRenderer(cellRenderer); ToolTipManager.sharedInstance().registerComponent(this); } }