[Dojo-checkins] ilia - r3460 - in trunk: src/widget tests/widget/tree

dojo-checkins-admin at dojotoolkit.org dojo-checkins-admin at dojotoolkit.org
Fri Apr 7 05:07:27 MDT 2006


Author: ilia
Date: Fri Apr  7 05:07:27 2006
New Revision: 3460

Added:
   trunk/tests/widget/tree/test_Tree_5_1.html
Modified:
   trunk/src/widget/Tree.js
   trunk/src/widget/TreeBasicController.js
   trunk/src/widget/TreeLoadingController.js
   trunk/src/widget/TreeNode.js
   trunk/src/widget/TreeRPCController.js
Log:
 * added nested locking (alpha)
 * runRPC added 
 * callFunc, callObj order changed to callObj, callFunc

Modified: trunk/src/widget/Tree.js
==============================================================================
--- trunk/src/widget/Tree.js	(original)
+++ trunk/src/widget/Tree.js	Fri Apr  7 05:07:27 2006
@@ -63,6 +63,8 @@
 
 	DNDMode: "off",
 
+	lockLevel: 0, // lock ++ unlock --, so nested locking works fine
+
 	strictFolders: true,
 
 	DNDModes: {
@@ -506,8 +508,30 @@
 		child.parent = child.tree = null;
 
 		return child;
-	}
+	},
 
+	markLoading: function() {
+		// no way to mark tree loading
+	},
+
+	unMarkLoading: function() {
+		// no way to show that tree finished loading
+	},
+
+
+	lock: function() {
+		!this.lockLevel && this.markLoading();		
+		this.lockLevel++;		
+	},
+	unlock: function() {
+		this.lockLevel--;
+		!this.lockLevel && this.unMarkLoading();
+	},
+	isLocked: function() { return this.lockLevel > 0; },
+	flushLock: function() {
+		this.lockLevel = 0;
+		this.unMarkLoading();
+	}
 });
 
 

Modified: trunk/src/widget/TreeBasicController.js
==============================================================================
--- trunk/src/widget/TreeBasicController.js	(original)
+++ trunk/src/widget/TreeBasicController.js	Fri Apr  7 05:07:27 2006
@@ -216,16 +216,16 @@
 	},
 
 
