package com.gwtext.client.widgets.tree;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.http.client.*;
import com.google.gwt.xml.client.*;
/**
* Provides the abilty to a TreePanel using remote XML data.This TreeLoader can be configured to load tree data from XML
* returned from a remote URL.
*<p>
* Sample code for loading a TreePanel using AsyncTreeNode and XmltreeLoader :
*
* <pre>
* <code>
*
* final TreePanel treePanel = new TreePanel() {
* {
* setAnimate(true);
* setEnableDD(true);
* setContainerScroll(true);
* setRootVisible(true);
* }
* };
*
* final XMLTreeLoader loader = new XMLTreeLoader() {
* {
* setDataUrl("countries-cb.xml");
* setMethod("get");
* setRootTag("countries");
* setFolderIdMapping("@id");
* setLeafIdMapping("@id");
* setFolderTitleMapping("@title");
* setFolderTag("team");
* setLeafTitleMapping("@title");
* setLeafTag("country");
* setQtipMapping("@qtip");
* setDisabledMapping("@disabled");
* setCheckedMapping("@checked");
* setIconMapping("@icon");
* setAttributeMappings(new String[]{"@rank"});
* }
* };
* AsyncTreeNode root = new AsyncTreeNode("Countries", loader);
*
* treePanel.setRootNode(root);
* treePanel.render();
*
* root.expand();
* treePanel.expandAll();
* </code>
* </pre>
*
* The above code loads a Tree using the following XML data - countries-cb.xml
*
* <pre>
* <code>
*<countries>
* <team id="team-a" title="Team A" icon="images/silk/flag_yellow.gif" checked="true">
* <country title="Brazil" qtip="Rank 2" rank="2" checked="false"/>
* <country title="Canada" qtip="Rank 3" rank="3" checked="false"/>
* <country title="China" qtip="Rank 4" rank="4" checked="false"/>
* </team>
* <team title="Team B" icon="images/silk/flag_blue.gif">
* <country title="Germany" qtip="Captain" checked="true" rank="1"/>
* <country title="France" qtip="Rank 2" rank="2" checked="false"/>
* <country title="Canada" qtip="Rank 3" rank="3" checked="false"/>
* <country title="India" qtip="Rank 4" rank="4" checked="false"/>
* <country title="Seychelles" qtip="Rank 5" rank="5" checked="false"/>
* </team>
*
* <team title="Team C" icon="images/silk/flag_green.gif">
* <country title="United States" qtip="Captain - Rank 1" checked="true" rank="1"/>
* <country title="Japan" qtip="Rank 2" rank="2" checked="false"/>
* <country title="Italy" qtip="Rank 3" rank="3" checked="false"/>
* <country title="Finland" qtip="Rank 4" rank="4" checked="false"/>
* </team>
* </countries>
* </code>
* </pre>
*
* @see com.gwtext.client.widgets.tree.TreePanel
* @see com.gwtext.client.widgets.tree.TreeLoader
* @see com.gwtext.client.widgets.tree.AsyncTreeNode
*/
public class XMLTreeLoader extends TreeLoader {
static {
init();
}
/**
* Construct a new XMLTreeLoader.
*/
public XMLTreeLoader() {
}
/**
* Construct a new XMLTreeLoader.
*
* @param url the data url
* @param rootTag the root tag
* @param folderTag the folder tag
*
*/
public XMLTreeLoader(String url, String rootTag, String folderTag) {
setDataUrl(url);
setRootTag(rootTag);
setFolderTag(folderTag);
}
protected native JavaScriptObject create(JavaScriptObject configJS)/*-{
return new $wnd.Ext.tree.XMLTreeLoader(configJS, this);
}-*/;
private static native void init() /*-{
$wnd.Ext.tree.XMLTreeLoader = function(configJS, selfJ) {
$wnd.Ext.tree.XMLTreeLoader.superclass.constructor.call(this, configJS);
this.selfJ = selfJ;
};
$wnd.Ext.extend($wnd.Ext.tree.XMLTreeLoader, $wnd.Ext.tree.TreeLoader, {
load : function(node, callback){
if(this.clearOnLoad){
while(node.firstChild){
node.removeChild(node.firstChild);
}
}
this.requestData(node, callback);
},
requestData : function(node, callback){
if(this.fireEvent("beforeload", this, node, callback) !== false){
var nodeJ = @com.gwtext.client.widgets.tree.TreeNode::instance(Lcom/google/gwt/core/client/JavaScriptObject;)(node);
var params = this.getParams(node);
@com.gwtext.client.widgets.tree.XMLTreeLoader::requestData(Lcom/google/gwt/core/client/JavaScriptObject;Lcom/gwtext/client/widgets/tree/TreeNode;Lcom/gwtext/client/widgets/tree/XMLTreeLoader;Ljava/lang/String;Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;)(this, nodeJ, this.selfJ, this.requestMethod, this.dataUrl||this.url, this.handleResponse, this.handleFailure, callback, params);
}else{
// if the load is cancelled, make sure we notify
// the node that we are done
if(typeof callback == "function"){
callback();
}
}
},
handleResponse : function(response){
this.transId = false;
//var a = response.argument;
var callback = response.callback;
var node = response.node;
var responseData = response.responseData;
if(typeof callback == "function"){
callback(this, node);
}
this.fireEvent("load", this, node, responseData);
},
handleFailure : function(response){
this.transId = false;
var callback = response.callback;
var node = response.node;
var responseData = response.responseData;
this.fireEvent("loadexception", this, node, responseData);
if(typeof callback == "function"){
callback(this, node);
}
}
});
}-*/;
private static void requestData(final JavaScriptObject treeLoaderJS, final TreeNode root, final XMLTreeLoader treeLoader, String method, String url, final JavaScriptObject success, final JavaScriptObject failure, final JavaScriptObject callback, String params) {
//build side nav tree from xml data
RequestBuilder.Method httpMethod = "post".equalsIgnoreCase(method) ? RequestBuilder.POST : RequestBuilder.GET;
RequestBuilder builder = new RequestBuilder(httpMethod, url);
builder.setHeader("Content-type","application/x-www-form-urlencoded");
try {
builder.sendRequest(params, new RequestCallback() {
public void onResponseReceived(Request request, Response response) {
if (response.getStatusCode() == 200) {
Document xml = null;
try {
xml = XMLParser.parse(response.getText());
} catch (Exception e) {
call(failure, treeLoaderJS, root.getJsObj(), callback, e.getMessage());
return;
}
String rootTag = treeLoader.getRootTag();
Node rootNode = null;
if (rootTag == null) {
rootNode = xml.getDocumentElement().getParentNode().getChildNodes().item(0);
} else {
rootNode = xml.getElementsByTagName(rootTag).item(0);
}
load(treeLoader, root, rootNode.getChildNodes());
call(success, treeLoaderJS, root.getJsObj(), callback, response.getText());
} else {
call(failure, treeLoaderJS, root.getJsObj(), callback, response.getStatusCode() + ":" + response.getText());
}
}
public void onError(Request request, Throwable throwable) {
call(failure, treeLoaderJS, root.getJsObj(), callback, throwable.getMessage());
}
});
} catch (RequestException e) {
call(failure, treeLoaderJS, root.getJsObj(), callback, e.getMessage());
}
}
private static native void call(JavaScriptObject func, JavaScriptObject treeLoader, JavaScriptObject node, JavaScriptObject callback, String responseData)/*-{
var arguments = {callback: callback, node: node, responseData : responseData};
func.call(treeLoader, arguments);
}-*/;
private static void load(XMLTreeLoader treeLoader, TreeNode currentNode, NodeList chidren) {
for (int i = 0; i < chidren.getLength(); i++) {
Node child = chidren.item(i);
if (!(child instanceof Element)) continue;
String name = child.getNodeName();
String folderTag = treeLoader.getFolderTag();
String leafTag = treeLoader.getLeafTag();
if (name.equals(folderTag)) {
final String id = evaluateNodeValue(child, treeLoader.getFolderIdMapping());
final String title = evaluateNodeValue(child, treeLoader.getFolderTitleMapping());
TreeNode treeNode = createNode(child, treeLoader, id, title);
currentNode.appendChild(treeNode);
load(treeLoader, treeNode, child.getChildNodes());
} else if (name.equals(leafTag)) {
final String id = evaluateNodeValue(child, treeLoader.getLeafIdMapping());
final String title = evaluateNodeValue(child, treeLoader.getLeafTitleMapping());
TreeNode treeNode = createNode(child, treeLoader, id, title);
currentNode.appendChild(treeNode);
}
}
}
private static TreeNode createNode(Node child, XMLTreeLoader treeLoader, final String id, String title) {
final String icon = evaluateNodeValue(child, treeLoader.getIconMapping());
final String iconCls = evaluateNodeValue(child, treeLoader.getIconClsMapping());
final String qtip = evaluateNodeValue(child, treeLoader.getQtipMapping());
final String checked = evaluateNodeValue(child, treeLoader.getCheckedMapping());
final String disabled = evaluateNodeValue(child, treeLoader.getDisabledMapping());
final String allowDrag = evaluateNodeValue(child, treeLoader.getAllowDragMapping());
final String allowDrop = evaluateNodeValue(child, treeLoader.getAllowDropMapping());
final String expanded = evaluateNodeValue(child, treeLoader.getExpandedMapping());
final String href = evaluateNodeValue(child, treeLoader.getHrefMapping());
final String hrefTarget = evaluateNodeValue(child, treeLoader.getHrefTargetMapping());
TreeNode treeNode = new TreeNode(title) {
{
setId(id);
setIcon(icon);
setIconCls(iconCls);
setTooltip(qtip);
setDisabled(booleanValue(disabled));
setAllowDrag(allowDrag == null || booleanValue(allowDrag));
setAllowDrop(allowDrop == null || booleanValue(allowDrop));
setExpanded(expanded == null || booleanValue(expanded));
setHref(href);
setHrefTarget(hrefTarget);
}
};
if (checked != null) {
treeNode.setChecked(booleanValue(checked));
}
String[] attributeMappings = treeLoader.getAttributeMappings();
if (attributeMappings != null) {
for (int j = 0; j < attributeMappings.length; j++) {
String attributeMapping = attributeMappings[j];
String attributeName = attributeMapping.replaceAll("@", "");
String attributeValue = evaluateNodeValue(child, attributeMapping);
treeNode.setAttribute(attributeName, attributeValue);
}
}
return treeNode;
}
private static boolean booleanValue(String value) {
if (value == null) return false;
return value.equalsIgnoreCase("true") || value.equals("1");
}
private static String evaluateNodeValue(Node node, String mapping) {
if (mapping == null) return null;
String value = null;
if (mapping.startsWith("@")) {
String attribute = mapping.substring(1, mapping.length());
Node item = node.getAttributes().getNamedItem(attribute);
value = item == null ? null : item.getNodeValue();
} else {
NodeList nodeList = node.getChildNodes();
for (int j = 0; j < nodeList.getLength(); j++) {
Node child = nodeList.item(j);
if (!(child instanceof Element)) continue;
String nodeName = child.getNodeName();
if (nodeName.equals(mapping)) {
value = child.getChildNodes().item(0).getNodeValue();
}
}
}
return value;
}
private String rootTag;
private String folderTag = "node";
private String leafTag = "leaf";
private String folderTitleMapping = "@title";
private String leafTitleMapping = "@title";
private String folderIdMapping;
private String leafIdMapping;
private String iconMapping = "@icon";
private String iconClsMapping = "@iconCls";
private String qtipMapping = "@qtip";
private String checkedMapping = "@checked";
private String disabledMapping = "@disabled";
private String expandedMapping = "@expanded";
private String hrefMapping = "@href";
private String hrefTargetMapping = "@hrefTarget";
private String allowDragMapping = "@allowDrag";
private String allowDropMapping = "@allowDrop";
private String[] attributeMappings;
/**
* The root tag name in the XML data.
*
* @param rootTag the root tag name
*/
public void setRootTag(String rootTag) {
this.rootTag = rootTag;
}
/**
* The folder tag name in the XML data.
*
* @param folderTag the folder tag name
*/
public void setFolderTag(String folderTag) {
this.folderTag = folderTag;
}
/**
* The leaf tag name in the XML data.
*
* @param leafTag the leaf tag name
*/
public void setLeafTag(String leafTag) {
this.leafTag = leafTag;
}
/**
* Mapping corresponding to the title of the folder relative to the folder tag.
*
* @param folderTitleMapping the folder title mapping
*/
public void setFolderTitleMapping(String folderTitleMapping) {
this.folderTitleMapping = folderTitleMapping;
}
/**
* Mapping corresponding to the title of the leaf relative to the leaf tag.
*
* @param leafTitleMapping the leaf title mapping
*/
public void setLeafTitleMapping(String leafTitleMapping) {
this.leafTitleMapping = leafTitleMapping;
}
/**
* Return the root tag name.
*
* @return the root tag
*/
public String getRootTag() {
return rootTag;
}
/**
* Return the folder tag name.
*
* @return the folder tag
*/
public String getFolderTag() {
return folderTag;
}
/**
* Return the leaf tag name.
*
* @return the leaf tag
*/
public String getLeafTag() {
return leafTag;
}
/**
* Return the folder title mapping.
*
* @return folder title mapping
*/
public String getFolderTitleMapping() {
return folderTitleMapping;
}
/**
* Return the leaf title mapping.
*
* @return the leaftitle mapping
*/
public String getLeafTitleMapping() {
return leafTitleMapping;
}
/**
* Return the folder ID value mapping.
*
* @return the folder ID value mapping
*/
public String getFolderIdMapping() {
return folderIdMapping;
}
/**
* Return the leaf ID value mapping.
*
* @return the leaf ID value mapping
*/
public String getLeafIdMapping() {
return leafIdMapping;
}
/**
* Set the folder ID mapping relative to the folder tag.
*
* @param folderIdMapping the folder ID mapping
*/
public void setFolderIdMapping(String folderIdMapping) {
this.folderIdMapping = folderIdMapping;
}
/**
* Set the leaf ID mapping relative to the leaf tag.
*
* @param leafIdMapping the leaf ID mapping
*/
public void setLeafIdMapping(String leafIdMapping) {
this.leafIdMapping = leafIdMapping;
}
/**
* Return the icon mapping.
*
* @return the icon mapping
*/
public String getIconMapping() {
return iconMapping;
}
/**
* Set the icon mapping.
*
* @param iconMapping the icon mapping
*/
public void setIconMapping(String iconMapping) {
this.iconMapping = iconMapping;
}
/**
* Return the icon class mapping.
*
* @return the icon class mapping
*/
public String getIconClsMapping() {
return iconClsMapping;
}
/**
* Set the icon class mapping.
*
* @param iconClsMapping the icon class mapping
*/
public void setIconClsMapping(String iconClsMapping) {
this.iconClsMapping = iconClsMapping;
}
/**
* Return the quick tip value mapping.
*
* @return the quick tip mapping
*/
public String getQtipMapping() {
return qtipMapping;
}
/**
* Set the quick tip value mapping.
*
* @param qtipMapping the quick tip mapping
*/
public void setQtipMapping(String qtipMapping) {
this.qtipMapping = qtipMapping;
}
/**
* Return the checkbox state value mapping.
*
* @return the checked mapping
*/
public String getCheckedMapping() {
return checkedMapping;
}
/**
* Set the checkbox state value mapping.
*
* @param checkedMapping the checked mapping
*/
public void setCheckedMapping(String checkedMapping) {
this.checkedMapping = checkedMapping;
}
/**
* Return the mapping for the disabled state value.
*
* @return the disabled mapping
*/
public String getDisabledMapping() {
return disabledMapping;
}
/**
* Set the mapping for the disabled state value.
*
* @param disabledMapping the disabled mapping
*/
public void setDisabledMapping(String disabledMapping) {
this.disabledMapping = disabledMapping;
}
/**
* Return the mapping for the node's expanded state value.
*
* @return the expanded mapping
*/
public String getExpandedMapping() {
return expandedMapping;
}
/**
* Set the mapping for the node's expanded state value.
*
* @param expandedMapping the expanded mapping
*/
public void setExpandedMapping(String expandedMapping) {
this.expandedMapping = expandedMapping;
}
/**
* Return the node's href value mapping
*
* @return the href mapping
*/
public String getHrefMapping() {
return hrefMapping;
}
/**
* Set the node's href value mapping.
*
* @param hrefMapping the href mapping
*/
public void setHrefMapping(String hrefMapping) {
this.hrefMapping = hrefMapping;
}
/**
* Return the node's href target value mapping.
*
* @return the href target mapping
*/
public String getHrefTargetMapping() {
return hrefTargetMapping;
}
/**
* Return the node's href target value mapping.
*
* @param hrefTargetMapping the href target mapping
*/
public void setHrefTargetMapping(String hrefTargetMapping) {
this.hrefTargetMapping = hrefTargetMapping;
}
/**
* Return the node's "allow drag" mapping.
*
* @return the allow drag mapping
*/
public String getAllowDragMapping() {
return allowDragMapping;
}
/**
* Set the node's "allow drag" mapping.
*
* @param allowDragMapping the allow drag mapping
*/
public void setAllowDragMapping(String allowDragMapping) {
this.allowDragMapping = allowDragMapping;
}
/**
* Return the node's "allow drop" mapping.
*
* @return the allow drop mapping
*/
public String getAllowDropMapping() {
return allowDropMapping;
}
/**
* Set the node's "allow drop" mapping.
*
* @param allowDropMapping the allow drop mapping
*/
public void setAllowDropMapping(String allowDropMapping) {
this.allowDropMapping = allowDropMapping;
}
/**
* Return the node's attribute name(s) mapping.
*
* @return the attribute name mapping
*/
public String[] getAttributeMappings() {
return attributeMappings;
}
/**
* Set the node's attribute name(s) mapping.
*
* @param attributeMappings attribute name mapping
*/
public void setAttributeMappings(String[] attributeMappings) {
this.attributeMappings = attributeMappings;
}
}
|