001: package com.gwtext.client.widgets.tree;
002:
003: import com.google.gwt.core.client.JavaScriptObject;
004: import com.google.gwt.http.client.*;
005: import com.google.gwt.xml.client.*;
006:
007: /**
008: * Provides the abilty to a TreePanel using remote XML data.This TreeLoader can be configured to load tree data from XML
009: * returned from a remote URL.
010: *<p>
011: * Sample code for loading a TreePanel using AsyncTreeNode and XmltreeLoader :
012: *
013: * <pre>
014: * <code>
015: *
016: * final TreePanel treePanel = new TreePanel() {
017: * {
018: * setAnimate(true);
019: * setEnableDD(true);
020: * setContainerScroll(true);
021: * setRootVisible(true);
022: * }
023: * };
024: *
025: * final XMLTreeLoader loader = new XMLTreeLoader() {
026: * {
027: * setDataUrl("countries-cb.xml");
028: * setMethod("get");
029: * setRootTag("countries");
030: * setFolderIdMapping("@id");
031: * setLeafIdMapping("@id");
032: * setFolderTitleMapping("@title");
033: * setFolderTag("team");
034: * setLeafTitleMapping("@title");
035: * setLeafTag("country");
036: * setQtipMapping("@qtip");
037: * setDisabledMapping("@disabled");
038: * setCheckedMapping("@checked");
039: * setIconMapping("@icon");
040: * setAttributeMappings(new String[]{"@rank"});
041: * }
042: * };
043: * AsyncTreeNode root = new AsyncTreeNode("Countries", loader);
044: *
045: * treePanel.setRootNode(root);
046: * treePanel.render();
047: *
048: * root.expand();
049: * treePanel.expandAll();
050: * </code>
051: * </pre>
052: *
053: * The above code loads a Tree using the following XML data - countries-cb.xml
054: *
055: * <pre>
056: * <code>
057: *<countries>
058: * <team id="team-a" title="Team A" icon="images/silk/flag_yellow.gif" checked="true">
059: * <country title="Brazil" qtip="Rank 2" rank="2" checked="false"/>
060: * <country title="Canada" qtip="Rank 3" rank="3" checked="false"/>
061: * <country title="China" qtip="Rank 4" rank="4" checked="false"/>
062: * </team>
063: * <team title="Team B" icon="images/silk/flag_blue.gif">
064: * <country title="Germany" qtip="Captain" checked="true" rank="1"/>
065: * <country title="France" qtip="Rank 2" rank="2" checked="false"/>
066: * <country title="Canada" qtip="Rank 3" rank="3" checked="false"/>
067: * <country title="India" qtip="Rank 4" rank="4" checked="false"/>
068: * <country title="Seychelles" qtip="Rank 5" rank="5" checked="false"/>
069: * </team>
070: *
071: * <team title="Team C" icon="images/silk/flag_green.gif">
072: * <country title="United States" qtip="Captain - Rank 1" checked="true" rank="1"/>
073: * <country title="Japan" qtip="Rank 2" rank="2" checked="false"/>
074: * <country title="Italy" qtip="Rank 3" rank="3" checked="false"/>
075: * <country title="Finland" qtip="Rank 4" rank="4" checked="false"/>
076: * </team>
077: * </countries>
078: * </code>
079: * </pre>
080: *
081: * @see com.gwtext.client.widgets.tree.TreePanel
082: * @see com.gwtext.client.widgets.tree.TreeLoader
083: * @see com.gwtext.client.widgets.tree.AsyncTreeNode
084: */
085: public class XMLTreeLoader extends TreeLoader {
086:
087: static {
088: init();
089: }
090:
091: /**
092: * Construct a new XMLTreeLoader.
093: */
094: public XMLTreeLoader() {
095: }
096:
097: /**
098: * Construct a new XMLTreeLoader.
099: *
100: * @param url the data url
101: * @param rootTag the root tag
102: * @param folderTag the folder tag
103: *
104: */
105: public XMLTreeLoader(String url, String rootTag, String folderTag) {
106: setDataUrl(url);
107: setRootTag(rootTag);
108: setFolderTag(folderTag);
109: }
110:
111: protected native JavaScriptObject create(JavaScriptObject configJS)/*-{
112: return new $wnd.Ext.tree.XMLTreeLoader(configJS, this);
113: }-*/;
114:
115: private static native void init() /*-{
116: $wnd.Ext.tree.XMLTreeLoader = function(configJS, selfJ) {
117: $wnd.Ext.tree.XMLTreeLoader.superclass.constructor.call(this, configJS);
118: this.selfJ = selfJ;
119: };
120:
121: $wnd.Ext.extend($wnd.Ext.tree.XMLTreeLoader, $wnd.Ext.tree.TreeLoader, {
122:
123: load : function(node, callback){
124: if(this.clearOnLoad){
125: while(node.firstChild){
126: node.removeChild(node.firstChild);
127: }
128: }
129: this.requestData(node, callback);
130: },
131:
132: requestData : function(node, callback){
133: if(this.fireEvent("beforeload", this, node, callback) !== false){
134: var nodeJ = @com.gwtext.client.widgets.tree.TreeNode::instance(Lcom/google/gwt/core/client/JavaScriptObject;)(node);
135: var params = this.getParams(node);
136: @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);
137:
138: }else{
139: // if the load is cancelled, make sure we notify
140: // the node that we are done
141: if(typeof callback == "function"){
142: callback();
143: }
144: }
145: },
146:
147: handleResponse : function(response){
148: this.transId = false;
149: //var a = response.argument;
150: var callback = response.callback;
151: var node = response.node;
152: var responseData = response.responseData;
153: if(typeof callback == "function"){
154: callback(this, node);
155: }
156: this.fireEvent("load", this, node, responseData);
157: },
158:
159: handleFailure : function(response){
160: this.transId = false;
161: var callback = response.callback;
162: var node = response.node;
163: var responseData = response.responseData;
164: this.fireEvent("loadexception", this, node, responseData);
165: if(typeof callback == "function"){
166: callback(this, node);
167: }
168: }
169: });
170: }-*/;
171:
172: private static void requestData(
173: final JavaScriptObject treeLoaderJS, final TreeNode root,
174: final XMLTreeLoader treeLoader, String method, String url,
175: final JavaScriptObject success,
176: final JavaScriptObject failure,
177: final JavaScriptObject callback, String params) {
178: //build side nav tree from xml data
179: RequestBuilder.Method httpMethod = "post"
180: .equalsIgnoreCase(method) ? RequestBuilder.POST
181: : RequestBuilder.GET;
182:
183: RequestBuilder builder = new RequestBuilder(httpMethod, url);
184: builder.setHeader("Content-type",
185: "application/x-www-form-urlencoded");
186: try {
187: builder.sendRequest(params, new RequestCallback() {
188:
189: public void onResponseReceived(Request request,
190: Response response) {
191: if (response.getStatusCode() == 200) {
192: Document xml = null;
193: try {
194: xml = XMLParser.parse(response.getText());
195: } catch (Exception e) {
196: call(failure, treeLoaderJS,
197: root.getJsObj(), callback, e
198: .getMessage());
199: return;
200: }
201: String rootTag = treeLoader.getRootTag();
202: Node rootNode = null;
203: if (rootTag == null) {
204: rootNode = xml.getDocumentElement()
205: .getParentNode().getChildNodes()
206: .item(0);
207: } else {
208: rootNode = xml
209: .getElementsByTagName(rootTag)
210: .item(0);
211: }
212: load(treeLoader, root, rootNode.getChildNodes());
213: call(success, treeLoaderJS, root.getJsObj(),
214: callback, response.getText());
215:
216: } else {
217: call(failure, treeLoaderJS, root.getJsObj(),
218: callback, response.getStatusCode()
219: + ":" + response.getText());
220: }
221: }
222:
223: public void onError(Request request, Throwable throwable) {
224: call(failure, treeLoaderJS, root.getJsObj(),
225: callback, throwable.getMessage());
226: }
227: });
228: } catch (RequestException e) {
229: call(failure, treeLoaderJS, root.getJsObj(), callback, e
230: .getMessage());
231: }
232: }
233:
234: private static native void call(JavaScriptObject func,
235: JavaScriptObject treeLoader, JavaScriptObject node,
236: JavaScriptObject callback, String responseData)/*-{
237: var arguments = {callback: callback, node: node, responseData : responseData};
238: func.call(treeLoader, arguments);
239: }-*/;
240:
241: private static void load(XMLTreeLoader treeLoader,
242: TreeNode currentNode, NodeList chidren) {
243: for (int i = 0; i < chidren.getLength(); i++) {
244: Node child = chidren.item(i);
245: if (!(child instanceof Element))
246: continue;
247: String name = child.getNodeName();
248: String folderTag = treeLoader.getFolderTag();
249: String leafTag = treeLoader.getLeafTag();
250:
251: if (name.equals(folderTag)) {
252: final String id = evaluateNodeValue(child, treeLoader
253: .getFolderIdMapping());
254: final String title = evaluateNodeValue(child,
255: treeLoader.getFolderTitleMapping());
256: TreeNode treeNode = createNode(child, treeLoader, id,
257: title);
258: currentNode.appendChild(treeNode);
259: load(treeLoader, treeNode, child.getChildNodes());
260: } else if (name.equals(leafTag)) {
261: final String id = evaluateNodeValue(child, treeLoader
262: .getLeafIdMapping());
263: final String title = evaluateNodeValue(child,
264: treeLoader.getLeafTitleMapping());
265: TreeNode treeNode = createNode(child, treeLoader, id,
266: title);
267: currentNode.appendChild(treeNode);
268: }
269: }
270: }
271:
272: private static TreeNode createNode(Node child,
273: XMLTreeLoader treeLoader, final String id, String title) {
274: final String icon = evaluateNodeValue(child, treeLoader
275: .getIconMapping());
276: final String iconCls = evaluateNodeValue(child, treeLoader
277: .getIconClsMapping());
278: final String qtip = evaluateNodeValue(child, treeLoader
279: .getQtipMapping());
280: final String checked = evaluateNodeValue(child, treeLoader
281: .getCheckedMapping());
282: final String disabled = evaluateNodeValue(child, treeLoader
283: .getDisabledMapping());
284: final String allowDrag = evaluateNodeValue(child, treeLoader
285: .getAllowDragMapping());
286: final String allowDrop = evaluateNodeValue(child, treeLoader
287: .getAllowDropMapping());
288: final String expanded = evaluateNodeValue(child, treeLoader
289: .getExpandedMapping());
290: final String href = evaluateNodeValue(child, treeLoader
291: .getHrefMapping());
292: final String hrefTarget = evaluateNodeValue(child, treeLoader
293: .getHrefTargetMapping());
294:
295: TreeNode treeNode = new TreeNode(title) {
296: {
297: setId(id);
298: setIcon(icon);
299: setIconCls(iconCls);
300: setTooltip(qtip);
301: setDisabled(booleanValue(disabled));
302: setAllowDrag(allowDrag == null
303: || booleanValue(allowDrag));
304: setAllowDrop(allowDrop == null
305: || booleanValue(allowDrop));
306: setExpanded(expanded == null || booleanValue(expanded));
307: setHref(href);
308: setHrefTarget(hrefTarget);
309: }
310: };
311: if (checked != null) {
312: treeNode.setChecked(booleanValue(checked));
313: }
314:
315: String[] attributeMappings = treeLoader.getAttributeMappings();
316: if (attributeMappings != null) {
317: for (int j = 0; j < attributeMappings.length; j++) {
318: String attributeMapping = attributeMappings[j];
319: String attributeName = attributeMapping.replaceAll("@",
320: "");
321: String attributeValue = evaluateNodeValue(child,
322: attributeMapping);
323: treeNode.setAttribute(attributeName, attributeValue);
324: }
325: }
326: return treeNode;
327: }
328:
329: private static boolean booleanValue(String value) {
330: if (value == null)
331: return false;
332: return value.equalsIgnoreCase("true") || value.equals("1");
333: }
334:
335: private static String evaluateNodeValue(Node node, String mapping) {
336: if (mapping == null)
337: return null;
338: String value = null;
339: if (mapping.startsWith("@")) {
340: String attribute = mapping.substring(1, mapping.length());
341: Node item = node.getAttributes().getNamedItem(attribute);
342: value = item == null ? null : item.getNodeValue();
343: } else {
344: NodeList nodeList = node.getChildNodes();
345: for (int j = 0; j < nodeList.getLength(); j++) {
346: Node child = nodeList.item(j);
347: if (!(child instanceof Element))
348: continue;
349: String nodeName = child.getNodeName();
350: if (nodeName.equals(mapping)) {
351: value = child.getChildNodes().item(0)
352: .getNodeValue();
353: }
354: }
355: }
356: return value;
357: }
358:
359: private String rootTag;
360: private String folderTag = "node";
361: private String leafTag = "leaf";
362: private String folderTitleMapping = "@title";
363: private String leafTitleMapping = "@title";
364: private String folderIdMapping;
365: private String leafIdMapping;
366:
367: private String iconMapping = "@icon";
368: private String iconClsMapping = "@iconCls";
369: private String qtipMapping = "@qtip";
370: private String checkedMapping = "@checked";
371: private String disabledMapping = "@disabled";
372: private String expandedMapping = "@expanded";
373: private String hrefMapping = "@href";
374: private String hrefTargetMapping = "@hrefTarget";
375: private String allowDragMapping = "@allowDrag";
376: private String allowDropMapping = "@allowDrop";
377:
378: private String[] attributeMappings;
379:
380: /**
381: * The root tag name in the XML data.
382: *
383: * @param rootTag the root tag name
384: */
385: public void setRootTag(String rootTag) {
386: this .rootTag = rootTag;
387: }
388:
389: /**
390: * The folder tag name in the XML data.
391: *
392: * @param folderTag the folder tag name
393: */
394: public void setFolderTag(String folderTag) {
395: this .folderTag = folderTag;
396: }
397:
398: /**
399: * The leaf tag name in the XML data.
400: *
401: * @param leafTag the leaf tag name
402: */
403: public void setLeafTag(String leafTag) {
404: this .leafTag = leafTag;
405: }
406:
407: /**
408: * Mapping corresponding to the title of the folder relative to the folder tag.
409: *
410: * @param folderTitleMapping the folder title mapping
411: */
412: public void setFolderTitleMapping(String folderTitleMapping) {
413: this .folderTitleMapping = folderTitleMapping;
414: }
415:
416: /**
417: * Mapping corresponding to the title of the leaf relative to the leaf tag.
418: *
419: * @param leafTitleMapping the leaf title mapping
420: */
421: public void setLeafTitleMapping(String leafTitleMapping) {
422: this .leafTitleMapping = leafTitleMapping;
423: }
424:
425: /**
426: * Return the root tag name.
427: *
428: * @return the root tag
429: */
430: public String getRootTag() {
431: return rootTag;
432: }
433:
434: /**
435: * Return the folder tag name.
436: *
437: * @return the folder tag
438: */
439: public String getFolderTag() {
440: return folderTag;
441: }
442:
443: /**
444: * Return the leaf tag name.
445: *
446: * @return the leaf tag
447: */
448: public String getLeafTag() {
449: return leafTag;
450: }
451:
452: /**
453: * Return the folder title mapping.
454: *
455: * @return folder title mapping
456: */
457: public String getFolderTitleMapping() {
458: return folderTitleMapping;
459: }
460:
461: /**
462: * Return the leaf title mapping.
463: *
464: * @return the leaftitle mapping
465: */
466: public String getLeafTitleMapping() {
467: return leafTitleMapping;
468: }
469:
470: /**
471: * Return the folder ID value mapping.
472: *
473: * @return the folder ID value mapping
474: */
475: public String getFolderIdMapping() {
476: return folderIdMapping;
477: }
478:
479: /**
480: * Return the leaf ID value mapping.
481: *
482: * @return the leaf ID value mapping
483: */
484: public String getLeafIdMapping() {
485: return leafIdMapping;
486: }
487:
488: /**
489: * Set the folder ID mapping relative to the folder tag.
490: *
491: * @param folderIdMapping the folder ID mapping
492: */
493: public void setFolderIdMapping(String folderIdMapping) {
494: this .folderIdMapping = folderIdMapping;
495: }
496:
497: /**
498: * Set the leaf ID mapping relative to the leaf tag.
499: *
500: * @param leafIdMapping the leaf ID mapping
501: */
502: public void setLeafIdMapping(String leafIdMapping) {
503: this .leafIdMapping = leafIdMapping;
504: }
505:
506: /**
507: * Return the icon mapping.
508: *
509: * @return the icon mapping
510: */
511: public String getIconMapping() {
512: return iconMapping;
513: }
514:
515: /**
516: * Set the icon mapping.
517: *
518: * @param iconMapping the icon mapping
519: */
520: public void setIconMapping(String iconMapping) {
521: this .iconMapping = iconMapping;
522: }
523:
524: /**
525: * Return the icon class mapping.
526: *
527: * @return the icon class mapping
528: */
529: public String getIconClsMapping() {
530: return iconClsMapping;
531: }
532:
533: /**
534: * Set the icon class mapping.
535: *
536: * @param iconClsMapping the icon class mapping
537: */
538: public void setIconClsMapping(String iconClsMapping) {
539: this .iconClsMapping = iconClsMapping;
540: }
541:
542: /**
543: * Return the quick tip value mapping.
544: *
545: * @return the quick tip mapping
546: */
547: public String getQtipMapping() {
548: return qtipMapping;
549: }
550:
551: /**
552: * Set the quick tip value mapping.
553: *
554: * @param qtipMapping the quick tip mapping
555: */
556: public void setQtipMapping(String qtipMapping) {
557: this .qtipMapping = qtipMapping;
558: }
559:
560: /**
561: * Return the checkbox state value mapping.
562: *
563: * @return the checked mapping
564: */
565: public String getCheckedMapping() {
566: return checkedMapping;
567: }
568:
569: /**
570: * Set the checkbox state value mapping.
571: *
572: * @param checkedMapping the checked mapping
573: */
574: public void setCheckedMapping(String checkedMapping) {
575: this .checkedMapping = checkedMapping;
576: }
577:
578: /**
579: * Return the mapping for the disabled state value.
580: *
581: * @return the disabled mapping
582: */
583: public String getDisabledMapping() {
584: return disabledMapping;
585: }
586:
587: /**
588: * Set the mapping for the disabled state value.
589: *
590: * @param disabledMapping the disabled mapping
591: */
592: public void setDisabledMapping(String disabledMapping) {
593: this .disabledMapping = disabledMapping;
594: }
595:
596: /**
597: * Return the mapping for the node's expanded state value.
598: *
599: * @return the expanded mapping
600: */
601: public String getExpandedMapping() {
602: return expandedMapping;
603: }
604:
605: /**
606: * Set the mapping for the node's expanded state value.
607: *
608: * @param expandedMapping the expanded mapping
609: */
610: public void setExpandedMapping(String expandedMapping) {
611: this .expandedMapping = expandedMapping;
612: }
613:
614: /**
615: * Return the node's href value mapping
616: *
617: * @return the href mapping
618: */
619: public String getHrefMapping() {
620: return hrefMapping;
621: }
622:
623: /**
624: * Set the node's href value mapping.
625: *
626: * @param hrefMapping the href mapping
627: */
628: public void setHrefMapping(String hrefMapping) {
629: this .hrefMapping = hrefMapping;
630: }
631:
632: /**
633: * Return the node's href target value mapping.
634: *
635: * @return the href target mapping
636: */
637: public String getHrefTargetMapping() {
638: return hrefTargetMapping;
639: }
640:
641: /**
642: * Return the node's href target value mapping.
643: *
644: * @param hrefTargetMapping the href target mapping
645: */
646: public void setHrefTargetMapping(String hrefTargetMapping) {
647: this .hrefTargetMapping = hrefTargetMapping;
648: }
649:
650: /**
651: * Return the node's "allow drag" mapping.
652: *
653: * @return the allow drag mapping
654: */
655: public String getAllowDragMapping() {
656: return allowDragMapping;
657: }
658:
659: /**
660: * Set the node's "allow drag" mapping.
661: *
662: * @param allowDragMapping the allow drag mapping
663: */
664: public void setAllowDragMapping(String allowDragMapping) {
665: this .allowDragMapping = allowDragMapping;
666: }
667:
668: /**
669: * Return the node's "allow drop" mapping.
670: *
671: * @return the allow drop mapping
672: */
673: public String getAllowDropMapping() {
674: return allowDropMapping;
675: }
676:
677: /**
678: * Set the node's "allow drop" mapping.
679: *
680: * @param allowDropMapping the allow drop mapping
681: */
682: public void setAllowDropMapping(String allowDropMapping) {
683: this .allowDropMapping = allowDropMapping;
684: }
685:
686: /**
687: * Return the node's attribute name(s) mapping.
688: *
689: * @return the attribute name mapping
690: */
691: public String[] getAttributeMappings() {
692: return attributeMappings;
693: }
694:
695: /**
696: * Set the node's attribute name(s) mapping.
697: *
698: * @param attributeMappings attribute name mapping
699: */
700: public void setAttributeMappings(String[] attributeMappings) {
701: this.attributeMappings = attributeMappings;
702: }
703: }
|