001 /* 002 Copyright (C) 2002-2003 Laurent Martelli <laurent@aopsys.com> 003 004 This program is free software; you can redistribute it and/or modify 005 it under the terms of the GNU Lesser General Public License as 006 published by the Free Software Foundation; either version 2 of the 007 License, or (at your option) any later version. 008 009 This program is distributed in the hope that it will be useful, but 010 WITHOUT ANY WARRANTY; without even the implied warranty of 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 Lesser General Public License for more details. 013 014 You should have received a copy of the GNU Lesser General Public 015 License along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 017 USA */ 018 019 package org.objectweb.jac.aspects.gui.web; 020 021 import org.objectweb.jac.aspects.gui.*; 022 import org.objectweb.jac.core.Wrappee; 023 import org.objectweb.jac.core.rtti.CollectionItem; 024 import java.io.PrintWriter; 025 import java.util.HashSet; 026 027 /** 028 * This class defines a Swing component tree view for objects that are 029 * related to a root object through relations or collections. 030 * 031 * @see GuiAC */ 032 033 public class Tree extends AbstractView 034 implements View, HTMLViewer, TreeListener 035 { 036 TreeModel model; 037 boolean showRelations = true; 038 RootNode rootNode = null; 039 HashSet expandedNodes = new HashSet(); 040 041 /** 042 * Constructs a new tree view. 043 * @param pathDef designate root objects of the tree 044 * @param showRelations wether to build a node for relation items 045 */ 046 public Tree(ViewFactory factory, DisplayContext context, 047 String pathDef, boolean showRelations) { 048 super(factory,context); 049 this.showRelations = showRelations; 050 051 rootNode = new RootNode(); 052 model = new TreeModel( rootNode, pathDef, showRelations ); 053 } 054 // interface TreeView 055 056 public void close(boolean validate) { 057 model.unregisterEvents(); 058 } 059 060 public void genHTML(PrintWriter out) { 061 genNode(out,(AbstractNode)model.getRoot(),""); 062 } 063 064 protected boolean isExpanded(AbstractNode node) { 065 return expandedNodes.contains(node); 066 } 067 068 protected void genNode(PrintWriter out, AbstractNode node, String curPath) { 069 String nodePath = node instanceof RootNode ? "/" : curPath; 070 String nodeClass = node.isLeaf() ? "leafNode" : "treeNode"; 071 boolean isRoot = node == model.getRoot(); 072 073 if (!isRoot) { 074 out.println("<div class=\""+nodeClass+"\">"); 075 if (!node.isLeaf()) { 076 if (isExpanded(node)) 077 out.print(" <a href=\""+eventURL("onCollapseNode")+ 078 "&nodePath="+nodePath+"\" class=\"fixed\">[-]</a>"); 079 else 080 out.print(" <a href=\""+eventURL("onExpandNode")+ 081 "&nodePath="+nodePath+"\" class=\"fixed\">[+]</a>"); 082 } 083 out.println(iconElement(node.getIcon(),"")+ 084 " <a href=\""+eventURL("onSelectNode")+"&nodePath="+ 085 nodePath+"\">"+node.getText()+"</a>"); 086 } 087 088 if (isExpanded(node) || isRoot) { 089 out.println(" <div class=\""+(isRoot?"rootNodes":"nodes")+"\">"); 090 for (int i=0; i<node.getChildCount();i++) { 091 genNode(out,(AbstractNode)node.getChildAt(i),curPath+"/"+i); 092 } 093 out.println(" </div>"); 094 } 095 if (!isRoot) { 096 out.println("</div>"); 097 } 098 } 099 100 // TreeListener interface 101 102 public void onSelectNode(String nodePath) { 103 try { 104 AbstractNode node = pathToNode(nodePath); 105 logger.debug("onSelectNode path="+nodePath+" -> "+node); 106 if (node == null) 107 return; 108 logger.debug(" node="+node); 109 Object selected = node.getUserObject(); 110 logger.debug(" selected="+selected); 111 if (selected instanceof CollectionItem) { 112 context.getDisplay().refresh(); 113 } else { 114 EventHandler.get().onNodeSelection(context,node,true); 115 } 116 } catch (Exception e) { 117 context.getDisplay().showError("Error",e.toString()); 118 } 119 } 120 121 public void onExpandNode(String nodePath) { 122 try { 123 AbstractNode node = pathToNode(nodePath); 124 // ensure that the children of this node are uptodate 125 if (node instanceof ObjectNode) 126 ((ObjectNode)node).updateChildren(); 127 expandedNodes.add(node); 128 } finally { 129 context.getDisplay().refresh(); 130 } 131 } 132 133 public void onCollapseNode(String nodePath) { 134 try { 135 AbstractNode node = pathToNode(nodePath); 136 expandedNodes.remove(node); 137 } finally { 138 context.getDisplay().refresh(); 139 } 140 } 141 142 /* 143 * Get a Node from its path. 144 */ 145 protected AbstractNode pathToNode(String nodePath) { 146 AbstractNode node = (AbstractNode)model.getRoot(); 147 if (nodePath.startsWith("/")) { 148 nodePath = nodePath.substring(1); 149 int index = nodePath.indexOf("/"); 150 while (index!=-1) { 151 node = (AbstractNode)node.getChildAt( 152 Integer.parseInt(nodePath.substring(0,index))); 153 nodePath = nodePath.substring(index+1); 154 index = nodePath.indexOf("/"); 155 } 156 if (nodePath.length()>0) 157 node = (AbstractNode)node.getChildAt(Integer.parseInt(nodePath)); 158 } 159 return node; 160 } 161 }