You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by jk...@apache.org on 2006/09/23 01:22:51 UTC
svn commit: r449122 [33/40] - in
/tapestry/tapestry4/trunk/tapestry-framework/src: java/org/apache/tapestry/
java/org/apache/tapestry/dojo/ java/org/apache/tapestry/dojo/form/
java/org/apache/tapestry/dojo/html/ java/org/apache/tapestry/form/
java/org/...
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeNodeV3.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeNodeV3.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeNodeV3.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeNodeV3.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,726 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.widget.TreeNodeV3");
+
+dojo.require("dojo.html.*");
+dojo.require("dojo.event.*");
+dojo.require("dojo.io.*");
+dojo.require("dojo.widget.TreeWithNode");
+
+dojo.widget.defineWidget(
+ "dojo.widget.TreeNodeV3",
+ [dojo.widget.HtmlWidget, dojo.widget.TreeWithNode],
+ function() {
+ this.actionsDisabled = [];
+ },
+{
+ tryLazyInit: true,
+
+ /*
+ * Basic actions one can perform on nodes and, some(addchild) on trees
+ */
+ actions: {
+ MOVE: "MOVE",
+ DETACH: "DETACH",
+ EDIT: "EDIT",
+ ADDCHILD: "ADDCHILD",
+ SELECT: "SELECT"
+ },
+
+
+ labelClass: "",
+ contentClass: "",
+
+ expandNode: null,
+ labelNode: null,
+
+
+ nodeType: "",
+ selected: false,
+
+ getNodeType: function() {
+ return this.nodeType;
+ },
+
+ cloneProperties: ["actionsDisabled","tryLazyInit","nodeType","objectId","object",
+ "title","isFolder","isExpanded","state"],
+
+
+ /**
+ * copy cloneProperties with recursion into them
+ * contains "copy constructor"
+ */
+ clone: function(deep) {
+ var ret = new this.constructor();
+
+ //dojo.debug("start cloning props "+this);
+
+ for(var i=0; i<this.cloneProperties.length; i++) {
+ var prop = this.cloneProperties[i];
+ //dojo.debug("cloning "+prop+ ":" +this[prop]);
+ ret[prop] = dojo.lang.shallowCopy(this[prop], true);
+ }
+
+ if (this.tree.unsetFolderOnEmpty && !deep && this.isFolder) {
+ ret.isFolder = false;
+ }
+
+ //dojo.debug("cloned props "+this);
+
+ ret.toggleObj = this.toggleObj;
+
+ dojo.widget.manager.add(ret);
+
+ ret.tree = this.tree;
+ ret.buildRendering({},{});
+ ret.initialize({},{});
+
+ if (deep && this.children.length) {
+ //dojo.debug("deeper copy start");
+ for(var i=0; i<this.children.length; i++) {
+ var child = this.children[i];
+ //dojo.debug("copy child "+child);
+ if (child.clone) {
+ ret.children.push(child.clone(deep));
+ } else {
+ ret.children.push(dojo.lang.shallowCopy(child, deep));
+ }
+ }
+ //dojo.debug("deeper copy end");
+ ret.setChildren();
+ }
+
+
+
+ return ret;
+ },
+
+
+ markProcessing: function() {
+ this.markProcessingSavedClass = dojo.html.getClass(this.expandNode);
+ dojo.html.setClass(this.expandNode, this.tree.classPrefix+'ExpandLoading');
+ },
+
+ unmarkProcessing: function() {
+ dojo.html.setClass(this.expandNode, this.markProcessingSavedClass);
+ },
+
+
+
+
+ /**
+ * get information from args & parent, then build rendering
+ */
+ buildRendering: function(args, fragment, parent) {
+ //dojo.debug("Build for "+args.toSource());
+
+ if (args.tree) {
+ this.tree = dojo.lang.isString(args.tree) ? dojo.widget.manager.getWidgetById(args.tree) : args.tree;
+ } else if (parent && parent.tree) {
+ this.tree = parent.tree;
+ }
+
+ if (!this.tree) {
+ dojo.raise("Can't evaluate tree from arguments or parent");
+ }
+
+
+ //dojo.profile.start("buildRendering - cloneNode");
+
+ this.domNode = this.tree.nodeTemplate.cloneNode(true);
+ this.expandNode = this.domNode.firstChild;
+ this.contentNode = this.domNode.childNodes[1];
+ this.labelNode = this.contentNode.firstChild;
+
+ if (this.labelClass) {
+ dojo.html.addClass(this.labelNode, this.labelClass);
+ }
+
+ if (this.contentClass) {
+ dojo.html.addClass(this.contentNode, this.contentClass);
+ }
+
+
+ //dojo.profile.end("buildRendering - cloneNode");
+
+
+ this.domNode.widgetId = this.widgetId;
+
+ //dojo.profile.start("buildRendering - innerHTML");
+ this.labelNode.innerHTML = this.title;
+ //dojo.profile.end("buildRendering - innerHTML");
+
+ },
+
+
+ isTreeNode: true,
+
+
+ object: {},
+
+ title: "",
+
+ isFolder: null, // set by widget depending on children/args
+
+ contentNode: null, // the item label
+
+ expandClass: "",
+
+
+ isExpanded: false,
+
+
+ containerNode: null,
+
+
+ getInfo: function() {
+ // No title here (title may be widget)
+ var info = {
+ widgetId: this.widgetId,
+ objectId: this.objectId,
+ index: this.getParentIndex()
+ }
+
+ return info;
+ },
+
+ setFolder: function() {
+ //dojo.debug("SetFolder in "+this);
+ this.isFolder = true;
+ this.viewSetExpand();
+ if (!this.containerNode) { // maybe this node was unfolderized and still has container
+ this.viewAddContainer(); // all folders have container.
+ }
+ //dojo.debug("publish "+this.tree.eventNames.setFolder);
+ dojo.event.topic.publish(this.tree.eventNames.afterSetFolder, { source: this });
+ },
+
+
+
+ initialize: function(args, frag, parent) {
+
+ //dojo.profile.start("initialize");
+
+ /**
+ * first we populate current widget from args,
+ * then use its data to initialize
+ * args may be empty, all data inside widget for copy constructor
+ */
+ if (args.isFolder) {
+ this.isFolder = true;
+ }
+
+ if (this.children.length || this.isFolder) {
+ //dojo.debug("children found");
+ //dojo.debug(this.children);
+ //dojo.debug("isFolder "+args.isFolder);
+
+ // viewSetExpand for Folder is set here also
+ this.setFolder();
+ } else {
+ // set expandicon for leaf
+ this.viewSetExpand();
+ }
+
+ for(var i=0; i<this.actionsDisabled.length;i++) {
+ this.actionsDisabled[i] = this.actionsDisabled[i].toUpperCase();
+ }
+ //dojo.debug("publish "+this.tree.eventNames.changeTree);
+
+ dojo.event.topic.publish(this.tree.eventNames.afterChangeTree, {oldTree:null, newTree:this.tree, node:this} );
+
+
+ //dojo.profile.end("initialize");
+
+ //dojo.debug("initialize out "+this);
+ //dojo.debug(this+" parent "+parent);
+ },
+
+ unsetFolder: function() {
+ this.isFolder = false;
+ this.viewSetExpand();
+ dojo.event.topic.publish(this.tree.eventNames.afterUnsetFolder, { source: this });
+ },
+
+
+ insertNode: function(parent, index) {
+
+ if (!index) index = 0;
+ //dojo.debug("insertNode "+this+" parent "+parent+" before "+index);
+
+ if (index==0) {
+ dojo.html.prependChild(this.domNode, parent.containerNode);
+ } else {
+ dojo.html.insertAfter(this.domNode, parent.children[index-1].domNode);
+ }
+ },
+
+ updateTree: function(newTree) {
+
+ if (this.tree === newTree) {
+ return;
+ }
+
+ var oldTree = this.tree;
+
+
+ dojo.lang.forEach(this.getDescendants(),
+ function(elem) {
+ elem.tree = newTree;
+ });
+
+ /**
+ * UNTESTED
+ * changes class prefix for all domnodes when moving between trees
+ */
+ if (oldTree.classPrefix != newTree.classPrefix) {
+ var stack = [this.domNode]
+ var elem;
+ var reg = new RegExp("(^|\\s)"+oldTree.classPrefix, "g");
+
+ while (elem = stack.pop()) {
+ for(var i=0; i<elem.childNodes.length; i++) {
+ var childNode = elem.childNodes[i]
+ if (childNode.nodeType != 1) continue;
+ // change prefix for classes
+ dojo.html.setClass(childNode, dojo.html.getClass(childNode).replace(reg, '$1'+newTree.classPrefix));
+ stack.push(childNode);
+ }
+ }
+
+ }
+
+ var message = {oldTree:oldTree, newTree:newTree, node:this}
+
+ dojo.event.topic.publish(this.tree.eventNames.afterChangeTree, message );
+ dojo.event.topic.publish(newTree.eventNames.afterChangeTree, message );
+
+
+ },
+
+
+ /**
+ * called every time the widget is added with createWidget or created wia markup
+ * from addChild -> registerChild or from postInitialize->registerChild
+ * not called in batch procession
+ * HTML & widget.createWidget only
+ * Layout MUST be removed when node is detached
+ *
+ */
+ addedTo: function(parent, index, dontPublishEvent) {
+ //dojo.profile.start("addedTo");
+ //dojo.debug(this + " addedTo "+parent+" index "+index);
+ //dojo.debug(parent.children);
+ //dojo.debug(parent.containerNode.innerHTML);
+
+ //dojo.debug((new Error()).stack);
+
+
+ if (this.tree !== parent.tree) {
+ this.updateTree(parent.tree);
+ }
+
+ if (parent.isTreeNode) {
+ if (!parent.isFolder) {
+ //dojo.debug("folderize parent "+parent);
+ parent.setFolder();
+ parent.state = parent.loadStates.LOADED;
+ }
+ }
+
+
+ var siblingsCount = parent.children.length;
+
+ // setFolder works BEFORE insertNode
+ this.insertNode(parent, index);
+
+
+ this.viewAddLayout();
+
+
+ //dojo.debug("siblings "+parent.children);
+
+ if (siblingsCount > 1) {
+ if (index == 0 && parent.children[1] instanceof dojo.widget.Widget) {
+ parent.children[1].viewUpdateLayout();
+ }
+ if (index == siblingsCount-1 && parent.children[siblingsCount-2] instanceof dojo.widget.Widget) {
+ parent.children[siblingsCount-2].viewUpdateLayout();
+ }
+ } else if (parent.isTreeNode) {
+ // added as the first child
+ //dojo.debug("added as first");
+ parent.viewSetHasChildren();
+ }
+
+ if (!dontPublishEvent) {
+
+ var message = {
+ child: this,
+ index: index,
+ parent: parent
+ }
+
+ dojo.event.topic.publish(this.tree.eventNames.afterAddChild, message);
+ }
+
+ //dojo.profile.end("addedTo");
+
+
+ },
+
+ /**
+ * Fast program-only hacky creation of widget
+ *
+ */
+ createSimple: function(args, parent) {
+ // I pass no args and ignore default controller
+ //dojo.profile.start(this.widgetType+" createSimple");
+ //dojo.profile.start(this.widgetType+" createSimple constructor");
+ if (args.tree) {
+ var tree = args.tree;
+ } else if (parent) {
+ var tree = parent.tree;
+ } else {
+ dojo.raise("createSimple: can't evaluate tree");
+ }
+ tree = dojo.widget.byId(tree);
+
+ //dojo.debug(tree);
+
+ var treeNode = new tree.defaultChildWidget();
+ //dojo.profile.end(this.widgetType+" createSimple constructor");
+
+ //dojo.profile.start(this.widgetType+" createSimple mixin");
+ for(var x in args){ // fastMixIn
+ treeNode[x] = args[x];
+ }
+
+
+ //dojo.profile.end(this.widgetType+" createSimple mixin");
+
+
+ // HtmlWidget.postMixIn
+ treeNode.toggleObj = dojo.lfx.toggle[treeNode.toggle.toLowerCase()] || dojo.lfx.toggle.plain;
+
+ //dojo.profile.start(this.widgetType + " manager");
+ dojo.widget.manager.add(treeNode);
+ //dojo.profile.end(this.widgetType + " manager");
+
+ //dojo.profile.start(this.widgetType + " buildRendering");
+ treeNode.buildRendering(args, {}, parent);
+ //dojo.profile.end(this.widgetType + " buildRendering");
+
+ treeNode.initialize(args, {}, parent);
+
+ //dojo.profile.end(this.widgetType+"createSimple");
+ if (treeNode.parent) {
+ delete dojo.widget.manager.topWidgets[treeNode.widgetId];
+ }
+
+ return treeNode;
+ },
+
+
+
+ // can override e.g for case of div with +- text inside
+ viewUpdateLayout: function() {
+ //dojo.profile.start("viewUpdateLayout");
+ //dojo.debug("UpdateLayout in "+this);
+
+ this.viewRemoveLayout();
+ this.viewAddLayout();
+ //dojo.profile.end("viewUpdateLayout");
+ },
+
+
+ viewAddContainer: function() {
+ // make controller only if children exist
+ this.containerNode = this.tree.containerNodeTemplate.cloneNode(true);
+ this.domNode.appendChild(this.containerNode);
+ },
+ /*
+ viewRemoveContainer: function() {
+ // make controller only if children exist
+ this.domNode.removeChild(this.containerNode);
+ this.containerNode = null;
+ },
+ */
+
+ viewAddLayout: function() {
+ //dojo.profile.start("viewAddLayout");
+ //dojo.debug("viewAddLayout in "+this);
+
+ if (this.parent["isTree"]) {
+ //dojo.debug("Parent isTree => add isTreeRoot");
+
+ // use setClass, not addClass for speed
+ dojo.html.setClass(this.domNode, dojo.html.getClass(this.domNode) + ' '+this.tree.classPrefix+'IsRoot')
+ }
+ //dojo.debug(this.parent.children.length);
+ //dojo.debug(this.parent.children[this.parent.children.length-1]);
+ if (this.isLastChild()) {
+ //dojo.debug("Checked last node for "+this);
+ //dojo.debug("Parent last is "+this.parent.children[this.parent.children.length-1]);
+ //dojo.debug("last node => add isTreeLast for "+this);
+ dojo.html.setClass(this.domNode, dojo.html.getClass(this.domNode) + ' '+this.tree.classPrefix+'IsLast')
+ }
+ //dojo.profile.end("viewAddLayout");
+ //dojo.debug("viewAddLayout out");
+
+ },
+
+
+ viewRemoveLayout: function() {
+ //dojo.debug("viewRemoveLayout in "+this);
+ //dojo.profile.start("viewRemoveLayout");
+ //dojo.debug((new Error()).stack);
+ dojo.html.removeClass(this.domNode, this.tree.classPrefix+"IsRoot");
+ dojo.html.removeClass(this.domNode, this.tree.classPrefix+"IsLast");
+ //dojo.profile.end("viewRemoveLayout");
+ },
+
+ viewGetExpandClass: function() {
+ if (this.isFolder) {
+ return this.isExpanded ? "ExpandOpen" : "ExpandClosed";
+ } else {
+ return "ExpandLeaf";
+ }
+ },
+
+ viewSetExpand: function() {
+ //dojo.profile.start("viewSetExpand");
+
+ //dojo.debug("viewSetExpand in "+this);
+
+ var expand = this.tree.classPrefix+this.viewGetExpandClass();
+ var reg = new RegExp("(^|\\s)"+this.tree.classPrefix+"Expand\\w+",'g');
+
+ dojo.html.setClass(this.domNode, dojo.html.getClass(this.domNode).replace(reg,'') + ' '+expand);
+
+ //dojo.debug(dojo.html.getClass(this.domNode))
+ //dojo.profile.end("viewSetExpand");
+ this.viewSetHasChildrenAndExpand();
+ },
+
+ viewGetChildrenClass: function() {
+ return 'Children'+(this.children.length ? 'Yes' : 'No');
+ },
+
+ viewSetHasChildren: function() {
+ //dojo.debug(this+' '+this.children.length)
+
+ var clazz = this.tree.classPrefix+this.viewGetChildrenClass();
+
+ var reg = new RegExp("(^|\\s)"+this.tree.classPrefix+"Children\\w+",'g');
+
+ dojo.html.setClass(this.domNode, dojo.html.getClass(this.domNode).replace(reg,'') + ' '+clazz);
+
+ this.viewSetHasChildrenAndExpand();
+ },
+
+ /**
+ * set TreeStateChildrenYes-ExpandClosed pair
+ * needed for IE, because IE reads only last class from .TreeChildrenYes.TreeExpandClosed pair
+ */
+ viewSetHasChildrenAndExpand: function() {
+ var clazz = this.tree.classPrefix+'State'+this.viewGetChildrenClass()+'-'+this.viewGetExpandClass();
+
+ var reg = new RegExp("(^|\\s)"+this.tree.classPrefix+"State[\\w-]+",'g');
+
+ dojo.html.setClass(this.domNode, dojo.html.getClass(this.domNode).replace(reg,'') + ' '+clazz);
+ },
+
+ viewUnfocus: function() {
+ dojo.html.removeClass(this.labelNode, this.tree.classPrefix+"LabelFocused");
+ },
+
+ viewFocus: function() {
+ dojo.html.addClass(this.labelNode, this.tree.classPrefix+"LabelFocused");
+ },
+
+
+
+// ================================ detach from parent ===================================
+
+ detach: function() {
+ if (!this.parent) return;
+
+ var parent = this.parent;
+ var index = this.getParentIndex();
+
+ this.doDetach.apply(this, arguments);
+
+ dojo.event.topic.publish(this.tree.eventNames.afterDetach,
+ { child: this, parent: parent, index:index }
+ );
+
+ },
+
+
+ /* node does not leave tree */
+ doDetach: function() {
+ //dojo.debug("doDetach in "+this+" parent "+this.parent+" class "+dojo.html.getClass(this.domNode));
+
+ var parent = this.parent;
+
+ //dojo.debug(parent.containerNode.style.display)
+
+ if (!parent) return;
+
+ var index = this.getParentIndex();
+
+
+ this.viewRemoveLayout();
+
+ dojo.widget.DomWidget.prototype.removeChild.call(parent, this);
+
+ var siblingsCount = parent.children.length;
+
+ //dojo.debug("siblingsCount "+siblingsCount);
+
+ if (siblingsCount > 0) {
+ if (index == 0) { // deleted first node => update new first
+ parent.children[0].viewUpdateLayout();
+ }
+ if (index == siblingsCount) { // deleted last node
+ parent.children[siblingsCount-1].viewUpdateLayout();
+ }
+ } else {
+ if (parent.isTreeNode) {
+ parent.viewSetHasChildren();
+ }
+ }
+
+ if (this.tree.unsetFolderOnEmpty && !parent.children.length && parent.isTreeNode) {
+ parent.unsetFolder();
+ }
+
+ //dojo.debug(parent.containerNode.style.display)
+
+ this.parent = null;
+ },
+
+
+ /**
+ * publish destruction event so that controller may unregister/unlisten
+ */
+ destroy: function() {
+
+ dojo.event.topic.publish(this.tree.eventNames.beforeNodeDestroy, { source: this } );
+
+ this.detach();
+
+ return dojo.widget.HtmlWidget.prototype.destroy.apply(this, arguments);
+ },
+
+
+ expand: function(){
+
+ if (this.isExpanded) return;
+
+
+ //dojo.profile.start("expand "+this);
+
+ //dojo.debug("expand in "+this);
+
+ //dojo.profile.start("expand - lazy init "+this);
+ if (this.tryLazyInit) {
+ this.setChildren();
+ this.tryLazyInit = false;
+ }
+
+ //dojo.profile.end("expand - lazy init "+this);
+
+
+ this.isExpanded = true;
+
+ this.viewSetExpand();
+
+ //dojo.profile.start("expand - showChildren "+this);
+
+ /**
+ * no matter if I have children or not. need to show/hide container anyway.
+ * use case: empty folder is expanded => then child is added, container already shown all fine
+ */
+ this.showChildren();
+
+ //dojo.profile.end("expand - showChildren "+this);
+
+
+ //dojo.profile.end("expand "+this);
+ },
+
+
+ collapse: function(){
+
+ if (!this.isExpanded) return;
+
+ this.isExpanded = false;
+
+ this.hideChildren();
+ },
+
+
+ hideChildren: function(){
+ this.tree.toggleObj.hide(
+ this.containerNode, this.toggleDuration, this.explodeSrc, dojo.lang.hitch(this, "onHideChildren")
+ );
+ },
+
+
+ showChildren: function(){
+ //dojo.profile.start("showChildren"+this);
+
+ this.tree.toggleObj.show(
+ this.containerNode, this.toggleDuration, this.explodeSrc, dojo.lang.hitch(this, "onShowChildren")
+ );
+
+ //dojo.profile.end("showChildren"+this);
+ },
+
+
+
+ onShowChildren: function() {
+
+ //dojo.profile.start("onShowChildren"+this);
+
+ this.onShow();
+
+ //dojo.profile.end("onShowChildren"+this);
+
+ dojo.event.topic.publish(this.tree.eventNames.afterExpand, {source: this} );
+ },
+
+ onHideChildren: function() {
+
+ this.viewSetExpand();
+ this.onHide();
+ dojo.event.topic.publish(this.tree.eventNames.afterCollapse, {source: this} );
+ },
+
+ /* Edit current node : change properties and update contents */
+ setTitle: function(title) {
+ var oldTitle = this.title;
+
+ this.labelNode.innerHTML = this.title = title;
+
+ dojo.event.topic.publish(this.tree.eventNames.afterSetTitle, { source: this, oldTitle:oldTitle });
+
+ },
+
+
+ toString: function() {
+ return '['+this.widgetType+', '+this.title+']';
+ }
+
+
+});
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeNodeV3.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeRPCController.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeRPCController.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeRPCController.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeRPCController.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,174 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+
+dojo.provide("dojo.widget.TreeRPCController");
+
+dojo.require("dojo.event.*");
+dojo.require("dojo.json")
+dojo.require("dojo.io.*");
+dojo.require("dojo.widget.TreeLoadingController");
+
+
+dojo.deprecated("dojo.widget.TreeRPCController", "use TreeV3 and TreeRpcControllerV3 instead", "0.5");
+
+dojo.widget.tags.addParseTreeHandler("dojo:TreeRPCController");
+
+dojo.widget.TreeRPCController = function(){
+ dojo.widget.TreeLoadingController.call(this);
+}
+
+dojo.inherits(dojo.widget.TreeRPCController, dojo.widget.TreeLoadingController);
+
+dojo.lang.extend(dojo.widget.TreeRPCController, {
+ widgetType: "TreeRPCController",
+
+ /**
+ * Make request to server about moving children.
+ *
+ * Request returns "true" if move succeeded,
+ * object with error field if failed
+ *
+ * I can't leave DragObject floating until async request returns, need to return false/true
+ * so making it sync way...
+ *
+ * Also, "loading" icon is not shown until function finishes execution, so no indication for remote request.
+ */
+ doMove: function(child, newParent, index){
+
+ //if (newParent.isTreeNode) newParent.markLoading();
+
+ var params = {
+ // where from
+ child: this.getInfo(child),
+ childTree: this.getInfo(child.tree),
+ // where to
+ newParent: this.getInfo(newParent),
+ newParentTree: this.getInfo(newParent.tree),
+ newIndex: index
+ };
+
+ var success;
+
+ this.runRPC({
+ url: this.getRPCUrl('move'),
+ /* I hitch to get this.loadOkHandler */
+ load: function(response){
+ success = this.doMoveProcessResponse(response, child, newParent, index) ;
+ },
+ sync: true,
+ lock: [child, newParent],
+ params: params
+ });
+
+
+ return success;
+ },
+
+ doMoveProcessResponse: function(response, child, newParent, index){
+
+ if(!dojo.lang.isUndefined(response.error)){
+ this.RPCErrorHandler("server", response.error);
+ return false;
+ }
+
+ var args = [child, newParent, index];
+ return dojo.widget.TreeLoadingController.prototype.doMove.apply(this, args);
+
+ },
+
+
+ doRemoveNode: function(node, callObj, callFunc){
+
+ var params = {
+ node: this.getInfo(node),
+ tree: this.getInfo(node.tree)
+ }
+
+ this.runRPC({
+ url: this.getRPCUrl('removeNode'),
+ /* I hitch to get this.loadOkHandler */
+ load: function(response){
+ this.doRemoveNodeProcessResponse(response, node, callObj, callFunc)
+ },
+ params: params,
+ lock: [node]
+ });
+
+ },
+
+
+ doRemoveNodeProcessResponse: function(response, node, callObj, callFunc){
+ if(!dojo.lang.isUndefined(response.error)){
+ this.RPCErrorHandler("server", response.error);
+ return false;
+ }
+
+ if(!response){ return false; }
+
+ if(response == true){
+ /* change parent succeeded */
+ var args = [ node, callObj, callFunc ];
+ dojo.widget.TreeLoadingController.prototype.doRemoveNode.apply(this, args);
+
+ return;
+ }else if(dojo.lang.isObject(response)){
+ dojo.raise(response.error);
+ }else{
+ dojo.raise("Invalid response "+response)
+ }
+
+
+ },
+
+
+
+ // -----------------------------------------------------------------------------
+ // Create node stuff
+ // -----------------------------------------------------------------------------
+
+
+ doCreateChild: function(parent, index, output, callObj, callFunc){
+
+ var params = {
+ tree: this.getInfo(parent.tree),
+ parent: this.getInfo(parent),
+ index: index,
+ data: output
+ }
+
+ this.runRPC({
+ url: this.getRPCUrl('createChild'),
+ load: function(response) {
+ // suggested data is dead, fresh data from server is used
+ this.doCreateChildProcessResponse( response, parent, index, callObj, callFunc)
+ },
+ params: params,
+ lock: [parent]
+ });
+
+ },
+
+ doCreateChildProcessResponse: function(response, parent, index, callObj, callFunc){
+
+ if(!dojo.lang.isUndefined(response.error)){
+ this.RPCErrorHandler("server",response.error);
+ return false;
+ }
+
+ if(!dojo.lang.isObject(response)){
+ dojo.raise("Invalid result "+response)
+ }
+
+ var args = [parent, index, response, callObj, callFunc];
+
+ dojo.widget.TreeLoadingController.prototype.doCreateChild.apply(this, args);
+ }
+});
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeRPCController.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeRpcControllerV3.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeRpcControllerV3.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeRpcControllerV3.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeRpcControllerV3.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,424 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+
+dojo.provide("dojo.widget.TreeRpcControllerV3");
+
+dojo.require("dojo.event.*");
+dojo.require("dojo.json")
+dojo.require("dojo.io.*");
+dojo.require("dojo.widget.TreeLoadingControllerV3");
+
+dojo.widget.defineWidget(
+ "dojo.widget.TreeRpcControllerV3",
+ dojo.widget.TreeLoadingControllerV3,
+{
+ // TODO: do something with addChild / setChild, so that RpcController become able
+ // to hook on this and report to server
+
+ extraRpcOnEdit: false,
+
+ /**
+ * Make request to server about moving children.
+ *
+ * Request returns "true" if move succeeded,
+ * object with error field if failed
+ *
+ * I can't leave DragObject floating until async request returns, need to return false/true
+ * so making it sync way...
+ *
+ * Also, "loading" icon is not shown until function finishes execution, so no indication for remote request.
+ */
+ doMove: function(child, newParent, index, sync){
+
+ //if (newParent.isTreeNode) newParent.markLoading();
+
+
+ var params = {
+ // where from
+ child: this.getInfo(child),
+ childTree: this.getInfo(child.tree),
+ // where to
+ newParent: this.getInfo(newParent),
+ newParentTree: this.getInfo(newParent.tree),
+ newIndex: index
+ };
+
+
+ var deferred = this.runRpc({
+ url: this.getRpcUrl('move'),
+ sync: sync,
+ params: params
+ });
+
+ var _this = this;
+ var args = arguments;
+
+ //deferred.addCallback(function(res) { dojo.debug("doMove fired "+res); return res});
+
+ deferred.addCallback(function() {
+ dojo.widget.TreeBasicControllerV3.prototype.doMove.apply(_this,args);
+ });
+
+
+ return deferred;
+ },
+
+ // -------------- detach
+
+ prepareDetach: function(node, sync) {
+ var deferred = this.startProcessing(node);
+ return deferred;
+ },
+
+ finalizeDetach: function(node) {
+ this.finishProcessing(node);
+ },
+
+ doDetach: function(node, sync){
+
+
+ var params = {
+ node: this.getInfo(node),
+ tree: this.getInfo(node.tree)
+ }
+
+ var deferred = this.runRpc({
+ url: this.getRpcUrl('detach'),
+ sync: sync,
+ params: params
+ });
+
+
+ var _this = this;
+ var args = arguments;
+
+ deferred.addCallback(function() {
+ dojo.widget.TreeBasicControllerV3.prototype.doDetach.apply(_this,args);
+ });
+
+
+ return deferred;
+
+ },
+
+ // -------------------------- Inline edit node ---------------------
+
+ /**
+ * send edit start request if needed
+ * useful for server-side locking
+ */
+ requestEditConfirmation: function(node, action, sync) {
+ if (!this.extraRpcOnEdit) {
+ return dojo.Deferred.prototype.makeCalled();
+ }
+
+ //dojo.debug("requestEditConfirmation "+node+" "+action);
+
+ var _this = this;
+
+ var deferred = this.startProcessing(node);
+
+ //dojo.debug("startProcessing "+node);
+
+ var params = {
+ node: this.getInfo(node),
+ tree: this.getInfo(node.tree)
+ }
+
+ deferred.addCallback(function() {
+ //dojo.debug("add action on requestEditConfirmation "+action);
+ return _this.runRpc({
+ url: _this.getRpcUrl(action),
+ sync: sync,
+ params: params
+ });
+ });
+
+
+ deferred.addBoth(function(r) {
+ //dojo.debug("finish rpc with "+r);
+ _this.finishProcessing(node);
+ return r;
+ });
+
+ return deferred;
+ },
+
+ editLabelSave: function(node, newContent, sync) {
+ var deferred = this.startProcessing(node);
+
+ var _this = this;
+
+ var params = {
+ node: this.getInfo(node),
+ tree: this.getInfo(node.tree),
+ newContent: newContent
+ }
+
+
+ deferred.addCallback(function() {
+ return _this.runRpc({
+ url: _this.getRpcUrl('editLabelSave'),
+ sync: sync,
+ params: params
+ });
+ });
+
+
+ deferred.addBoth(function(r) {
+ _this.finishProcessing(node);
+ return r;
+ });
+
+ return deferred;
+ },
+
+ editLabelStart: function(node, sync) {
+ if (!this.canEditLabel(node)) {
+ return false;
+ }
+
+ var _this = this;
+
+ if (!this.editor.isClosed()) {
+ //dojo.debug("editLabelStart editor open");
+ var deferred = this.editLabelFinish(this.editor.saveOnBlur, sync);
+ deferred.addCallback(function() {
+ return _this.editLabelStart(node, sync);
+ });
+ return deferred;
+ }
+
+ //dojo.debug("editLabelStart closed, request");
+ var deferred = this.requestEditConfirmation(node, 'editLabelStart', sync);
+
+ deferred.addCallback(function() {
+ //dojo.debug("start edit");
+ _this.doEditLabelStart(node);
+ });
+
+
+ return deferred;
+
+ },
+
+ editLabelFinish: function(save, sync) {
+ var _this = this;
+
+ var node = this.editor.node;
+
+ var deferred = dojo.Deferred.prototype.makeCalled();
+
+ if (!save && !node.isPhantom) {
+ deferred = this.requestEditConfirmation(this.editor.node,'editLabelFinishCancel', sync);
+ }
+
+ if (save) {
+ if (node.isPhantom) {
+ deferred = this.sendCreateChildRequest(
+ node.parent,
+ node.getParentIndex(),
+ {title:this.editor.getContents()},
+ sync
+ );
+ } else {
+ // this deferred has new information from server
+ deferred = this.editLabelSave(node, this.editor.getContents(), sync);
+ }
+ }
+
+ deferred.addCallback(function(server_data) {
+ _this.doEditLabelFinish(save, server_data);
+ });
+
+ deferred.addErrback(function(r) {
+ //dojo.debug("Error occured");
+ //dojo.debugShallow(r);
+ _this.doEditLabelFinish(false);
+ return false;
+ });
+
+ return deferred;
+ },
+
+
+
+ /**
+ * TODO: merge server-side info
+ */
+ createAndEdit: function(parent, index, sync) {
+ var data = {title:parent.tree.defaultChildTitle};
+
+ if (!this.canCreateChild(parent, index, data)) {
+ return false;
+ }
+
+ /* close editor first */
+ if (!this.editor.isClosed()) {
+ //dojo.debug("editLabelStart editor open");
+ var deferred = this.editLabelFinish(this.editor.saveOnBlur, sync);
+ deferred.addCallback(function() {
+ return _this.createAndEdit(parent, index, sync);
+ });
+ return deferred;
+ }
+
+ var _this = this;
+
+ /* load parent and create child*/
+ var deferred = this.prepareCreateChild(parent, index, data, sync);
+
+
+ deferred.addCallback(function() {
+ var child = _this.makeDefaultNode(parent, index);
+ child.isPhantom = true;
+ return child;
+ });
+
+
+ deferred.addBoth(function(r) {
+ _this.finalizeCreateChild(parent, index, data, sync);
+ return r;
+ });
+
+ /* expand parent */
+ deferred.addCallback(function(child) {
+ var d = _this.exposeCreateChild(parent, index, data, sync);
+ d.addCallback(function() { return child });
+ return d;
+ });
+
+
+ deferred.addCallback(function(child) {
+ //dojo.debug("start edit");
+ _this.doEditLabelStart(child);
+ return child;
+ });
+
+
+
+ return deferred;
+
+ },
+
+ prepareDestroyChild: function(node, sync) {
+ //dojo.debug(node);
+ var deferred = this.startProcessing(node);
+ return deferred;
+ },
+
+ finalizeDestroyChild: function(node) {
+ this.finishProcessing(node);
+ },
+
+
+ doDestroyChild: function(node, sync){
+
+
+ var params = {
+ node: this.getInfo(node),
+ tree: this.getInfo(node.tree)
+ }
+
+ var deferred = this.runRpc({
+ url: this.getRpcUrl('destroyChild'),
+ sync: sync,
+ params: params
+ });
+
+
+ var _this = this;
+ var args = arguments;
+
+ deferred.addCallback(function() {
+ dojo.widget.TreeBasicControllerV3.prototype.doDestroyChild.apply(_this,args);
+ });
+
+
+ return deferred;
+
+ },
+
+ // -----------------------------------------------------------------------------
+ // Create node stuff
+ // -----------------------------------------------------------------------------
+ sendCreateChildRequest: function(parent, index, data, sync) {
+ var params = {
+ tree: this.getInfo(parent.tree),
+ parent: this.getInfo(parent),
+ index: index,
+ data: data
+ }
+
+ var deferred = this.runRpc({
+ url: this.getRpcUrl('createChild'),
+ sync: sync,
+ params: params
+ });
+
+ return deferred;
+ },
+
+
+ doCreateChild: function(parent, index, data, sync){
+
+ if (dojo.lang.isUndefined(data.title)) {
+ data.title = parent.tree.defaultChildTitle;
+ }
+
+ var deferred = this.sendCreateChildRequest(parent,index,data,sync);
+
+ var _this = this;
+ var args = arguments;
+
+
+ deferred.addCallback(function(server_data) {
+ dojo.lang.mixin(server_data, data); // add my data as less priority
+ //dojo.debug("Create ");
+ //dojo.debug(server_data);
+ return dojo.widget.TreeBasicControllerV3.prototype.doCreateChild.call(_this,parent,index,server_data);
+ });
+
+
+ return deferred;
+ },
+
+ // TODO: merge server data into cloned node, like in createChild
+ doClone: function(child, newParent, index, deep, sync) {
+
+ var params = {
+ child: this.getInfo(child),
+ newParent: this.getInfo(newParent),
+ index: index,
+ deep: deep ? true : false, // undefined -> false
+ tree: this.getInfo(child.tree)
+ }
+
+
+ var deferred = this.runRpc({
+ url: this.getRpcUrl('clone'),
+ sync: sync,
+ params: params
+ });
+
+ var _this = this;
+ var args = arguments;
+
+ deferred.addCallback(function() {
+ dojo.widget.TreeBasicControllerV3.prototype.doClone.apply(_this,args);
+ });
+
+
+ return deferred;
+ }
+
+
+});
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeRpcControllerV3.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeSelector.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeSelector.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeSelector.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeSelector.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,191 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+
+dojo.provide("dojo.widget.TreeSelector");
+
+dojo.require("dojo.widget.HtmlWidget");
+
+dojo.deprecated("dojo.widget.TreeSelector", "use TreeV3 and TreeSelectorV3 instead", "0.5");
+
+
+dojo.widget.tags.addParseTreeHandler("dojo:TreeSelector");
+
+
+dojo.widget.TreeSelector = function() {
+ dojo.widget.HtmlWidget.call(this);
+
+
+ this.eventNames = {};
+
+ this.listenedTrees = [];
+
+}
+
+dojo.inherits(dojo.widget.TreeSelector, dojo.widget.HtmlWidget);
+
+
+dojo.lang.extend(dojo.widget.TreeSelector, {
+ widgetType: "TreeSelector",
+ selectedNode: null,
+
+ dieWithTree: false,
+
+ eventNamesDefault: {
+ select : "select",
+ destroy : "destroy",
+ deselect : "deselect",
+ dblselect: "dblselect" // select already selected node.. Edit or whatever
+ },
+
+ initialize: function() {
+
+ for(name in this.eventNamesDefault) {
+ if (dojo.lang.isUndefined(this.eventNames[name])) {
+ this.eventNames[name] = this.widgetId+"/"+this.eventNamesDefault[name];
+ }
+ }
+
+ },
+
+
+ destroy: function() {
+ dojo.event.topic.publish(this.eventNames.destroy, { source: this } );
+
+ return dojo.widget.HtmlWidget.prototype.destroy.apply(this, arguments);
+ },
+
+
+ listenTree: function(tree) {
+ dojo.event.topic.subscribe(tree.eventNames.titleClick, this, "select");
+ dojo.event.topic.subscribe(tree.eventNames.iconClick, this, "select");
+ dojo.event.topic.subscribe(tree.eventNames.collapse, this, "onCollapse");
+ dojo.event.topic.subscribe(tree.eventNames.moveFrom, this, "onMoveFrom");
+ dojo.event.topic.subscribe(tree.eventNames.removeNode, this, "onRemoveNode");
+ dojo.event.topic.subscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy");
+
+ /* remember all my trees to deselect when element is movedFrom them */
+ this.listenedTrees.push(tree);
+ },
+
+
+ unlistenTree: function(tree) {
+
+ dojo.event.topic.unsubscribe(tree.eventNames.titleClick, this, "select");
+ dojo.event.topic.unsubscribe(tree.eventNames.iconClick, this, "select");
+ dojo.event.topic.unsubscribe(tree.eventNames.collapse, this, "onCollapse");
+ dojo.event.topic.unsubscribe(tree.eventNames.moveFrom, this, "onMoveFrom");
+ dojo.event.topic.unsubscribe(tree.eventNames.removeNode, this, "onRemoveNode");
+ dojo.event.topic.unsubscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy");
+
+
+ for(var i=0; i<this.listenedTrees.length; i++){
+ if(this.listenedTrees[i] === tree){
+ this.listenedTrees.splice(i, 1);
+ break;
+ }
+ }
+ },
+
+
+ onTreeDestroy: function(message) {
+
+ this.unlistenTree(message.source);
+
+ if (this.dieWithTree) {
+ //dojo.debug("Killing myself "+this.widgetId);
+ this.destroy();
+ //dojo.debug("done");
+ }
+ },
+
+
+ // deselect node if parent is collapsed
+ onCollapse: function(message) {
+ if (!this.selectedNode) return;
+
+ var node = message.source;
+ var parent = this.selectedNode.parent;
+ while (parent !== node && parent.isTreeNode) {
+ parent = parent.parent;
+ }
+ if (parent.isTreeNode) {
+ this.deselect();
+ }
+ },
+
+
+
+ select: function(message) {
+ var node = message.source;
+ var e = message.event;
+
+ if (this.selectedNode === node) {
+ if(e.ctrlKey || e.shiftKey || e.metaKey){
+ // If the node is currently selected, and they select it again while holding
+ // down a meta key, it deselects it
+ this.deselect();
+ return;
+ }
+ dojo.event.topic.publish(this.eventNames.dblselect, { node: node });
+ return;
+ }
+
+ if (this.selectedNode) {
+ this.deselect();
+ }
+
+ this.doSelect(node);
+
+ dojo.event.topic.publish(this.eventNames.select, {node: node} );
+ },
+
+ /**
+ * Deselect node if target tree is out of our concern
+ */
+ onMoveFrom: function(message) {
+ if (message.child !== this.selectedNode) {
+ return;
+ }
+
+ if (!dojo.lang.inArray(this.listenedTrees, message.newTree)) {
+ this.deselect();
+ }
+ },
+
+ onRemoveNode: function(message) {
+ if (message.child !== this.selectedNode) {
+ return;
+ }
+
+ this.deselect();
+ },
+
+ doSelect: function(node){
+
+ node.markSelected();
+
+ this.selectedNode = node;
+ },
+
+ deselect: function(){
+
+ var node = this.selectedNode;
+
+ this.selectedNode = null;
+ node.unMarkSelected();
+ dojo.event.topic.publish(this.eventNames.deselect, {node: node} );
+
+ }
+
+});
+
+
+
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeSelector.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeSelectorV3.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeSelectorV3.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeSelectorV3.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeSelectorV3.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,245 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+
+dojo.provide("dojo.widget.TreeSelectorV3");
+
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.TreeCommon");
+
+dojo.widget.defineWidget(
+ "dojo.widget.TreeSelectorV3",
+ [dojo.widget.HtmlWidget, dojo.widget.TreeCommon],
+ function() {
+ this.eventNames = {};
+ this.listenedTrees = {};
+ this.selectedNodes = [];
+ },
+{
+ // TODO: add multiselect
+
+ listenTreeEvents: ["afterTreeCreate","afterCollapse","afterChangeTree", "afterDetach", "beforeTreeDestroy"],
+ listenNodeFilter: function(elem) { return elem instanceof dojo.widget.Widget},
+
+ allowedMulti: true,
+
+ eventNamesDefault: {
+ select : "select",
+ deselect : "deselect",
+ dblselect: "dblselect" // select already selected node.. Edit or whatever
+ },
+
+ onAfterTreeCreate: function(message) {
+ var tree = message.source;
+ dojo.event.browser.addListener(tree.domNode, "onclick", dojo.lang.hitch(this, this.onTreeClick));
+ if (dojo.render.html.ie) {
+ dojo.event.browser.addListener(tree.domNode, "ondblclick", dojo.lang.hitch(this, this.onTreeDblClick));
+ }
+ dojo.event.browser.addListener(tree.domNode, "onKey", dojo.lang.hitch(this, this.onKey));
+
+ },
+
+
+ onKey: function(e) {
+ if (!e.key || e.ctrkKey || e.altKey) { return; }
+
+ switch(e.key) {
+ case e.KEY_ENTER:
+ var node = this.domElement2TreeNode(e.target);
+ if (node) {
+ this.processNode(node, e);
+ }
+
+ }
+ },
+
+
+
+ onAfterChangeTree: function(message) {
+
+ if (!message.oldTree && message.node.selected) {
+ this.select(message.node);
+ }
+
+ if (!message.newTree || !this.listenedTrees[message.newTree.widgetId]) {
+ // moving from our trfee to new one that we don't listen
+
+ if (this.selectedNode && message.node.children) {
+ this.deselectIfAncestorMatch(message.node);
+ }
+
+ }
+
+
+ },
+
+
+
+ initialize: function(args) {
+
+ for(name in this.eventNamesDefault) {
+ if (dojo.lang.isUndefined(this.eventNames[name])) {
+ this.eventNames[name] = this.widgetId+"/"+this.eventNamesDefault[name];
+ }
+ }
+
+ },
+
+ onBeforeTreeDestroy: function(message) {
+ this.unlistenTree(message.source);
+ },
+
+ // deselect node if ancestor is collapsed
+ onAfterCollapse: function(message) {
+ this.deselectIfAncestorMatch(message.source);
+ },
+
+ // IE will throw select -> dblselect. Need to transform to select->select
+ onTreeDblClick: function(event) {
+ this.onTreeClick(event);
+ },
+
+ checkSpecialEvent: function(event) {
+ return event.shiftKey || event.ctrlKey;
+ },
+
+
+ onTreeClick: function(event) {
+ var node = this.domElement2TreeNode(event.target);
+ if (node) {
+ this.processNode(node, event);
+ }
+ },
+
+
+ /**
+ * press on selected with ctrl => deselect it
+ * press on selected w/o ctrl => dblselect it and deselect all other
+ *
+ * press on unselected with ctrl => add it to selection
+ *
+ * event may be both mouse & keyboard enter
+ */
+ processNode: function(node, event) {
+ if (node.actionIsDisabled(node.actions.SELECT)) {
+ return;
+ }
+
+ //dojo.debug("click "+node+ "special "+this.checkSpecialEvent(event));
+ //dojo.html.setClass(event.target, "TreeLabel TreeNodeEmphased");
+
+ if (dojo.lang.inArray(this.selectedNodes, node)) {
+ if(this.checkSpecialEvent(event)){
+ // If the node is currently selected, and they select it again while holding
+ // down a meta key, it deselects it
+ this.deselect(node);
+ return;
+ }
+
+ var _this = this;
+ var i=0;
+ var selectedNode;
+ while(this.selectedNodes.length > i) {
+ selectedNode = this.selectedNodes[i];
+ if (selectedNode !== node) {
+ //dojo.debug("Deselect "+selectedNode);
+ _this.deselect(selectedNode);
+ continue;
+ }
+
+ i++; // skip the doubleclicked node
+ }
+
+
+ dojo.event.topic.publish(this.eventNames.dblselect, { node: node });
+ return;
+ }
+
+ // if unselected node..
+
+
+ // deselect all if no meta key or disallowed
+ if (!this.checkSpecialEvent(event) || !this.allowedMulti) {
+ //dojo.debug("deselect All");
+ this.deselectAll();
+ }
+
+ //dojo.debug("select");
+
+ this.select(node);
+
+ },
+
+
+ deselectIfAncestorMatch: function(ancestor) {
+ /* deselect all nodes with this ancestor */
+ var _this = this;
+ dojo.lang.forEach(this.selectedNodes, function(node) {
+ var selectedNode = node;
+ while (node && node.isTreeNode) {
+ if (node === ancestor) {
+ _this.deselect(selectedNode);
+ return;
+ }
+ node = node.parent;
+ }
+ });
+ },
+
+
+
+
+ onAfterDetach: function(message) {
+ this.deselectIfAncestorMatch(message.child);
+ },
+
+
+ select: function(node) {
+
+ var index = dojo.lang.find(this.selectedNodes, node, true);
+
+ if (index >=0 ) {
+ return; // already selected
+ }
+
+ //dojo.debug("select "+node);
+ this.selectedNodes.push(node);
+
+ dojo.event.topic.publish(this.eventNames.select, {node: node} );
+ },
+
+
+ deselect: function(node){
+ var index = dojo.lang.find(this.selectedNodes, node, true);
+ if (index < 0) {
+ //dojo.debug("not selected");
+ return; // not selected
+ }
+
+ //dojo.debug("deselect "+node);
+ //dojo.debug((new Error()).stack);
+
+ this.selectedNodes.splice(index, 1);
+ dojo.event.topic.publish(this.eventNames.deselect, {node: node} );
+ //dojo.debug("deselect");
+
+ },
+
+ deselectAll: function() {
+ //dojo.debug("deselect all "+this.selectedNodes);
+ while (this.selectedNodes.length) {
+ this.deselect(this.selectedNodes[0]);
+ }
+ }
+
+});
+
+
+
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeSelectorV3.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeTimeoutIterator.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeTimeoutIterator.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeTimeoutIterator.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeTimeoutIterator.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,169 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+
+dojo.provide("dojo.widget.TreeTimeoutIterator");
+
+
+dojo.require("dojo.event.*");
+dojo.require("dojo.json")
+dojo.require("dojo.io.*");
+dojo.require("dojo.widget.TreeCommon");
+
+
+/**
+ * Iterates the tree processNext
+ * filterFunc/filterObj called to determine if I need to pass the node
+ *
+ * callFunc/callObj called to process the node
+ * callObj.callFunc(elem, iterator) should call iterator.forward() to go on
+ * callFunc may change elem to another object (e.g create widget from it),
+ * keeping its parent and parent position are untouched *
+ *
+ * finishFunc/finishObj called at the end
+ *
+ * TODO: it should work only sync-way to solve CPU-hungry tasks
+ */
+ dojo.declare(
+ "dojo.widget.TreeTimeoutIterator",
+ null,
+
+function(elem, callFunc, callObj) {
+ var _this = this;
+
+ this.currentParent = elem;
+
+ this.callFunc = callFunc;
+ this.callObj = callObj ? callObj: this;
+ this.stack = [];
+},
+
+{
+ // public
+ maxStackDepth: Number.POSITIVE_INFINITY,
+
+ stack: null,
+ currentParent: null,
+
+ currentIndex: 0,
+
+ filterFunc: function() { return true },
+
+ finishFunc: function() { return true },
+
+
+ setFilter: function(func, obj) {
+ this.filterFunc = func;
+ this.filterObj = obj;
+ },
+
+
+ setMaxLevel: function(level) {
+ this.maxStackDepth = level-2;
+ },
+
+ forward: function(timeout) {
+ var _this = this;
+
+ if (this.timeout) { // if timeout required between forwards
+ // tid will be assigned at the end of outer func execution
+ var tid = setTimeout(function() {_this.processNext(); clearTimeout(tid); }, _this.timeout);
+ } else {
+ return this.processNext();
+ }
+ },
+
+ start: function(processFirst) {
+ if (processFirst) {
+ return this.callFunc.call(this.callObj, this.currentParent, this);
+ }
+
+ return this.processNext();
+ },
+
+ /**
+ * @private
+ * find next node, move current parent to it if possible & process
+ */
+ processNext: function() {
+
+ //dojo.debug("processNext with currentParent "+this.currentParent+" index "+this.currentIndex);
+ var handler;
+
+ var _this = this;
+
+ var found;
+
+ var next;
+
+ if (this.maxStackDepth == -2) {
+ return; // process only first cause level=0, do not process children
+ }
+
+ while (true) {
+ var children = this.currentParent.children;
+
+ if (children && children.length) {
+
+ // look for a node that can be the next target
+ do {
+ next = children[this.currentIndex];
+ //dojo.debug("check "+next);
+ } while (this.currentIndex++ < children.length && !(found = this.filterFunc.call(this.filterObj,next)));
+
+
+ if (found) {
+ //dojo.debug("found "+next);
+ // move to next node as new parent if depth is fine
+ // I can't check current children to decide whether to move it or not,
+ // because expand may populate children
+ if (next.isFolder && this.stack.length <= this.maxStackDepth) {
+ this.moveParent(next,0);
+ }
+ //dojo.debug("Run callFunc on "+next);
+ return this.callFunc.call(this.callObj, next, this);
+ }
+ }
+
+ if (this.stack.length) {
+ this.popParent();
+ continue;
+ }
+
+ break;
+ }
+
+ /**
+ * couldn't find next node to process, finish here
+ */
+ return this.finishFunc.call(this.finishObj);
+
+ },
+
+ setFinish: function(func, obj) {
+ this.finishFunc = func;
+ this.finishObj = obj;
+ },
+
+ popParent: function() {
+ var p = this.stack.pop();
+ //dojo.debug("Pop "+p[0]+":"+p[1]);
+ this.currentParent = p[0];
+ this.currentIndex = p[1];
+ },
+
+ moveParent: function(nextParent, nextIndex) {
+ //dojo.debug("Move from "+this.currentParent+":"+this.currentIndex+" to "+nextParent+":"+nextIndex);
+ this.stack.push([this.currentParent, this.currentIndex]);
+ this.currentParent = nextParent;
+ this.currentIndex = nextIndex;
+ }
+
+});
\ No newline at end of file
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeTimeoutIterator.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeV3.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeV3.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeV3.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeV3.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,343 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+/**
+ * Tree model does all the drawing, visual node management etc.
+ * Throws events about clicks on it, so someone may catch them and process
+ * Tree knows nothing about DnD stuff, covered in TreeDragAndDrop and (if enabled) attached by controller
+*/
+
+/**
+ * TODO: use domNode.cloneNode instead of createElement for grid
+ * Should be faster (lyxsus)
+ */
+dojo.provide("dojo.widget.TreeV3");
+
+dojo.require("dojo.widget.TreeWithNode");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.event.*");
+dojo.require("dojo.io.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.TreeNodeV3");
+
+dojo.widget.defineWidget(
+ "dojo.widget.TreeV3",
+ [dojo.widget.HtmlWidget, dojo.widget.TreeWithNode],
+ function() {
+ this.eventNames = {};
+
+ this.DndAcceptTypes = [];
+ this.actionsDisabled = [];
+
+ this.listeners = [];
+
+ this.tree = this;
+ },
+{
+ DndMode: "",
+
+ /**
+ * factory to generate default widgets
+ */
+ defaultChildWidget: null,
+
+ defaultChildTitle: "New Node", // for editing
+
+
+ eagerWidgetInstantiation: false,
+
+ eventNamesDefault: {
+
+ // tree created.. Perform tree-wide actions if needed
+ afterTreeCreate: "afterTreeCreate",
+ beforeTreeDestroy: "beforeTreeDestroy",
+ /* can't name it "beforeDestroy", because such name causes memleaks in IE */
+ beforeNodeDestroy: "beforeNodeDestroy",
+ afterChangeTree: "afterChangeTree",
+
+ afterSetFolder: "afterSetFolder",
+ afterUnsetFolder: "afterUnsetFolder",
+ beforeMoveFrom: "beforeMoveFrom",
+ beforeMoveTo: "beforeMoveTo",
+ afterMoveFrom: "afterMoveFrom",
+ afterMoveTo: "afterMoveTo",
+ afterAddChild: "afterAddChild",
+ afterDetach: "afterDetach",
+ afterExpand: "afterExpand",
+ afterSetTitle: "afterSetTitle",
+ afterCollapse: "afterCollapse"
+ },
+
+ classPrefix: "Tree",
+
+ style: "",
+
+ /**
+ * is it possible to add a new child to leaf ?
+ */
+ allowAddChildToLeaf: true,
+
+ /**
+ * when last children is removed from node should it stop being a "folder" ?
+ */
+ unsetFolderOnEmpty: true,
+
+
+ DndModes: {
+ BETWEEN: 1,
+ ONTO: 2
+ },
+
+ DndAcceptTypes: "",
+
+ // will have cssRoot before it
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/TreeV3.css"),
+
+ templateString: '<div style="${this.style}">\n</div>',
+
+ isExpanded: true, // consider this "root node" to be always expanded
+
+ isTree: true,
+
+
+
+ createNode: function(data) {
+
+ data.tree = this.widgetId;
+
+ if (data.widgetName) {
+ // TODO: check if such widget has createSimple
+ return dojo.widget.createWidget(data.widgetName, data);
+ } else if (this.defaultChildWidget.prototype.createSimple) {
+ return this.defaultChildWidget.prototype.createSimple(data);
+ } else {
+ var ns = this.defaultChildWidget.prototype["namespace"];
+ var wt = this.defaultChildWidget.prototype.widgetType;
+
+ return dojo.widget.createWidget(ns + ":" + wt, data);
+ }
+
+ },
+
+
+ // expandNode has +- CSS background. Not img.src for performance, background src string resides in single place.
+ // selection in KHTML/Mozilla disabled treewide, IE requires unselectable for every node
+ // you can add unselectable if you want both in postCreate of tree and in this template
+
+ // create new template and put into prototype
+ makeNodeTemplate: function() {
+
+ var domNode = document.createElement("div");
+ dojo.html.setClass(domNode, this.classPrefix+"Node "+this.classPrefix+"ExpandLeaf "+this.classPrefix+"ChildrenNo");
+ this.nodeTemplate = domNode;
+
+ var expandNode = document.createElement("div");
+ var clazz = this.classPrefix+"Expand";
+ if (dojo.render.html.ie) {
+ clazz = clazz + ' ' + this.classPrefix+"IEExpand";
+ }
+ dojo.html.setClass(expandNode, clazz);
+
+ this.expandNodeTemplate = expandNode;
+
+ // need <span> inside <div>
+ // div for multiline support, span for styling exactly the text, not whole line
+ var labelNode = document.createElement("span");
+ dojo.html.setClass(labelNode, this.classPrefix+"Label");
+ this.labelNodeTemplate = labelNode;
+
+ var contentNode = document.createElement("div");
+ var clazz = this.classPrefix+"Content";
+
+ /**
+ * IE does not support min-height properly so I have to rely
+ * on this hack
+ * FIXME: do it in CSS only, remove iconHeight from code
+ */
+ if (dojo.render.html.ie) {
+ clazz = clazz + ' ' + this.classPrefix+"IEContent";
+ }
+
+
+ dojo.html.setClass(contentNode, clazz);
+
+ this.contentNodeTemplate = contentNode;
+
+ domNode.appendChild(expandNode);
+ domNode.appendChild(contentNode);
+ contentNode.appendChild(labelNode);
+
+
+ },
+
+ makeContainerNodeTemplate: function() {
+
+ var div = document.createElement('div');
+ div.style.display = 'none';
+ dojo.html.setClass(div, this.classPrefix+"Container");
+
+ this.containerNodeTemplate = div;
+
+ },
+
+
+ actions: {
+ ADDCHILD: "ADDCHILD"
+ },
+
+
+ getInfo: function() {
+ var info = {
+ widgetId: this.widgetId,
+ objectId: this.objectId
+ }
+
+ return info;
+ },
+
+ adjustEventNames: function() {
+
+ for(var name in this.eventNamesDefault) {
+ if (dojo.lang.isUndefined(this.eventNames[name])) {
+ this.eventNames[name] = this.widgetId+"/"+this.eventNamesDefault[name];
+ }
+ }
+ },
+
+
+ adjustDndMode: function() {
+ var _this = this;
+
+
+ var DndMode = 0;
+ dojo.lang.forEach(this.DndMode.split(';'),
+ function(elem) {
+ var mode = _this.DndModes[dojo.string.trim(elem).toUpperCase()];
+ if (mode) DndMode = DndMode | mode;
+ }
+ );
+
+
+ this.DndMode = DndMode;
+
+ },
+
+ /**
+ * publish destruction event so that any listeners should stop listening
+ */
+ destroy: function() {
+ dojo.event.topic.publish(this.tree.eventNames.beforeTreeDestroy, { source: this } );
+
+ return dojo.widget.HtmlWidget.prototype.destroy.apply(this, arguments);
+ },
+
+ initialize: function(args){
+
+ this.domNode.widgetId = this.widgetId;
+
+ for(var i=0; i<this.actionsDisabled.length;i++) {
+ this.actionsDisabled[i] = this.actionsDisabled[i].toUpperCase();
+ }
+
+ //dojo.debug(args.defaultChildWidget ? true : false)
+
+ if (!args.defaultChildWidget) {
+ this.defaultChildWidget = dojo.widget.TreeNodeV3;
+ } else {
+ this.defaultChildWidget = dojo.lang.getObjPathValue(args.defaultChildWidget);
+ }
+
+ this.adjustEventNames();
+ this.adjustDndMode();
+
+ this.makeNodeTemplate();
+ this.makeContainerNodeTemplate();
+
+ this.containerNode = this.domNode;
+
+ dojo.html.setClass(this.domNode, this.classPrefix+"Container");
+
+ var _this = this;
+
+
+
+ dojo.lang.forEach(this.listeners,
+ function(elem) {
+ var t = dojo.lang.isString(elem) ? dojo.widget.byId(elem) : elem;
+ t.listenTree(_this)
+ }
+ );
+
+
+
+ },
+
+
+ postCreate: function() {
+ dojo.event.topic.publish(this.eventNames.afterTreeCreate, { source: this } );
+ },
+
+
+ /**
+ * Move child to newParent as last child
+ * redraw tree and update icons.
+ *
+ * Called by target, saves source in event.
+ * events are published for BOTH trees AFTER update.
+ */
+ move: function(child, newParent, index) {
+
+ if (!child.parent) {
+ dojo.raise(this.widgetType+": child can be moved only while it's attached");
+ }
+
+ var oldParent = child.parent;
+ var oldTree = child.tree;
+ var oldIndex = child.getParentIndex();
+ var newTree = newParent.tree;
+ var newParent = newParent;
+ var newIndex = index;
+
+ var message = {
+ oldParent: oldParent, oldTree: oldTree, oldIndex: oldIndex,
+ newParent: newParent, newTree: newTree, newIndex: newIndex,
+ child: child
+ };
+
+ dojo.event.topic.publish(oldTree.eventNames.beforeMoveFrom, message);
+ dojo.event.topic.publish(newTree.eventNames.beforeMoveTo, message);
+
+ this.doMove.apply(this, arguments);
+
+
+ /* publish events here about structural changes for both source and target trees */
+ dojo.event.topic.publish(oldTree.eventNames.afterMoveFrom, message);
+ dojo.event.topic.publish(newTree.eventNames.afterMoveTo, message);
+
+ },
+
+
+ /* do actual parent change here. Write remove child first */
+ doMove: function(child, newParent, index) {
+ //dojo.debug("MOVE "+child+" to "+newParent+" at "+index);
+
+ //var parent = child.parent;
+ child.doDetach();
+
+ //dojo.debug("addChild "+child+" to "+newParent+" at "+index);
+
+ newParent.doAddChild(child, index);
+ },
+
+ toString: function() {
+ return "["+this.widgetType+" ID:"+this.widgetId +"]"
+ }
+
+});
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeV3.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeWithNode.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeWithNode.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeWithNode.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeWithNode.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,271 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+
+dojo.require("dojo.lang.declare");
+dojo.provide("dojo.widget.TreeWithNode");
+
+dojo.declare(
+ "dojo.widget.TreeWithNode",
+ null,
+ function(){ },
+{
+ /*
+ * dynamic loading-related stuff.
+ * When an empty folder node appears, it is "UNCHECKED" first,
+ * then after Rpc call it becomes LOADING and, finally LOADED
+ *
+ * tree may be dynamically loaded also
+ */
+ loadStates: {
+ UNCHECKED: "UNCHECKED",
+ LOADING: "LOADING",
+ LOADED: "LOADED"
+ },
+
+ state: "UNCHECKED", // after creation will change to loadStates: "loaded/loading/unchecked"
+
+
+ objectId: "", // the widget represents an object
+
+
+ // I need this to parse children
+ isContainer: true,
+
+ lockLevel: 0, // lock ++ unlock --, so nested locking works fine
+
+ lock: function() {
+ this.lockLevel++;
+ },
+ unlock: function() {
+ if (!this.lockLevel) {
+ //dojo.debug((new Error()).stack);
+ dojo.raise(this.widgetType+" unlock: not locked");
+ }
+ this.lockLevel--;
+ },
+
+
+ expandLevel: "", // expand to level automatically
+ loadLevel: "", // load to level automatically
+
+ hasLock: function() {
+ return this.lockLevel>0;
+ },
+
+ isLocked: function() {
+ var node = this;
+ while (true) {
+ if (node.lockLevel) {
+ return true;
+ }
+ if (!node.parent || node.isTree) {
+ break;
+ }
+
+ node = node.parent;
+
+ }
+
+ return false;
+ },
+
+
+ flushLock: function() {
+ this.lockLevel = 0;
+ //this.unMarkLoading();
+ },
+
+
+ actionIsDisabled: function(action) {
+ var disabled = false;
+
+ if (dojo.lang.inArray(this.actionsDisabled, action)) {
+ disabled = true;
+ }
+
+
+ //dojo.debug("Check "+this+" "+disabled)
+
+
+ if (this.isTreeNode) {
+ if (!this.tree.allowAddChildToLeaf && action == this.actions.ADDCHILD && !this.isFolder) {
+ disabled = true;
+ }
+ }
+ return disabled;
+ },
+
+ actionIsDisabledNow: function(action) {
+ return this.actionIsDisabled(action) || this.isLocked();
+ },
+
+
+ /**
+ * childrenArray is array of Widgets or array of Objects
+ * widgets may be both attached and detached
+ *
+ * Use Cases
+ * 1) lots of widgets are packed and passed in.
+ * - widgets are created
+ * - widgets have no parent (detached or not attached yet)
+ *
+ * 2) array of widgets and data objects passed in with flag makeWidgetsFromChildren
+ * - some widgets are not created
+ * - all objects have no parent
+ *
+ * 3) expand is called with makeWidgetsFromChildren=true
+ * - some objects need to be turned into widgets
+ * - some widgets have parent (e.g markup), some widgets and objects do not
+ *
+ * Will folderize a node as side-effect.
+ */
+ setChildren: function(childrenArray) {
+ //dojo.profile.start("setChildren "+this);
+ //dojo.debug("setChildren in "+this);
+
+
+ if (this.isTreeNode && !this.isFolder) {
+ //dojo.debug("folder parent "+parent+ " isfolder "+parent.isFolder);
+ this.setFolder();
+ } else if (this.isTreeNode) {
+ this.state = this.loadStates.LOADED;
+ }
+
+ var hadChildren = this.children.length > 0;
+
+ if (childrenArray) {
+ this.children = childrenArray;
+ }
+
+
+
+ var hasChildren = this.children.length > 0;
+ if (this.isTreeNode && hasChildren != hadChildren) {
+ // call only when hasChildren state changes
+ this.viewSetHasChildren();
+ }
+
+
+
+ for(var i=0; i<this.children.length; i++) {
+ var child = this.children[i];
+
+ //dojo.profile.start("setChildren - create "+this);
+
+ if (!(child instanceof dojo.widget.Widget)) {
+
+ child = this.children[i] = this.tree.createNode(child);
+ var childWidgetCreated = true;
+ //dojo.debugShallow(child)
+
+ //dojo.debug("setChildren creates node "+child);
+ } else {
+ var childWidgetCreated = false;
+ }
+
+ //dojo.profile.end("setChildren - create "+this);
+
+ //dojo.profile.start("setChildren - attach "+this);
+
+ if (!child.parent) { // detached child
+
+ //dojo.debug("detached child "+child);
+
+ child.parent = this;
+
+ //dojo.profile.start("setChildren - updateTree "+this);
+
+ if (this.tree !== child.tree) {
+ child.updateTree(this.tree);
+ }
+ //dojo.profile.end("setChildren - updateTree "+this);
+
+
+ //dojo.debug("Add layout for "+child);
+ child.viewAddLayout();
+ this.containerNode.appendChild(child.domNode);
+
+ var message = {
+ child: child,
+ index: i,
+ parent: this,
+ childWidgetCreated: childWidgetCreated
+ }
+
+ delete dojo.widget.manager.topWidgets[child.widgetId];
+
+
+ //dojo.profile.start("setChildren - event "+this);
+ //dojo.debug("publish "+this.tree.eventNames.afterAddChild)
+ dojo.event.topic.publish(this.tree.eventNames.afterAddChild, message);
+
+ //dojo.profile.end("setChildren - event "+this);
+
+ }
+
+ if (this.tree.eagerWidgetInstantiation) {
+ dojo.lang.forEach(this.children, function(child) {
+ child.setChildren();
+ });
+ }
+
+ //dojo.profile.end("setChildren - attach "+this);
+
+
+ }
+
+
+
+ //dojo.profile.end("setChildren "+this);
+
+ },
+
+
+ doAddChild: function(child, index) {
+ return this.addChild(child, index, true);
+ },
+
+ addChild: function(child, index, dontPublishEvent) {
+ if (dojo.lang.isUndefined(index)) {
+ index = this.children.length;
+ }
+
+ //dojo.debug("doAddChild "+index+" called for "+this+" child "+child+" existing children "+(this.children.length ? this.children : "<no children>"));
+
+ if (!child.isTreeNode){
+ dojo.raise("You can only add TreeNode widgets to a "+this.widgetType+" widget!");
+ return;
+ }
+
+ this.children.splice(index, 0, child);
+ child.parent = this;
+
+ child.addedTo(this, index, dontPublishEvent);
+
+ // taken from DomWidget.registerChild
+ // delete from widget list that are notified on resize etc (no parent)
+ delete dojo.widget.manager.topWidgets[child.widgetId];
+
+ },
+
+ /**
+ * does not inform children about resize (skips onShow),
+ * because on large trees that's slow
+ */
+ onShow: function() {
+ this.animationInProgress=false;
+ },
+
+ onHide: function() {
+ this.animationInProgress=false;
+ }
+
+});
Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/TreeWithNode.js
------------------------------------------------------------------------------
svn:eol-style = native