-	removeNode: function(node, callFunc, callObj) {
+	removeNode: function(node, callObj, callFunc) {
 		if (!this.canRemoveNode(node)) {
 			return false;
 		}
 
-		return this.doRemoveNode(node, callFunc, callObj);
+		return this.doRemoveNode(node, callObj, callFunc);
 	},
 
 
-	doRemoveNode: function(node, callFunc, callObj) {
+	doRemoveNode: function(node, callObj, callFunc) {
 		node.tree.removeNode(node);
 
 		if (callFunc) {
@@ -249,7 +249,7 @@
 	/* send data to server and add child from server */
 	/* data may contain an almost ready child, or anything else, suggested to server */
 	/*in RPC controllers server responds with child data to be inserted */
-	createChild: function(parent, index, data, callFunc, callObj) {
+	createChild: function(parent, index, data, callObj, callFunc) {
 		if (!this.canCreateChild(parent, index, data)) {
 			return false;
 		}
@@ -257,7 +257,7 @@
 		return this.doCreateChild.apply(this, arguments);
 	},
 
-	doCreateChild: function(parent, index, data, callFunc, callObj) {
+	doCreateChild: function(parent, index, data, callObj, callFunc) {
 
 		var widgetType = data.widgetType ? data.widgetType : "TreeNode";
 

Modified: trunk/src/widget/TreeLoadingController.js
==============================================================================
--- trunk/src/widget/TreeLoadingController.js	(original)
+++ trunk/src/widget/TreeLoadingController.js	Fri Apr  7 05:07:27 2006
@@ -28,7 +28,7 @@
 	/**
 	 * Common RPC error handler (dies)
 	*/
-	RPCErrorHandler: function(type, obj) {
+	RPCErrorHandler: function(type, obj, evt) {
 		alert( "RPC Error: " + (obj.message||"no message"));
 	},
 
@@ -56,17 +56,19 @@
 	/**
 	 * Add all loaded nodes from array obj as node children and expand it
 	*/
-	loadProcessResponse: function(type, node, result, callFunc, callObj) {
+	loadProcessResponse: function(node, result, callObj, callFunc) {
 
 		if (!dojo.lang.isUndefined(result.error)) {
 			this.RPCErrorHandler("server", result.error);
 			return false;
 		}
+		
+		//dojo.debugShallow(result);
 
 		var newChildren = result;
 
 		if (!dojo.lang.isArray(newChildren)) {
-			dojo.raise('Not array loaded: '+newChildren);
+			dojo.raise('loadProcessResponse: Not array loaded: '+newChildren);
 		}
 
 		for(var i=0; i<newChildren.length; i++) {
@@ -80,6 +82,8 @@
 
 		node.state = node.loadStates.LOADED;
 
+		//dojo.debug(callFunc);
+
 		if (dojo.lang.isFunction(callFunc)) {
 			callFunc.apply(dojo.lang.isUndefined(callObj) ? this : callObj, [node, newChildren]);
 		}
@@ -90,39 +94,71 @@
 		return obj.getInfo();
 	},
 
+	runRPC: function(kw) {
+		var _this = this;
+		
+		var handle = function(type, data, evt) {
+			// unlock BEFORE any processing is done
+			// so errorHandler may apply locking			
+			if (kw.lock) {
+				dojo.lang.forEach(kw.lock,
+					function(t) { t.unlock() }
+				);
+			}
+			
+			if(type == "load"){				
+				kw.load.call(this, data);							
+			}else{
+				this.RPCErrorHandler(type, data, evt);
+			}
+			
+		}
+		
+		if (kw.lock) {
+			dojo.lang.forEach(kw.lock,
+				function(t) { t.lock() }
+			);
+		}
+		
+		
+		dojo.io.bind({
+			url: kw.url,
+			/* I hitch to get this.loadOkHandler */
+			handle: dojo.lang.hitch(this, handle),
+			mimetype: "text/json",
+			preventCache: true,
+			sync: kw.sync,
+			content: { data: dojo.json.serialize(kw.params) }
+		});
+	},
+
+		
+		
 	/**
 	 * Load children of the node from server
 	 * Synchroneous loading doesn't break control flow
 	 * I need sync mode for DnD
 	*/
-	loadRemote: function(node, sync, callFunc, callObj){
-		node.markLoading();
-
-
+	loadRemote: function(node, sync, callObj, callFunc){
+		var _this = this;
+		
 		var params = {
 			node: this.getInfo(node),
 			tree: this.getInfo(node.tree)
 		};
+		
+		//dojo.debug(callFunc)
 
-		var requestUrl = this.getRPCUrl('getChildren');
-		//dojo.debug(requestUrl)
-
-		dojo.io.bind({
-			url: requestUrl,
-			/* I hitch to get this.loadOkHandler */
-			load: dojo.lang.hitch(this,
-				function(type, result) {
-					this.loadProcessResponse(type, node, result, callFunc, callObj) ;
-				}
-			),
-			error: this.RPCErrorHandler,
-			mimetype: "text/json",
-			preventCache: true,
+		this.runRPC({
+			url: this.getRPCUrl('getChildren'),
+			load: function(result) {
+				_this.loadProcessResponse(node, result, callObj, callFunc) ;
+			},
 			sync: sync,
-			content: { data: dojo.json.serialize(params) }
+			lock: [node],
+			params: params
 		});
-
-
+			
 	},
 
 
@@ -131,6 +167,7 @@
 		if (node.state == node.loadStates.UNCHECKED && node.isFolder) {
 
 			this.loadRemote(node, sync,
+				this,
 				function(node, newChildren) {
 					this.expand(node, sync, callObj, callFunc);
 				}
@@ -155,7 +192,7 @@
 	},
 
 
-	doCreateChild: function(parent, index, data, callFunc, callObj) {
+	doCreateChild: function(parent, index, data, callObj, callFunc) {
 
 		/* load nodes into newParent in sync mode, if needed, first */
 		if (parent.state == parent.loadStates.UNCHECKED) {

Modified: trunk/src/widget/TreeNode.js
==============================================================================
--- trunk/src/widget/TreeNode.js	(original)
+++ trunk/src/widget/TreeNode.js	Fri Apr  7 05:07:27 2006
@@ -37,6 +37,8 @@
 	},
 
 	isContainer: true,
+	
+	lockLevel: 0, // lock ++ unlock --, so nested locking works fine
 
 
 	templateString: ('<div class="dojoTreeNode"> '
@@ -92,10 +94,37 @@
 		return this.getParentIndex() == this.parent.children.length-1 ? true : false;
 	},
 
+	lock: function(){ return this.tree.lock.apply(this, arguments) },
+	unlock: function(){ return this.tree.unlock.apply(this, arguments) },
+	isLocked: function(){ return this.tree.isLocked.apply(this, arguments) },
+	cleanLock: function(){ return this.tree.cleanLock.apply(this, arguments) },
+
 	actionIsDisabled: function(action) {
 		var _this = this;
-
-		return (this.tree.strictFolders && action == this.actions.ADDCHILD && !this.isFolder) || dojo.lang.inArray(_this.actionsDisabled, action);
+		
+		var disabled = false;
+		
+		if (this.tree.strictFolders &&action == this.actions.ADDCHILD && !this.isFolder) {
+			disabled = true;
+		}
+			
+		if (dojo.lang.inArray(_this.actionsDisabled, action)) {
+			disabled = true;
+		}
+		
+		var node = this;
+		while (true) {
+			if (node.isLocked()) {
+				disabled = true;
+				break;
+			}
+			if (node instanceof dojo.widget.Tree) {
+				break;
+			}
+			node = node.parent;
+		}
+		
+		return disabled;
 	},
 
 	getInfo: function() {
@@ -157,9 +186,24 @@
 
 
 	markLoading: function() {
+		this._markLoadingSavedIcon = this.expandIcon.src;
 		this.expandIcon.src = this.tree.expandIconSrcLoading;
 	},
 
+	// if icon is "Loading" then 	
+	unMarkLoading: function() {
+		if (!this._markLoadingSavedIcon) return;
+		
+		var im = new Image();
+		im.src = this.tree.expandIconSrcLoading;
+		
+		//dojo.debug("Unmark "+this.expandIcon.src+" : "+im.src);
+		if (this.expandIcon.src == im.src) {
+			this.expandIcon.src = this._markLoadingSavedIcon;
+		}
+		this._markLoadingSavedIcon = null;
+	},
+
 
 	setFolder: function() {
 		dojo.event.connect(this.expandIcon, 'onclick', this, 'onTreeClick');
@@ -257,8 +301,8 @@
 	},
 
 
-	unMarkSelected: function() {
-		//dojo.debug('unmark')
+	unMarkSelected: function() {		
+		//dojo.debug('unmark')		
 		dojo.html.removeClass(this.titleNode, 'dojoTreeNodeLabelSelected');
 	},
 

Modified: trunk/src/widget/TreeRPCController.js
==============================================================================
--- trunk/src/widget/TreeRPCController.js	(original)
+++ trunk/src/widget/TreeRPCController.js	Fri Apr  7 05:07:27 2006
@@ -47,26 +47,22 @@
 
 		var success;
 
-		dojo.io.bind({
+		this.runRPC({		
 			url: this.getRPCUrl('move'),
 			/* I hitch to get this.loadOkHandler */
-			load: dojo.lang.hitch(this,
-				function(type, response) {
-					success = this.doMoveProcessResponse(type, response, child, newParent, index) ;
-				}
-			),
-			error: this.RPCErrorHandler,
-			mimetype: "text/json",
-			preventCache: true,
+			load: function(response) {
+				success = this.doMoveProcessResponse(response, child, newParent, index) ;
+			},
 			sync: true,
-			content: { data: dojo.json.serialize(params) }
+			lock: [child, newParent],
+			params: params
 		});
 
 
 		return success;
 	},
 
-	doMoveProcessResponse: function(type, response, child, newParent, index) {
+	doMoveProcessResponse: function(response, child, newParent, index) {
 
 		if (!dojo.lang.isUndefined(response.error)) {
 			this.RPCErrorHandler("server", response.error);
@@ -79,29 +75,27 @@
 	},
 
 
-	doRemoveNode: function(node, callFunc, callObj) {
+	doRemoveNode: function(node, callObj, callFunc) {
 
 		var params = {
 			node: this.getInfo(node),
 			tree: this.getInfo(node.tree)
 		}
 
-		dojo.io.bind({
+		this.runRPC({
 				url: this.getRPCUrl('removeNode'),
 				/* I hitch to get this.loadOkHandler */
-				load: dojo.lang.hitch(this, function(type, response) {
-					this.doRemoveNodeProcessResponse(type, response, node, callFunc, callObj) }
-				),
-				error: this.RPCErrorHandler,
-				mimetype: "text/json",
-				preventCache: true,
-				content: {data: dojo.json.serialize(params) }
+				load: function(response) {
+					this.doRemoveNodeProcessResponse(response, node, callObj, callFunc) 
+				},
+				params: params,
+				lock: [node]
 		});
 
 	},
 
 
-	doRemoveNodeProcessResponse: function(type, response, node, callFunc, callObj) {
+	doRemoveNodeProcessResponse: function(response, node, callObj, callFunc) {
 		if (!dojo.lang.isUndefined(response.error)) {
 			this.RPCErrorHandler("server", response.error);
 			return false;
@@ -111,7 +105,7 @@
 
 		if (response == true) {
 			/* change parent succeeded */
-			var args = [ node, callFunc, callObj ];
+			var args = [ node, callObj, callFunc ];
 			dojo.widget.TreeLoadingController.prototype.doRemoveNode.apply(this, args);
 
 			return;
@@ -131,7 +125,7 @@
 	// -----------------------------------------------------------------------------
 
 
-	doCreateChild: function(parent, index, output, callFunc, callObj) {
+	doCreateChild: function(parent, index, output, callObj, callFunc) {
 
 			var params = {
 				tree: this.getInfo(parent.tree),
@@ -140,37 +134,31 @@
 				data: output
 			}
 
-			dojo.io.bind({
-					url: this.getRPCUrl('createChild'),
-					/* I hitch to get this.loadOkHandler */
-					load: dojo.lang.hitch(this, function(type, response) {
-						// suggested data is dead, fresh data from server is used
-						this.doCreateChildProcessResponse(type, response, parent, index, callFunc, callObj) }
-					),
-					error: this.RPCErrorHandler,
-					mimetype: "text/json",
-					preventCache: true,
-					content: {data: dojo.json.serialize(params) }
+			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(type, response, parent, index, callFunc, callObj) {
+	doCreateChildProcessResponse: function(response, parent, index, callObj, callFunc) {
 
 		if (!dojo.lang.isUndefined(response.error)) {
 			this.RPCErrorHandler("server",response.error);
 			return false;
 		}
 
-		if (!parent.isTreeNode) {
-			dojo.raise("Can only add children to TreeNode")
-		}
-
 		if (!dojo.lang.isObject(response)) {
 			dojo.raise("Invalid result "+response)
 		}
 
-		var args = [parent, index, response, callFunc, callObj];
+		var args = [parent, index, response, callObj, callFunc];
+		
 		dojo.widget.TreeLoadingController.prototype.doCreateChild.apply(this, args);
 
 	}

Added: trunk/tests/widget/tree/test_Tree_5_1.html
==============================================================================
--- (empty file)
+++ trunk/tests/widget/tree/test_Tree_5_1.html	Fri Apr  7 05:07:27 2006
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+<script type="text/javascript">
+	var djConfig = {isDebug: true, debugAtAllCosts: true };
+</script>
+<script type="text/javascript" src="../../../dojo.js"></script>
+<script type="text/javascript">
+	dojo.require("dojo.lang.*");
+	dojo.require("dojo.widget.*");
+	dojo.require("dojo.widget.Tree");
+	dojo.require("dojo.widget.TreeLoadingController");
+	dojo.hostenv.writeIncludes();
+</script>
+
+
+</head>
+<body>
+
+<ul>
+<li>New nodes are loaded dynamically.
+<li>Tree is expanded to level 1, some nodes are autoexpanded also.
+<li>DND is working in between mode.
+</ul>
+
+<div dojoType="TreeLoadingController" RPCUrl="local" widgetId="treeController" DNDcontroller="create"></div>
+
+
+
+<div dojoType="Tree" expandLevel="1" widgetId="firstTree" controller="treeController" DNDMode="between" DNDAcceptTypes="firstTree">
+    <div dojoType="TreeNode" title="folder" isFolder="true">
+    </div>
+
+</div>
+
+
+
+</body>
+</html>


More information about the Dojo-checkins mailing list