/* (C) 2000-2002, DIUF, http://www.unifr.ch/diuf * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program 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 General * Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package iiuf.xmillum.tool; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import java.util.HashSet; import java.util.Set; import javax.swing.Icon; import javax.swing.JLabel; import javax.swing.JTree; import javax.swing.JScrollPane; import javax.swing.ListModel; import javax.swing.ListSelectionModel; import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.TreeModelListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.tree.DefaultTreeSelectionModel; import javax.swing.tree.TreeCellRenderer; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import javax.swing.ImageIcon; import iiuf.dom.DOMUtils; import iiuf.util.EventListenerList; import iiuf.util.Strings; import iiuf.xmillum.BrowserContext; import iiuf.xmillum.FlagAccess; import iiuf.xmillum.FlagListener; import iiuf.xmillum.FlagManager; import iiuf.xmillum.Tool; import iiuf.xmillum.Window; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; /** * XMLTree * * xmillum xml tree. * * <p>Usage: * * <xmi:tool class="iiuf.xmillum.tool.XMLTree" * showattributes="..." * start="..." * filter="..."/><p> * * <ul> * <li>start: (required) specifies what sub-tree is to be visualized * <li>showattributes: (optional) set it to 1 to show attributes in the tree * <li>filter: (optional) specifies the attributes that are not shown in the tree * </ul> * * @author $Author: ohitz $ * @version $Revision: 1.1 $ */ public class XMLTree implements Tool { protected BrowserContext context; Element element; Element startElement; Window window; boolean showAttributes = false; Set filtered = new HashSet(); FlagAccess flag; DOMTreeSelectionModel selectionModel; Icon elementIcon = new ImageIcon(XMLTree.class.getResource("element.gif")); Icon attributeIcon = new ImageIcon(XMLTree.class.getResource("attribute.gif")); Icon textIcon = new ImageIcon(XMLTree.class.getResource("text.gif")); public void activateTool(BrowserContext c, Element e) { context = c; element = e; String attr = element.getAttribute("showattributes"); if (attr != null) { if (attr.equals("1")) { showAttributes = true; } } filtered.add("tmp:refvalue"); String filter = element.getAttribute("filter"); if (filter != null) { String[] f = Strings.split(filter, ','); for (int i = 0; i < f.length; i++) { filtered.add(f[i]); } } String start = element.getAttribute("start"); if (start != null) { startElement = context.getSourceElementByReference(start); } JTree tree = new JTree(new DOMTreeModel(startElement)); tree.setCellRenderer(new DOMTreeCellRenderer()); selectionModel = new DOMTreeSelectionModel(); tree.setSelectionModel(selectionModel); flag = context.flagger.addFlagListener(FlagManager.SELECTION, listener); window = context.getWindowCreator().createWindow("XML Tree"); window.getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER); window.open(); } public void deactivateTool() { window.close(); } class DOMTreeCellRenderer implements TreeCellRenderer { Color textForeground; Color textBackground; Color selectionForeground; Color selectionBackground; Color selectionBorderColor; public DOMTreeCellRenderer() { textForeground = UIManager.getColor("Tree.textForeground"); textBackground = UIManager.getColor("Tree.textBackground"); selectionForeground = UIManager.getColor("Tree.selectionForeground"); selectionBackground = UIManager.getColor("Tree.selectionBackground"); selectionBorderColor = UIManager.getColor("Tree.selectionBorderColor"); } class Cell extends JLabel { boolean selected; boolean hasFocus; public Cell(String label, Icon icon, boolean sel, boolean focus) { super(label, icon, SwingConstants.LEFT); selected = sel; hasFocus = focus; } public void paint(Graphics g) { Color background; if (selected) { background = selectionBackground; } else { background = textBackground; if (background == null) { background = getBackground(); } } int imageOffset = getLabelStart(); if (background != null) { g.setColor(background); if (getComponentOrientation().isLeftToRight()) { g.fillRect(imageOffset, 0, getWidth() - 1 - imageOffset, getHeight()); } else { g.fillRect(0, 0, getWidth() - 1 - imageOffset, getHeight()); } } if (hasFocus) { Color border = selectionBorderColor; if (border != null) { g.setColor(border); if(getComponentOrientation().isLeftToRight()) { g.drawRect(imageOffset, 0, getWidth() - 1 - imageOffset, getHeight() - 1); } else { g.drawRect(0, 0, getWidth() - 1 - imageOffset, getHeight() - 1); } } } if (selected) { setForeground(selectionForeground); } else { setForeground(textForeground); } super.paint(g); } int getLabelStart() { Icon image = getIcon(); if (image != null && getText() != null) { return image.getIconWidth() + Math.max(0, getIconTextGap() - 1); } return 0; } } final int MAX_TEXT_LENGTH = 48; public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { Icon icon; String label; if (value instanceof Element) { Element e = (Element) value; label = "<"+e.getTagName()+">"; icon = elementIcon; } else if (value instanceof Attr) { Attr a = (Attr) value; label = a.getName()+"="+a.getValue(); icon = attributeIcon; } else if (value instanceof Text) { Text t = (Text) value; label = t.getData(); icon = textIcon; } else { label = "?"; icon = null; } if (label.length() > MAX_TEXT_LENGTH) { label = label.substring(0, MAX_TEXT_LENGTH-1-3)+"..."; } return new Cell(label, icon, selected, hasFocus); } } TreePath getPath(Element e) { if (e == null) { return null; } else if (e == startElement) { return new TreePath(e); } else { return getPath((Element) e.getParentNode()).pathByAddingChild(e); } } FlagListener listener = new FlagListener() { public void setFlag(Element e, String value) { String id = e.getAttribute("ref"); if (id != null) { Element o = context.getSourceElementByReference(id); if (value != null) { selectionModel.addToSelection(getPath(o)); } else { selectionModel.removeFromSelection(getPath(o)); } } } }; class DOMTreeSelectionModel extends DefaultTreeSelectionModel { NodeList getReferenced(TreePath p) { if (p == null) return null; Object o = p.getLastPathComponent(); if (o instanceof Element) { String r = ((Element) o).getAttribute("tmp:refvalue"); if (r != null) { return context.getInternalElementsWhichReference(r); } } return null; } public void addToSelection(TreePath path) { super.addSelectionPath(path); } public void removeFromSelection(TreePath path) { super.removeSelectionPath(path); } public void addSelectionPath(TreePath path) { NodeList nl = getReferenced(path); if (nl != null) { for (int i = 0; i < nl.getLength(); i++) { XMLTree.this.flag.setFlag((Element) nl.item(i), FlagManager.SELECTED); } } super.addSelectionPath(path); } public void addSelectionPaths(TreePath[] paths) { for (int j = 0; j < paths.length; j++) { NodeList nl = getReferenced(paths[j]); if (nl != null) { for (int i = 0; i < nl.getLength(); i++) { XMLTree.this.flag.setFlag((Element) nl.item(i), FlagManager.SELECTED); } } } super.addSelectionPaths(paths); } public void removeSelectionPath(TreePath path) { NodeList nl = getReferenced(path); if (nl != null) { for (int i = 0; i < nl.getLength(); i++) { XMLTree.this.flag.setFlag((Element) nl.item(i), null); } } super.removeSelectionPath(path); } public void removeSelectionPaths(TreePath[] paths) { for (int j = 0; j < paths.length; j++) { NodeList nl = getReferenced(paths[j]); if (nl != null) { for (int i = 0; i < nl.getLength(); i++) { XMLTree.this.flag.setFlag((Element) nl.item(i), null); } } } super.removeSelectionPaths(paths); } public void setSelectionPath(TreePath path) { XMLTree.this.flag.clearFlags(); NodeList nl = getReferenced(path); if (nl != null) { for (int i = 0; i < nl.getLength(); i++) { XMLTree.this.flag.setFlag((Element) nl.item(i), FlagManager.SELECTED); } } super.setSelectionPath(path); } public void setSelectionPaths(TreePath[] paths) { XMLTree.this.flag.clearFlags(); for (int j = 0; j < paths.length; j++) { NodeList nl = getReferenced(paths[j]); if (nl != null) { for (int i = 0; i < nl.getLength(); i++) { XMLTree.this.flag.setFlag((Element) nl.item(i), FlagManager.SELECTED); } } } super.setSelectionPaths(paths); } } class DOMTreeModel implements TreeModel { Element root; EventListenerList listeners = new EventListenerList(); public DOMTreeModel(Element e) { root = e; } public void addTreeModelListener(TreeModelListener l) { listeners.add(TreeModelListener.class, l, true); } public void removeTreeModelListener(TreeModelListener l) { listeners.remove(TreeModelListener.class, l); } public Object getChild(Object parent, int index) { Element e = (Element) parent; if (showAttributes) { NamedNodeMap nm = e.getAttributes(); for (int i = 0; i < nm.getLength(); i++) { Attr a = (Attr) nm.item(i); if (!filtered.contains(a.getName())) { if (index == 0) { return a; } index--; } } } NodeList nl = DOMUtils.getChilds((Element) parent, DOMUtils.TYPE_ELEMENT | DOMUtils.TYPE_TEXT); return nl.item(index); } public int getChildCount(Object parent) { Element e = (Element) parent; int n = 0; if (showAttributes) { NamedNodeMap nm = e.getAttributes(); for (int i = 0; i < nm.getLength(); i++) { Attr a = (Attr) nm.item(i); if (!filtered.contains(a.getName())) n++; } } NodeList nl = DOMUtils.getChilds((Element) parent, DOMUtils.TYPE_ELEMENT | DOMUtils.TYPE_TEXT); return n+nl.getLength(); } public int getIndexOfChild(Object parent, Object child) { int index = 0; if (showAttributes) { NamedNodeMap nm = ((Element) parent).getAttributes(); for (int i = 0; i < nm.getLength(); i++) { Attr a = (Attr) nm.item(i); if (!filtered.contains(a.getName())) { if (child == a) { return index; } index++; } } } NodeList nl = DOMUtils.getChilds((Element) parent, DOMUtils.TYPE_ELEMENT | DOMUtils.TYPE_TEXT); for (int i = 0; i < nl.getLength(); i++, index++) { if (child == nl.item(i)) { return index; } } return -1; } public Object getRoot() { return root; } public boolean isLeaf(Object node) { return (node instanceof Attr) || (node instanceof Text); } public void valueForPathChanged(TreePath path, Object newValue) { } } }