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/06/10 16:27:54 UTC

svn commit: r413306 [13/17] - in /tapestry/tapestry4/trunk: examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/ framework/src/java/org/apache/tapestry/ framework/src/java/org/apache/tapestry/dojo/form/ framework/src/java/org/apache/tape...

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/SvgButton.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/SvgButton.js?rev=413306&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/SvgButton.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/SvgButton.js Sat Jun 10 07:27:44 2006
@@ -0,0 +1,141 @@
+/*
+	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
+*/
+
+// FIXME: not yet functional
+
+dojo.provide("dojo.widget.SvgButton");
+
+dojo.require("dojo.widget.Button");
+
+dojo.widget.SvgButton = function(){
+	// FIXME: this is incomplete and doesn't work yet
+	// if DOMButton turns into a mixin, we should subclass Button instead and
+	// just mix in the DOMButton properties.
+
+	dojo.widget.DomButton.call(this);
+	dojo.widget.SvgWidget.call(this);
+
+	// FIXME: freaking implement this already!
+	this.onFoo = function(){ alert("bar"); }
+
+	this.label = "huzzah!";
+
+	this.setLabel = function(x, y, textSize, label, shape){
+		//var labelNode = this.domNode.ownerDocument.createTextNode(this.label);
+		//var textNode = this.domNode.ownerDocument.createElement("text");
+		var coords = dojo.widget.SvgButton.prototype.coordinates(x, y, textSize, label, shape);
+		var textString = "";
+		switch(shape) {
+			case "ellipse":
+				textString = "<text x='"+ coords[6] + "' y='"+ coords[7] + "'>"+ label + "</text>";
+				//textNode.setAttribute("x", coords[6]);
+				//textNode.setAttribute("y", coords[7]);
+				break;
+			case "rectangle":
+				//FIXME: implement
+				textString = "";
+				//textNode.setAttribute("x", coords[6]);
+				//textNode.setAttribute("y", coords[7]);
+				break;
+			case "circle":
+				//FIXME: implement
+				textString = "";
+				//textNode.setAttribute("x", coords[6]);
+				//textNode.setAttribute("y", coords[7]);
+				break;
+		}
+		//textNode.appendChild(labelNode);
+		//this.domNode.appendChild(textNode);
+		return textString;
+		//alert(textNode.getComputedTextLength());
+	}
+
+	this.fillInTemplate = function(x, y, textSize, label, shape){
+		// the idea is to set the text to the appropriate place given its length
+		// and the template shape
+		
+		// FIXME: For now, assuming text sizes are integers in SVG units
+		this.textSize = textSize || 12;
+		this.label = label;
+		// FIXEME: for now, I'm going to fake this... need to come up with a real way to 
+		// determine the actual width of the text, such as computedStyle
+		var textWidth = this.label.length*this.textSize ;
+		//this.setLabel();
+	}
+}
+
+dojo.inherits(dojo.widget.SvgButton, dojo.widget.DomButton);
+
+// FIXME
+dojo.widget.SvgButton.prototype.shapeString = function(x, y, textSize, label, shape) {
+	switch(shape) {
+		case "ellipse":
+			var coords = dojo.widget.SvgButton.prototype.coordinates(x, y, textSize, label, shape)
+			return "<ellipse cx='"+ coords[4]+"' cy='"+ coords[5]+"' rx='"+ coords[2]+"' ry='"+ coords[3]+"'/>";
+			break;
+		case "rect":
+			//FIXME: implement
+			return "";
+			//return "<rect x='110' y='45' width='70' height='30'/>";
+			break;
+		case "circle":
+			//FIXME: implement
+			return "";
+			//return "<circle cx='210' cy='60' r='23'/>";
+			break;
+	}
+}
+
+dojo.widget.SvgButton.prototype.coordinates = function(x, y, textSize, label, shape) {
+	switch(shape) {
+		case "ellipse":
+			var buttonWidth = label.length*textSize;
+			var buttonHeight = textSize*2.5
+			var rx = buttonWidth/2;
+			var ry = buttonHeight/2;
+			var cx = rx + x;
+			var cy = ry + y;
+			var textX = cx - rx*textSize/25;
+			var textY = cy*1.1;
+			return [buttonWidth, buttonHeight, rx, ry, cx, cy, textX, textY];
+			break;
+		case "rectangle":
+			//FIXME: implement
+			return "";
+			break;
+		case "circle":
+			//FIXME: implement
+			return "";
+			break;
+	}
+}
+
+dojo.widget.SvgButton.prototype.labelString = function(x, y, textSize, label, shape){
+	var textString = "";
+	var coords = dojo.widget.SvgButton.prototype.coordinates(x, y, textSize, label, shape);
+	switch(shape) {
+		case "ellipse":
+			textString = "<text x='"+ coords[6] + "' y='"+ coords[7] + "'>"+ label + "</text>";
+			break;
+		case "rectangle":
+			//FIXME: implement
+			textString = "";
+			break;
+		case "circle":
+			//FIXME: implement
+			textString = "";
+			break;
+	}
+	return textString;
+}
+
+dojo.widget.SvgButton.prototype.templateString = function(x, y, textSize, label, shape) {
+	return "<g class='dojoButton' dojoAttachEvent='onClick; onMouseMove: onFoo;' dojoAttachPoint='labelNode'>"+ dojo.widgets.SVGButton.prototype.shapeString(x, y, textSize, label, shape) + dojo.widget.SVGButton.prototype.labelString(x, y, textSize, label, shape) + "</g>";
+}

Propchange: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/SvgButton.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/SvgWidget.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/SvgWidget.js?rev=413306&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/SvgWidget.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/SvgWidget.js Sat Jun 10 07:27:44 2006
@@ -0,0 +1,92 @@
+/*
+	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.widget.DomWidget");
+dojo.provide("dojo.widget.SvgWidget");
+dojo.provide("dojo.widget.SVGWidget"); // back compat
+
+dojo.require("dojo.dom");
+
+// SVGWidget is a mixin ONLY
+dojo.widget.SvgWidget = function(args){
+	// mix in the parent type
+	// dojo.widget.DomWidget.call(this);
+}
+dojo.inherits(dojo.widget.SvgWidget, dojo.widget.DomWidget);
+
+dojo.lang.extend(dojo.widget.SvgWidget, {
+	getContainerHeight: function(){
+		// NOTE: container height must be returned as the INNER height
+		dojo.unimplemented("dojo.widget.SvgWidget.getContainerHeight");
+	},
+
+	getContainerWidth: function(){
+		// return this.parent.domNode.offsetWidth;
+		dojo.unimplemented("dojo.widget.SvgWidget.getContainerWidth");
+	},
+
+	setNativeHeight: function(height){
+		// var ch = this.getContainerHeight();
+		dojo.unimplemented("dojo.widget.SVGWidget.setNativeHeight");
+	},
+
+	createNodesFromText: function(txt, wrap){
+		return dojo.dom.createNodesFromText(txt, wrap);
+	}
+});
+
+dojo.widget.SVGWidget = dojo.widget.SvgWidget;
+
+try{
+(function(){
+	var tf = function(){
+		// FIXME: fill this in!!!
+		var rw = new function(){
+			dojo.widget.SvgWidget.call(this);
+			this.buildRendering = function(){ return; }
+			this.destroyRendering = function(){ return; }
+			this.postInitialize = function(){ return; }
+			this.cleanUp = function(){ return; }
+			this.widgetType = "SVGRootWidget";
+			this.domNode = document.documentElement;
+		}
+		var wm = dojo.widget.manager;
+		wm.root = rw;
+		wm.add(rw);
+
+		// extend the widgetManager with a getWidgetFromNode method
+		wm.getWidgetFromNode = function(node){
+			var filter = function(x){
+				if(x.domNode == node){
+					return true;
+				}
+			}
+			var widgets = [];
+			while((node)&&(widgets.length < 1)){
+				widgets = this.getWidgetsByFilter(filter);
+				node = node.parentNode;
+			}
+			if(widgets.length > 0){
+				return widgets[0];
+			}else{
+				return null;
+			}
+		}
+
+		wm.getWidgetFromEvent = function(domEvt){
+			return this.getWidgetFromNode(domEvt.target);
+		}
+
+		wm.getWidgetFromPrimitive = wm.getWidgetFromNode;
+	}
+	// make sure we get called when the time is right
+	dojo.event.connect(dojo.hostenv, "loaded", tf);
+})();
+}catch(e){ alert(e); }

Propchange: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/SvgWidget.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/SwtWidget.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/SwtWidget.js?rev=413306&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/SwtWidget.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/SwtWidget.js Sat Jun 10 07:27:44 2006
@@ -0,0 +1,64 @@
+/*
+	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.SwtWidget");
+
+dojo.require("dojo.event.*");
+dojo.require("dojo.widget.Widget");
+dojo.require("dojo.uri.*");
+dojo.require("dojo.lang.func");
+dojo.require("dojo.lang.extras");
+
+try{
+	importPackage(Packages.org.eclipse.swt.widgets);
+
+	dojo.declare("dojo.widget.SwtWidget", dojo.widget.Widget, {
+		initializer: function() {
+			if((arguments.length>0)&&(typeof arguments[0] == "object")){
+				this.create(arguments[0]);
+			}
+		},
+
+		display: null,
+		shell: null,
+
+		show: function(){ },
+		hide: function(){ },
+
+		addChild: function(){ },
+		registerChild: function(){ },
+		addWidgetAsDirectChild: function(){ },
+		removeChild: function(){ },
+		cleanUp: function(){ },
+		destroyRendering: function(){ },
+		postInitialize: function(){ },
+	});
+
+	// initialize SWT runtime
+
+	dojo.widget.SwtWidget.prototype.display = new Display();
+	dojo.widget.SwtWidget.prototype.shell = new Shell(dojo.widget.SwtWidget.prototype.display);
+
+	dojo.widget.manager.startShell = function(){
+		var sh = dojo.widget.SwtWidget.prototype.shell;
+		var d = dojo.widget.SwtWidget.prototype.display;
+		sh.open();
+		while(!sh.isDisposed()){
+			dojo.widget.manager.doNext();
+			if(!d.readAndDispatch()){
+				d.sleep();
+			}
+		}
+		d.dispose();
+	};
+}catch(e){
+	// seems we didn't have the SWT classes in the environment. Log it.
+	dojo.debug("dojo.widget.SwtWidget not loaded. SWT classes not available");
+}

Propchange: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/SwtWidget.js
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TabContainer.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TabContainer.js?rev=413306&r1=413305&r2=413306&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TabContainer.js (original)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TabContainer.js Sat Jun 10 07:27:44 2006
@@ -8,254 +8,254 @@
 		http://dojotoolkit.org/community/licensing.shtml
 */
 
-dojo.provide("dojo.widget.TabContainer");
-dojo.provide("dojo.widget.html.TabContainer");
-dojo.provide("dojo.widget.Tab");
-
-dojo.require("dojo.lang.func");
-dojo.require("dojo.widget.*");
-dojo.require("dojo.widget.HtmlWidget");
-dojo.require("dojo.event.*");
-dojo.require("dojo.html");
-dojo.require("dojo.style");
-dojo.require("dojo.html.layout");
-
-//////////////////////////////////////////
-// TabContainer -- a set of Tabs
-//////////////////////////////////////////
-dojo.widget.html.TabContainer = function() {
-	dojo.widget.HtmlWidget.call(this);
-}
-
-dojo.inherits(dojo.widget.html.TabContainer, dojo.widget.HtmlWidget);
-
-dojo.lang.extend(dojo.widget.html.TabContainer, {
-	widgetType: "TabContainer",
-    isContainer: true,
-
-	// Constructor arguments
-	labelPosition: "top",
-	closeButton: "none",
-
-	useVisibility: false,		// true-->use visibility:hidden instead of display:none
-	
-	// if false, TabContainers size changes according to size of currently selected tab
-	doLayout: true,
-
-	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlTabContainer.html"),
-	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlTabContainer.css"),
-
-	selectedTab: "",		// initially selected tab (widgetId)
-
-	fillInTemplate: function(args, frag) {
-		// Copy style info from input node to output node
-		var source = this.getFragNodeRef(frag);
-		dojo.html.copyStyle(this.domNode, source);
-
-		dojo.widget.html.TabContainer.superclass.fillInTemplate.call(this, args, frag);
-	},
-
-	postCreate: function(args, frag) {
-		// Load all the tabs, creating a label for each one
-		for(var i=0; i<this.children.length; i++){
-			this._setupTab(this.children[i]);
-		}
-
-		if (this.closeButton=="pane") {
-			var div = document.createElement("div");
-			dojo.html.addClass(div, "dojoTabPanePaneClose");
-			var self = this;
-			dojo.event.connect(div, "onclick", function(){ self._runOnCloseTab(self.selectedTabWidget); });
-			dojo.event.connect(div, "onmouseover", function(){ dojo.html.addClass(div, "dojoTabPanePaneCloseHover"); });
-			dojo.event.connect(div, "onmouseout", function(){ dojo.html.removeClass(div, "dojoTabPanePaneCloseHover"); });
-			this.dojoTabLabels.appendChild(div);
-		}
-
-		if(this.doLayout){
-			dojo.html.addClass(this.dojoTabLabels, "dojoTabLabels-"+this.labelPosition);
-		} else {
-			dojo.html.addClass(this.dojoTabLabels, "dojoTabLabels-"+this.labelPosition+"-noLayout");
-		}
-
-        this._doSizing();
-
-		// Display the selected tab
-		if(this.selectedTabWidget){
-			this.selectTab(this.selectedTabWidget, true);
-		}
-	},
-
-	addChild: function(child, overrideContainerNode, pos, ref, insertIndex){
-		this._setupTab(child);
-		dojo.widget.html.TabContainer.superclass.addChild.call(this,child, overrideContainerNode, pos, ref, insertIndex);
-
-		// in case the tab labels have overflowed from one line to two lines
-		this._doSizing();
-	},
-
-	_setupTab: function(tab){
-		tab.domNode.style.display="none";
-
-		// Create label
-		tab.div = document.createElement("div");
-		dojo.widget.wai.setAttr(tab.div, "waiRole", "tab");
-		dojo.html.addClass(tab.div, "dojoTabPaneTab");
-		var span = document.createElement("span");
-		span.innerHTML = tab.label;
-		dojo.html.disableSelection(span);
-		if (this.closeButton=="tab") {
-			var img = document.createElement("div");
-			dojo.html.addClass(img, "dojoTabPaneTabClose");
-			var self = this;
-			dojo.event.connect(img, "onclick", function(evt){ self._runOnCloseTab(tab); dojo.event.browser.stopEvent(evt); });
-			dojo.event.connect(img, "onmouseover", function(){ dojo.html.addClass(img,"dojoTabPaneTabCloseHover"); });
-			dojo.event.connect(img, "onmouseout", function(){ dojo.html.removeClass(img,"dojoTabPaneTabCloseHover"); });
-			span.appendChild(img);
-		}
-		tab.div.appendChild(span);
-		this.dojoTabLabels.appendChild(tab.div);
-		
-		var self = this;
-		dojo.event.connect(tab.div, "onclick", function(){ self.selectTab(tab); });
-
-		if(!this.selectedTabWidget || this.selectedTab==tab.widgetId || tab.selected){
-    		this.selectedTabWidget = tab;
-        } else {
-            this._hideTab(tab);
-        }
-
-		dojo.html.addClass(tab.domNode, "dojoTabPane");
-		with(tab.domNode.style){
-			top = dojo.style.getPixelValue(this.containerNode, "padding-top", true);
-			left = dojo.style.getPixelValue(this.containerNode, "padding-left", true);
-		}
-	},
-
-	// Configure the content pane to take up all the space except for where the tab labels are
-	_doSizing: function(){
-		// position the labels and the container node
-		var labelAlign=this.labelPosition.replace(/-h/,"");
-		var children = [
-			{domNode: this.dojoTabLabels, layoutAlign: labelAlign},
-			{domNode: this.containerNode, layoutAlign: "client"}
-		];
-
-
-		if (this.doLayout) {
-			dojo.html.layout(this.domNode, children);
-		} 
-			
-		// size the current tab
-		// TODO: should have ptr to current tab rather than searching
-		var cw=dojo.style.getContentWidth(this.containerNode);
-		var ch=dojo.style.getContentHeight(this.containerNode);
-		dojo.lang.forEach(this.children, function(child){
-			//if (this.doLayout) {
-				if(child.selected){
-					child.resizeTo(cw, ch);
-				} 
-			//} else {
-			//	child.onResized();
-			//}
-		});
-		
-	},
-
-    removeChild: function(tab) {
-
-		// remove tab event handlers
-		dojo.event.disconnect(tab.div, "onclick", function () { });
-		if (this.closeButton=="tab") {
-			var img = tab.div.lastChild.lastChild;
-			if (img) {
-				dojo.html.removeClass(img, "dojoTabPaneTabClose", function () { });
-				dojo.event.disconnect(img, "onclick", function () { });
-				dojo.event.disconnect(img, "onmouseover", function () { });
-				dojo.event.disconnect(img, "onmouseout", function () { });
-			}
-		}
-
-        dojo.widget.html.TabContainer.superclass.removeChild.call(this, tab);
-
-        dojo.html.removeClass(tab.domNode, "dojoTabPane");
-        this.dojoTabLabels.removeChild(tab.div);
-        delete(tab.div);
-
-        if (this.selectedTabWidget === tab) {
-            this.selectedTabWidget = undefined;
-            if (this.children.length > 0) {
-                this.selectTab(this.children[0], true);
-            }
-        }
-
-		// in case the tab labels have overflowed from one line to two lines
-		this._doSizing();
-    },
-
-    selectTab: function(tab, _noRefresh) {
-		// Deselect old tab and select new one
-		if (this.selectedTabWidget) {
-			this._hideTab(this.selectedTabWidget);
-		}
-		this.selectedTabWidget = tab;
-		this._showTab(tab, _noRefresh);
-	},
-
-	_showTab: function(tab, _noRefresh) {
-		dojo.html.addClass(tab.div, "current");
-		tab.selected=true;
-		if ( this.useVisibility && !dojo.render.html.ie ) {
-			tab.domNode.style.visibility="visible";
-		} else {
-			// make sure we dont refresh onClose and on postCreate
-			// speeds up things a bit when using refreshOnShow and fixes #646
-			if(_noRefresh && tab.refreshOnShow){
-				var tmp = tab.refreshOnShow;
-				tab.refreshOnShow = false;
-				tab.show();
-				tab.refreshOnShow = tmp;
-			}else{
-				tab.show();
-			}
-
-			tab.resizeTo(
-				dojo.style.getContentWidth(this.containerNode),
-				dojo.style.getContentHeight(this.containerNode)
-			);
-		}
-	},
-
-	_hideTab: function(tab) {
-		dojo.html.removeClass(tab.div, "current");
-		tab.selected=false;
-		if( this.useVisibility ){
-			tab.domNode.style.visibility="hidden";
-		}else{
-			tab.hide();
-		}
-	},
-
-	_runOnCloseTab: function(tab) {
-		var onc = tab.extraArgs.onClose || tab.extraArgs.onclose;
-		var fcn = dojo.lang.isFunction(onc) ? onc : window[onc];
-		var remove = dojo.lang.isFunction(fcn) ? fcn(this,tab) : true;
-		if(remove) {
-			this.removeChild(tab);
-			// makes sure we can clean up executeScripts in ContentPane onUnLoad
-			tab.destroy();
-		}
-	},
-
-	onResized: function() {
-		this._doSizing();
-	}
-});
-dojo.widget.tags.addParseTreeHandler("dojo:TabContainer");
-
-// These arguments can be specified for the children of a TabContainer.
-// Since any widget can be specified as a TabContainer child, mix them
-// into the base widget class.  (This is a hack, but it's effective.)
-dojo.lang.extend(dojo.widget.Widget, {
-	label: "",
-	selected: false	// is this tab currently selected?
+dojo.provide("dojo.widget.TabContainer");
+dojo.provide("dojo.widget.html.TabContainer");
+dojo.provide("dojo.widget.Tab");
+
+dojo.require("dojo.lang.func");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.event.*");
+dojo.require("dojo.html");
+dojo.require("dojo.style");
+dojo.require("dojo.html.layout");
+
+//////////////////////////////////////////
+// TabContainer -- a set of Tabs
+//////////////////////////////////////////
+dojo.widget.html.TabContainer = function() {
+	dojo.widget.HtmlWidget.call(this);
+}
+
+dojo.inherits(dojo.widget.html.TabContainer, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.html.TabContainer, {
+	widgetType: "TabContainer",
+    isContainer: true,
+
+	// Constructor arguments
+	labelPosition: "top",
+	closeButton: "none",
+
+	useVisibility: false,		// true-->use visibility:hidden instead of display:none
+	
+	// if false, TabContainers size changes according to size of currently selected tab
+	doLayout: true,
+
+	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlTabContainer.html"),
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlTabContainer.css"),
+
+	selectedTab: "",		// initially selected tab (widgetId)
+
+	fillInTemplate: function(args, frag) {
+		// Copy style info from input node to output node
+		var source = this.getFragNodeRef(frag);
+		dojo.html.copyStyle(this.domNode, source);
+
+		dojo.widget.html.TabContainer.superclass.fillInTemplate.call(this, args, frag);
+	},
+
+	postCreate: function(args, frag) {
+		// Load all the tabs, creating a label for each one
+		for(var i=0; i<this.children.length; i++){
+			this._setupTab(this.children[i]);
+		}
+
+		if (this.closeButton=="pane") {
+			var div = document.createElement("div");
+			dojo.html.addClass(div, "dojoTabPanePaneClose");
+			var self = this;
+			dojo.event.connect(div, "onclick", function(){ self._runOnCloseTab(self.selectedTabWidget); });
+			dojo.event.connect(div, "onmouseover", function(){ dojo.html.addClass(div, "dojoTabPanePaneCloseHover"); });
+			dojo.event.connect(div, "onmouseout", function(){ dojo.html.removeClass(div, "dojoTabPanePaneCloseHover"); });
+			this.dojoTabLabels.appendChild(div);
+		}
+
+		if(this.doLayout){
+			dojo.html.addClass(this.dojoTabLabels, "dojoTabLabels-"+this.labelPosition);
+		} else {
+			dojo.html.addClass(this.dojoTabLabels, "dojoTabLabels-"+this.labelPosition+"-noLayout");
+		}
+
+        this._doSizing();
+
+		// Display the selected tab
+		if(this.selectedTabWidget){
+			this.selectTab(this.selectedTabWidget, true);
+		}
+	},
+
+	addChild: function(child, overrideContainerNode, pos, ref, insertIndex){
+		this._setupTab(child);
+		dojo.widget.html.TabContainer.superclass.addChild.call(this,child, overrideContainerNode, pos, ref, insertIndex);
+
+		// in case the tab labels have overflowed from one line to two lines
+		this._doSizing();
+	},
+
+	_setupTab: function(tab){
+		tab.domNode.style.display="none";
+
+		// Create label
+		tab.div = document.createElement("div");
+		dojo.widget.wai.setAttr(tab.div, "waiRole", "tab");
+		dojo.html.addClass(tab.div, "dojoTabPaneTab");
+		var span = document.createElement("span");
+		span.innerHTML = tab.label;
+		dojo.html.disableSelection(span);
+		if (this.closeButton=="tab") {
+			var img = document.createElement("div");
+			dojo.html.addClass(img, "dojoTabPaneTabClose");
+			var self = this;
+			dojo.event.connect(img, "onclick", function(evt){ self._runOnCloseTab(tab); dojo.event.browser.stopEvent(evt); });
+			dojo.event.connect(img, "onmouseover", function(){ dojo.html.addClass(img,"dojoTabPaneTabCloseHover"); });
+			dojo.event.connect(img, "onmouseout", function(){ dojo.html.removeClass(img,"dojoTabPaneTabCloseHover"); });
+			span.appendChild(img);
+		}
+		tab.div.appendChild(span);
+		this.dojoTabLabels.appendChild(tab.div);
+		
+		var self = this;
+		dojo.event.connect(tab.div, "onclick", function(){ self.selectTab(tab); });
+
+		if(!this.selectedTabWidget || this.selectedTab==tab.widgetId || tab.selected){
+    		this.selectedTabWidget = tab;
+        } else {
+            this._hideTab(tab);
+        }
+
+		dojo.html.addClass(tab.domNode, "dojoTabPane");
+		with(tab.domNode.style){
+			top = dojo.style.getPixelValue(this.containerNode, "padding-top", true);
+			left = dojo.style.getPixelValue(this.containerNode, "padding-left", true);
+		}
+	},
+
+	// Configure the content pane to take up all the space except for where the tab labels are
+	_doSizing: function(){
+		// position the labels and the container node
+		var labelAlign=this.labelPosition.replace(/-h/,"");
+		var children = [
+			{domNode: this.dojoTabLabels, layoutAlign: labelAlign},
+			{domNode: this.containerNode, layoutAlign: "client"}
+		];
+
+
+		if (this.doLayout) {
+			dojo.html.layout(this.domNode, children);
+		} 
+			
+		// size the current tab
+		// TODO: should have ptr to current tab rather than searching
+		var cw=dojo.style.getContentWidth(this.containerNode);
+		var ch=dojo.style.getContentHeight(this.containerNode);
+		dojo.lang.forEach(this.children, function(child){
+			//if (this.doLayout) {
+				if(child.selected){
+					child.resizeTo(cw, ch);
+				} 
+			//} else {
+			//	child.onResized();
+			//}
+		});
+		
+	},
+
+    removeChild: function(tab) {
+
+		// remove tab event handlers
+		dojo.event.disconnect(tab.div, "onclick", function () { });
+		if (this.closeButton=="tab") {
+			var img = tab.div.lastChild.lastChild;
+			if (img) {
+				dojo.html.removeClass(img, "dojoTabPaneTabClose", function () { });
+				dojo.event.disconnect(img, "onclick", function () { });
+				dojo.event.disconnect(img, "onmouseover", function () { });
+				dojo.event.disconnect(img, "onmouseout", function () { });
+			}
+		}
+
+        dojo.widget.html.TabContainer.superclass.removeChild.call(this, tab);
+
+        dojo.html.removeClass(tab.domNode, "dojoTabPane");
+        this.dojoTabLabels.removeChild(tab.div);
+        delete(tab.div);
+
+        if (this.selectedTabWidget === tab) {
+            this.selectedTabWidget = undefined;
+            if (this.children.length > 0) {
+                this.selectTab(this.children[0], true);
+            }
+        }
+
+		// in case the tab labels have overflowed from one line to two lines
+		this._doSizing();
+    },
+
+    selectTab: function(tab, _noRefresh) {
+		// Deselect old tab and select new one
+		if (this.selectedTabWidget) {
+			this._hideTab(this.selectedTabWidget);
+		}
+		this.selectedTabWidget = tab;
+		this._showTab(tab, _noRefresh);
+	},
+
+	_showTab: function(tab, _noRefresh) {
+		dojo.html.addClass(tab.div, "current");
+		tab.selected=true;
+		if ( this.useVisibility && !dojo.render.html.ie ) {
+			tab.domNode.style.visibility="visible";
+		} else {
+			// make sure we dont refresh onClose and on postCreate
+			// speeds up things a bit when using refreshOnShow and fixes #646
+			if(_noRefresh && tab.refreshOnShow){
+				var tmp = tab.refreshOnShow;
+				tab.refreshOnShow = false;
+				tab.show();
+				tab.refreshOnShow = tmp;
+			}else{
+				tab.show();
+			}
+
+			tab.resizeTo(
+				dojo.style.getContentWidth(this.containerNode),
+				dojo.style.getContentHeight(this.containerNode)
+			);
+		}
+	},
+
+	_hideTab: function(tab) {
+		dojo.html.removeClass(tab.div, "current");
+		tab.selected=false;
+		if( this.useVisibility ){
+			tab.domNode.style.visibility="hidden";
+		}else{
+			tab.hide();
+		}
+	},
+
+	_runOnCloseTab: function(tab) {
+		var onc = tab.extraArgs.onClose || tab.extraArgs.onclose;
+		var fcn = dojo.lang.isFunction(onc) ? onc : window[onc];
+		var remove = dojo.lang.isFunction(fcn) ? fcn(this,tab) : true;
+		if(remove) {
+			this.removeChild(tab);
+			// makes sure we can clean up executeScripts in ContentPane onUnLoad
+			tab.destroy();
+		}
+	},
+
+	onResized: function() {
+		this._doSizing();
+	}
+});
+dojo.widget.tags.addParseTreeHandler("dojo:TabContainer");
+
+// These arguments can be specified for the children of a TabContainer.
+// Since any widget can be specified as a TabContainer child, mix them
+// into the base widget class.  (This is a hack, but it's effective.)
+dojo.lang.extend(dojo.widget.Widget, {
+	label: "",
+	selected: false	// is this tab currently selected?
 });

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TaskBar.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TaskBar.js?rev=413306&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TaskBar.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TaskBar.js Sat Jun 10 07:27:44 2006
@@ -0,0 +1,32 @@
+/*
+	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.TaskBar");
+dojo.provide("dojo.widget.TaskBarItem");
+dojo.require("dojo.widget.Widget");
+
+dojo.widget.TaskBar = function(){
+	dojo.widget.Widget.call(this);
+
+	this.widgetType = "TaskBar";
+	this.isContainer = true;
+}
+dojo.inherits(dojo.widget.TaskBar, dojo.widget.Widget);
+dojo.widget.tags.addParseTreeHandler("dojo:taskbar");
+
+dojo.widget.TaskBarItem = function(){
+	dojo.widget.Widget.call(this);
+
+	this.widgetType = "TaskBarItem";
+}
+dojo.inherits(dojo.widget.TaskBarItem, dojo.widget.Widget);
+dojo.widget.tags.addParseTreeHandler("dojo:taskbaritem");
+
+dojo.requireAfterIf("html", "dojo.widget.html.TaskBar");

Propchange: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TaskBar.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TimePicker.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TimePicker.js?rev=413306&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TimePicker.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TimePicker.js Sat Jun 10 07:27:44 2006
@@ -0,0 +1,82 @@
+/*
+	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.TimePicker");
+dojo.provide("dojo.widget.TimePicker.util");
+dojo.require("dojo.widget.DomWidget");
+dojo.require("dojo.date");
+
+dojo.widget.TimePicker = function(){
+	dojo.widget.Widget.call(this);
+	this.widgetType = "TimePicker";
+	this.isContainer = false;
+	// the following aliases prevent breaking people using 0.2.x
+	this.toRfcDateTime = dojo.widget.TimePicker.util.toRfcDateTime;
+	this.fromRfcDateTime = dojo.widget.TimePicker.util.fromRfcDateTime;
+	this.toAmPmHour = dojo.widget.TimePicker.util.toAmPmHour;
+	this.fromAmPmHour = dojo.widget.TimePicker.util.fromAmPmHour;
+}
+
+dojo.inherits(dojo.widget.TimePicker, dojo.widget.Widget);
+dojo.widget.tags.addParseTreeHandler("dojo:timepicker");
+
+dojo.requireAfterIf("html", "dojo.widget.html.TimePicker");
+
+dojo.widget.TimePicker.util = new function() {
+	// utility functions
+	this.toRfcDateTime = function(jsDate) {
+		if(!jsDate) {
+			jsDate = new Date();
+		}
+		return dojo.date.format(jsDate, "%Y-%m-%dT%H:%M:00%z");
+	}
+
+	this.fromRfcDateTime = function(rfcDate, useDefaultMinutes, isAnyTime) {
+		var tempDate = new Date();
+		if(!rfcDate || rfcDate.indexOf("T")==-1) {
+			if(useDefaultMinutes) {
+				tempDate.setMinutes(Math.floor(tempDate.getMinutes()/5)*5);
+			} else {
+				tempDate.setMinutes(0);
+			}
+		} else {
+			var tempTime = rfcDate.split("T")[1].split(":");
+			// fullYear, month, date
+			var tempDate = new Date();
+			tempDate.setHours(tempTime[0]);
+			tempDate.setMinutes(tempTime[1]);
+		}
+		return tempDate;
+	}
+
+	this.toAmPmHour = function(hour) {
+		var amPmHour = hour;
+		var isAm = true;
+		if (amPmHour == 0) {
+			amPmHour = 12;
+		} else if (amPmHour>12) {
+			amPmHour = amPmHour - 12;
+			isAm = false;
+		} else if (amPmHour == 12) {
+			isAm = false;
+		}
+		return [amPmHour, isAm];
+	}
+
+	this.fromAmPmHour = function(amPmHour, isAm) {
+		var hour = parseInt(amPmHour, 10);
+		if(isAm && hour == 12) {
+			hour = 0;
+		} else if (!isAm && hour<12) {
+			hour = hour + 12;
+		}
+		return hour;
+	}
+}

Propchange: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TimePicker.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Toggler.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Toggler.js?rev=413306&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Toggler.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Toggler.js Sat Jun 10 07:27:44 2006
@@ -0,0 +1,40 @@
+/*
+	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.Toggler");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.event.*");
+
+// clicking on this node shows/hides another widget
+
+dojo.widget.Toggler = function(){
+	dojo.widget.DomWidget.call(this);
+}
+
+dojo.inherits(dojo.widget.Toggler, dojo.widget.DomWidget);
+
+dojo.lang.extend(dojo.widget.Toggler, {
+	widgetType: "Toggler",
+	
+	// Associated widget 
+	targetId: '',
+	
+	fillInTemplate: function() {
+		dojo.event.connect(this.domNode, "onclick", this, "onClick");
+	},
+	
+	onClick: function() {
+		var pane = dojo.widget.byId(this.targetId);
+		if(!pane){ return; }
+		pane.explodeSrc = this.domNode;
+		pane.toggleShowing();
+	}
+});
+dojo.widget.tags.addParseTreeHandler("dojo:toggler");

Modified: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Tooltip.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Tooltip.js?rev=413306&r1=413305&r2=413306&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Tooltip.js (original)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Tooltip.js Sat Jun 10 07:27:44 2006
@@ -8,7 +8,7 @@
 		http://dojotoolkit.org/community/licensing.shtml
 */
 
-dojo.provide("dojo.widget.Tooltip");
-dojo.require("dojo.widget.Widget");
-
-dojo.requireAfterIf("html", "dojo.widget.html.Tooltip");
+dojo.provide("dojo.widget.Tooltip");
+dojo.require("dojo.widget.Widget");
+
+dojo.requireAfterIf("html", "dojo.widget.html.Tooltip");

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeContextMenu.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeContextMenu.js?rev=413306&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeContextMenu.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeContextMenu.js Sat Jun 10 07:27:44 2006
@@ -0,0 +1,214 @@
+/*
+	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.TreeContextMenu");
+dojo.provide("dojo.widget.TreeMenuItem");
+
+dojo.require("dojo.event.*");
+dojo.require("dojo.io.*");
+dojo.require("dojo.widget.Menu2");
+
+
+dojo.widget.tags.addParseTreeHandler("dojo:TreeContextMenu");
+dojo.widget.tags.addParseTreeHandler("dojo:TreeMenuItem");
+
+
+
+dojo.widget.TreeContextMenu = function() {
+	dojo.widget.PopupMenu2.call(this);
+
+	this.listenedTrees = [];
+
+}
+
+
+dojo.inherits(dojo.widget.TreeContextMenu, dojo.widget.PopupMenu2);
+
+dojo.lang.extend(dojo.widget.TreeContextMenu, {
+
+	widgetType: "TreeContextMenu",
+
+	open: function(x, y, parentMenu, explodeSrc){
+
+		var result = dojo.widget.PopupMenu2.prototype.open.apply(this, arguments);
+
+		/* publish many events here about structural changes */
+		dojo.event.topic.publish(this.eventNames.open, { menu:this });
+
+		return result;
+	},
+
+	listenTree: function(tree) {
+		/* add context menu to all nodes that exist already */
+		var nodes = tree.getDescendants();
+
+		for(var i=0; i<nodes.length; i++) {
+			if (!nodes[i].isTreeNode) continue;
+			this.bindDomNode(nodes[i].labelNode);
+		}
+
+
+		/* bind context menu to all nodes that will be created in the future (e.g loaded from server)*/
+		var _this = this;
+		dojo.event.topic.subscribe(tree.eventNames.createDOMNode, this, "onCreateDOMNode");
+		dojo.event.topic.subscribe(tree.eventNames.moveFrom, this, "onMoveFrom");
+		dojo.event.topic.subscribe(tree.eventNames.moveTo, this, "onMoveTo");
+		dojo.event.topic.subscribe(tree.eventNames.removeNode, this, "onRemoveNode");
+		dojo.event.topic.subscribe(tree.eventNames.addChild, this, "onAddChild");
+		dojo.event.topic.subscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy");
+
+		this.listenedTrees.push(tree);
+
+	},
+
+	unlistenTree: function(tree) {
+		/* clear event listeners */
+
+		dojo.event.topic.unsubscribe(tree.eventNames.createDOMNode, this, "onCreateDOMNode");
+		dojo.event.topic.unsubscribe(tree.eventNames.moveFrom, this, "onMoveFrom");
+		dojo.event.topic.unsubscribe(tree.eventNames.moveTo, this, "onMoveTo");
+		dojo.event.topic.unsubscribe(tree.eventNames.removeNode, this, "onRemoveNode");
+		dojo.event.topic.unsubscribe(tree.eventNames.addChild, this, "onAddChild");
+		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);
+	},
+
+	bindTreeNode: function(node) {
+		var _this = this;
+		//dojo.debug("bind to "+node);
+		dojo.lang.forEach(node.getDescendants(),
+			function(e) {_this.bindDomNode(e.labelNode); }
+		);
+	},
+
+
+	unBindTreeNode: function(node) {
+		var _this = this;
+		//dojo.debug("Unbind from "+node);
+		dojo.lang.forEach(node.getDescendants(),
+			function(e) {_this.unBindDomNode(e.labelNode); }
+		);
+	},
+
+	onCreateDOMNode: function(message) {
+		this.bindTreeNode(message.source);
+	},
+
+
+	onMoveFrom: function(message) {
+		if (!dojo.lang.inArray(this.listenedTrees, message.newTree)) {
+			this.unBindTreeNode(message.child);
+		}
+	},
+
+	onMoveTo: function(message) {
+		if (dojo.lang.inArray(this.listenedTrees, message.newTree)) {
+			this.bindTreeNode(message.child);
+		}
+	},
+
+	onRemoveNode: function(message) {
+		this.unBindTreeNode(message.child);
+	},
+
+	onAddChild: function(message) {
+		if (message.domNodeInitialized) {
+			// dom node was there already => I did not process onNodeDomCreate
+			this.bindTreeNode(message.child);
+		}
+	}
+
+
+});
+
+
+
+
+
+
+dojo.widget.TreeMenuItem = function() {
+	dojo.widget.MenuItem2.call(this);
+
+}
+
+
+dojo.inherits(dojo.widget.TreeMenuItem, dojo.widget.MenuItem2);
+
+
+dojo.lang.extend(dojo.widget.TreeMenuItem, {
+
+	widgetType: "TreeMenuItem",
+
+	// treeActions menu item performs following actions (to be checked for permissions)
+	treeActions: "",
+
+	initialize: function(args, frag) {
+
+		this.treeActions = this.treeActions.split(",");
+		for(var i=0; i<this.treeActions.length; i++) {
+			this.treeActions[i] = this.treeActions[i].toUpperCase();
+		}
+
+	},
+
+	getTreeNode: function() {
+		var menu = this;
+
+		while (! (menu instanceof dojo.widget.TreeContextMenu) ) {
+			menu = menu.parent;
+		}
+
+		var source = menu.getTopOpenEvent().target;
+
+		while (!source.getAttribute('treeNode') && source.tagName != 'body') {
+			source = source.parentNode;
+		}
+		if (source.tagName == 'body') {
+			dojo.raise("treeNode not detected");
+		}
+		var treeNode = dojo.widget.manager.getWidgetById(source.getAttribute('treeNode'));
+
+		return treeNode;
+	},
+
+
+	menuOpen: function(message) {
+		var treeNode = this.getTreeNode();
+
+		this.setDisabled(false); // enable by default
+
+		var _this = this;
+		dojo.lang.forEach(_this.treeActions,
+			function(action) {
+				_this.setDisabled( treeNode.actionIsDisabled(action) );
+			}
+		);
+
+	},
+
+	toString: function() {
+		return "["+this.widgetType+" node "+this.getTreeNode()+"]";
+	}
+
+});
+
+

Propchange: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeContextMenu.js
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeNode.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeNode.js?rev=413306&r1=413305&r2=413306&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeNode.js (original)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeNode.js Sat Jun 10 07:27:44 2006
@@ -8,527 +8,527 @@
 		http://dojotoolkit.org/community/licensing.shtml
 */
 
-
-dojo.provide("dojo.widget.TreeNode");
-
-dojo.require("dojo.event.*");
-dojo.require("dojo.io.*");
-
-// make it a tag
-dojo.widget.tags.addParseTreeHandler("dojo:TreeNode");
-
-
-// # //////////
-
-dojo.widget.TreeNode = function() {
-	dojo.widget.HtmlWidget.call(this);
-
-	this.actionsDisabled = [];
-}
-
-dojo.inherits(dojo.widget.TreeNode, dojo.widget.HtmlWidget);
-
-dojo.lang.extend(dojo.widget.TreeNode, {
-	widgetType: "TreeNode",
-
-	loadStates: {
-		UNCHECKED: "UNCHECKED",
-    	LOADING: "LOADING",
-    	LOADED: "LOADED"
-	},
-
-
-	actions: {
-		MOVE: "MOVE",
-    	REMOVE: "REMOVE",
-    	EDIT: "EDIT",
-    	ADDCHILD: "ADDCHILD"
-	},
-
-	isContainer: true,
-
-	lockLevel: 0, // lock ++ unlock --, so nested locking works fine
-
-
-	templateString: ('<div class="dojoTreeNode"> '
-		+ '<span treeNode="${this.widgetId}" class="dojoTreeNodeLabel" dojoAttachPoint="labelNode"> '
-		+ '		<span dojoAttachPoint="titleNode" dojoAttachEvent="onClick: onTitleClick" class="dojoTreeNodeLabelTitle">${this.title}</span> '
-		+ '</span> '
-		+ '<span class="dojoTreeNodeAfterLabel" dojoAttachPoint="afterLabelNode">${this.afterLabel}</span> '
-		+ '<div dojoAttachPoint="containerNode" style="display:none"></div> '
-		+ '</div>').replace(/(>|<)\s+/g, '$1'), // strip whitespaces between nodes
-
-
-	childIconSrc: "",
-	childIconFolderSrc: dojo.uri.dojoUri("src/widget/templates/images/Tree/closed.gif"), // for under root parent item child icon,
-	childIconDocumentSrc: dojo.uri.dojoUri("src/widget/templates/images/Tree/document.gif"), // for under root parent item child icon,
-
-	childIcon: null,
-	isTreeNode: true,
-
-	objectId: "", // the widget represents an object
-
-	afterLabel: "",
-	afterLabelNode: null, // node to the left of labelNode
-
-	// an icon left from childIcon: imgs[-2].
-	// if +/- for folders, blank for leaves
-	expandIcon: null,
-
-	title: "",
-	object: "", // node may have object attached, settable from HTML
-	isFolder: false,
-
-	labelNode: null, // the item label
-	titleNode: null, // the item title
-	imgs: null, // an array of icons imgs
-
-	expandLevel: "", // expand to level
-
-	tree: null,
-
-	depth: 0,
-
-	isExpanded: false,
-
-	state: null,  // after creation will change to loadStates: "loaded/loading/unchecked"
-	domNodeInitialized: false,  // domnode is initialized with icons etc
-
-
-	isFirstNode: function() {
-		return this.getParentIndex() == 0 ? true: false;
-	},
-
-	isLastNode: function() {
-		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;
-
-		var disabled = false;
-
-		if (this.tree.strictFolders && action == this.actions.ADDCHILD && !this.isFolder) {
-			disabled = true;
-		}
-
-		if (dojo.lang.inArray(_this.actionsDisabled, action)) {
-			disabled = true;
-		}
-
-		if (this.isLocked()) {
-			disabled = true;
-		}
-
-		return disabled;
-	},
-
-	getInfo: function() {
-		// No title here (title may be widget)
-		var info = {
-			widgetId: this.widgetId,
-			objectId: this.objectId,
-			index: this.getParentIndex(),
-			isFolder: this.isFolder
-		}
-
-		return info;
-	},
-
-	initialize: function(args, frag){
-
-		//dojo.debug(this.title)
-
-		this.state = this.loadStates.UNCHECKED;
-
-		for(var i=0; i<this.actionsDisabled.length; i++) {
-			this.actionsDisabled[i] = this.actionsDisabled[i].toUpperCase();
-		}
-
-		this.expandLevel = parseInt(this.expandLevel);
-
-	},
-
-
-	/**
-	 * Change visible node depth by appending/prepending with blankImgs
-	 * @param depthDiff Integer positive => move right, negative => move left
-	*/
-	adjustDepth: function(depthDiff) {
-
-		for(var i=0; i<this.children.length; i++) {
-			this.children[i].adjustDepth(depthDiff);
-		}
-
-		this.depth += depthDiff;
-
-		if (depthDiff>0) {
-			for(var i=0; i<depthDiff; i++) {
-				var img = this.tree.makeBlankImg();
-				this.imgs.unshift(img);
-				//dojo.debugShallow(this.domNode);
-				dojo.dom.insertBefore(this.imgs[0], this.domNode.firstChild);
-
-			}
-		}
-		if (depthDiff<0) {
-			for(var i=0; i<-depthDiff;i++) {
-				this.imgs.shift();
-				dojo.dom.removeNode(this.domNode.firstChild);
-			}
-		}
-
-	},
-
-
-	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');
-		this.expandIcon.src = this.isExpanded ? this.tree.expandIconSrcMinus : this.tree.expandIconSrcPlus;
-		this.isFolder = true;
-	},
-
-
-	createDOMNode: function(tree, depth){
-
-		this.tree = tree;
-		this.depth = depth;
-
-
-		//
-		// add the tree icons
-		//
-
-		this.imgs = [];
-
-		for(var i=0; i<this.depth+1; i++){
-
-			var img = this.tree.makeBlankImg();
-
-			this.domNode.insertBefore(img, this.labelNode);
-
-			this.imgs.push(img);
-		}
-
-
-		this.expandIcon = this.imgs[this.imgs.length-1];
-
-
-		this.childIcon = this.tree.makeBlankImg();
-
-		// add to images before the title
-		this.imgs.push(this.childIcon);
-
-		dojo.dom.insertBefore(this.childIcon, this.titleNode);
-
-		// node with children(from source html) becomes folder on build stage.
-		if (this.children.length || this.isFolder) {
-			this.setFolder();
-		}
-		else {
-			// leaves are always loaded
-			//dojo.debug("Set "+this+" state to loaded");
-			this.state = this.loadStates.LOADED;
-		}
-
-		dojo.event.connect(this.childIcon, 'onclick', this, 'onIconClick');
-
-
-		//
-		// create the child rows
-		//
-
-
-		for(var i=0; i<this.children.length; i++){
-			this.children[i].parent = this;
-
-			var node = this.children[i].createDOMNode(this.tree, this.depth+1);
-
-			this.containerNode.appendChild(node);
-		}
-
-
-		if (this.children.length) {
-			this.state = this.loadStates.LOADED;
-		}
-
-		this.updateIcons();
-
-		this.domNodeInitialized = true;
-
-		dojo.event.topic.publish(this.tree.eventNames.createDOMNode, { source: this } );
-
-		return this.domNode;
-	},
-
-	onTreeClick: function(e){
-		dojo.event.topic.publish(this.tree.eventNames.treeClick, { source: this, event: e });
-	},
-
-	onIconClick: function(e){
-		dojo.event.topic.publish(this.tree.eventNames.iconClick, { source: this, event: e });
-	},
-
-	onTitleClick: function(e){
-		dojo.event.topic.publish(this.tree.eventNames.titleClick, { source: this, event: e });
-	},
-
-	markSelected: function() {
-		dojo.html.addClass(this.titleNode, 'dojoTreeNodeLabelSelected');
-	},
-
-
-	unMarkSelected: function() {
-		//dojo.debug('unmark')
-		dojo.html.removeClass(this.titleNode, 'dojoTreeNodeLabelSelected');
-	},
-
-	updateExpandIcon: function() {
-		if (this.isFolder){
-			this.expandIcon.src = this.isExpanded ? this.tree.expandIconSrcMinus : this.tree.expandIconSrcPlus;
-		} else {
-			this.expandIcon.src = this.tree.blankIconSrc;
-		}
-	},
-
-	/* set the grid under the expand icon */
-	updateExpandGrid: function() {
-
-		if (this.tree.showGrid){
-			if (this.depth){
-				this.setGridImage(-2, this.isLastNode() ? this.tree.gridIconSrcL : this.tree.gridIconSrcT);
-			}else{
-				if (this.isFirstNode()){
-					this.setGridImage(-2, this.isLastNode() ? this.tree.gridIconSrcX : this.tree.gridIconSrcY);
-				}else{
-					this.setGridImage(-2, this.isLastNode() ? this.tree.gridIconSrcL : this.tree.gridIconSrcT);
-				}
-			}
-		}else{
-			this.setGridImage(-2, this.tree.blankIconSrc);
-		}
-
-	},
-
-	/* set the grid under the child icon */
-	updateChildGrid: function() {
-
-		if ((this.depth || this.tree.showRootGrid) && this.tree.showGrid){
-			this.setGridImage(-1, (this.children.length && this.isExpanded) ? this.tree.gridIconSrcP : this.tree.gridIconSrcC);
-		}else{
-			if (this.tree.showGrid && !this.tree.showRootGrid){
-				this.setGridImage(-1, (this.children.length && this.isExpanded) ? this.tree.gridIconSrcZ : this.tree.blankIconSrc);
-			}else{
-				this.setGridImage(-1, this.tree.blankIconSrc);
-			}
-		}
-
-
-	},
-
-	updateParentGrid: function() {
-		var parent = this.parent;
-
-		//dojo.debug("updateParentGrid "+this);
-
-		for(var i=0; i<this.depth; i++){
-
-			//dojo.debug("Parent "+parent);
-
-			var idx = this.imgs.length-(3+i);
-			var img = (this.tree.showGrid && !parent.isLastNode()) ? this.tree.gridIconSrcV : this.tree.blankIconSrc;
-
-			//dojo.debug("Image "+img+" for "+idx);
-
-			this.setGridImage(idx, img);
-
-			parent = parent.parent;
-		}
-	},
-
-	updateExpandGridColumn: function() {
-		if (!this.tree.showGrid) return;
-
-		var _this = this;
-
-		var icon = this.isLastNode() ? this.tree.blankIconSrc : this.tree.gridIconSrcV;
-
-		dojo.lang.forEach(_this.getDescendants(),
-			function(node) { node.setGridImage(_this.depth, icon); }
-		);
-
-		this.updateExpandGrid();
-	},
-
-	updateIcons: function(){
-
-
-		//dojo.profile.start("updateIcons")
-
-		//dojo.debug("Update icons for "+this)
-		//dojo.debug(this.isFolder)
-
-		this.imgs[0].style.display = this.tree.showRootGrid ? 'inline' : 'none';
-
-
-		//
-		// set the expand icon
-		//
-
-
-		//
-		// set the child icon
-		//
-		this.buildChildIcon();
-
-		this.updateExpandGrid();
-		this.updateChildGrid();
-		this.updateParentGrid();
-
-
-
-		dojo.profile.stop("updateIcons")
-
-	},
-
-	buildChildIcon: function() {
-		// IE (others?) tries to download whatever is on src attribute so setting "url()" like before isnt a good idea
-		// Only results in a 404
-		if(this.childIconSrc){
-			this.childIcon.src = this.childIconSrc;
-		}
-		this.childIcon.style.display = this.childIconSrc ? 'inline' : 'none';
-	},
-
-	setGridImage: function(idx, src){
-
-		if (idx < 0){
-			idx = this.imgs.length + idx;
-		}
-
-		//if (idx >= this.imgs.length-2) return;
-		this.imgs[idx].style.backgroundImage = 'url(' + src + ')';
-	},
-
-
-	updateIconTree: function(){
-		this.tree.updateIconTree.call(this);
-	},
-
-
-
-
-	expand: function(){
-		if (this.isExpanded) return;
-
-		if (this.children.length) {
-			this.showChildren();
-		}
-
-		this.isExpanded = true;
-
-		this.updateExpandIcon();
-
-		dojo.event.topic.publish(this.tree.eventNames.expand, {source: this} );
-	},
-
-	collapse: function(){
-		if (!this.isExpanded) return;
-
-		this.hideChildren();
-		this.isExpanded = false;
-
-		this.updateExpandIcon();
-
-		dojo.event.topic.publish(this.tree.eventNames.collapse, {source: this} );
-	},
-
-	hideChildren: function(){
-		this.tree.toggleObj.hide(
-			this.containerNode, this.toggleDuration, this.explodeSrc, dojo.lang.hitch(this, "onHide")
-		);
-
-		/* if dnd is in action, recalculate changed coordinates */
-		if(dojo.exists(dojo, 'dnd.dragManager.dragObjects') && dojo.dnd.dragManager.dragObjects.length) {
-			dojo.dnd.dragManager.cacheTargetLocations();
-		}
-	},
-
-	showChildren: function(){
-		this.tree.toggleObj.show(
-			this.containerNode, this.toggleDuration, this.explodeSrc, dojo.lang.hitch(this, "onShow")
-		);
-
-		/* if dnd is in action, recalculate changed coordinates */
-		if(dojo.exists(dojo, 'dnd.dragManager.dragObjects') && dojo.dnd.dragManager.dragObjects.length) {
-			dojo.dnd.dragManager.cacheTargetLocations();
-		}
-	},
-
-	addChild: function(){
-		return this.tree.addChild.apply(this, arguments);
-	},
-
-	doAddChild: function(){
-		return this.tree.doAddChild.apply(this, arguments);
-	},
-
-
-
-	/* Edit current node : change properties and update contents */
-	edit: function(props) {
-		dojo.lang.mixin(this, props);
-		if (props.title) {
-			this.titleNode.innerHTML = this.title;
-		}
-
-		if (props.afterLabel) {
-			this.afterLabelNode.innerHTML = this.afterLabel;
-		}
-
-		if (props.childIconSrc) {
-			this.buildChildIcon();
-		}
-
-
-	},
-
-
-	removeNode: function(){ return this.tree.removeNode.apply(this, arguments) },
-	doRemoveNode: function(){ return this.tree.doRemoveNode.apply(this, arguments) },
-
-
-	toString: function() {
-		return "["+this.widgetType+" Tree:"+this.tree+" ID:"+this.widgetId+" Title:"+this.title+"]";
-
-	}
-
-});
-
-
-
-
+
+dojo.provide("dojo.widget.TreeNode");
+
+dojo.require("dojo.event.*");
+dojo.require("dojo.io.*");
+
+// make it a tag
+dojo.widget.tags.addParseTreeHandler("dojo:TreeNode");
+
+
+// # //////////
+
+dojo.widget.TreeNode = function() {
+	dojo.widget.HtmlWidget.call(this);
+
+	this.actionsDisabled = [];
+}
+
+dojo.inherits(dojo.widget.TreeNode, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.TreeNode, {
+	widgetType: "TreeNode",
+
+	loadStates: {
+		UNCHECKED: "UNCHECKED",
+    	LOADING: "LOADING",
+    	LOADED: "LOADED"
+	},
+
+
+	actions: {
+		MOVE: "MOVE",
+    	REMOVE: "REMOVE",
+    	EDIT: "EDIT",
+    	ADDCHILD: "ADDCHILD"
+	},
+
+	isContainer: true,
+
+	lockLevel: 0, // lock ++ unlock --, so nested locking works fine
+
+
+	templateString: ('<div class="dojoTreeNode"> '
+		+ '<span treeNode="${this.widgetId}" class="dojoTreeNodeLabel" dojoAttachPoint="labelNode"> '
+		+ '		<span dojoAttachPoint="titleNode" dojoAttachEvent="onClick: onTitleClick" class="dojoTreeNodeLabelTitle">${this.title}</span> '
+		+ '</span> '
+		+ '<span class="dojoTreeNodeAfterLabel" dojoAttachPoint="afterLabelNode">${this.afterLabel}</span> '
+		+ '<div dojoAttachPoint="containerNode" style="display:none"></div> '
+		+ '</div>').replace(/(>|<)\s+/g, '$1'), // strip whitespaces between nodes
+
+
+	childIconSrc: "",
+	childIconFolderSrc: dojo.uri.dojoUri("src/widget/templates/images/Tree/closed.gif"), // for under root parent item child icon,
+	childIconDocumentSrc: dojo.uri.dojoUri("src/widget/templates/images/Tree/document.gif"), // for under root parent item child icon,
+
+	childIcon: null,
+	isTreeNode: true,
+
+	objectId: "", // the widget represents an object
+
+	afterLabel: "",
+	afterLabelNode: null, // node to the left of labelNode
+
+	// an icon left from childIcon: imgs[-2].
+	// if +/- for folders, blank for leaves
+	expandIcon: null,
+
+	title: "",
+	object: "", // node may have object attached, settable from HTML
+	isFolder: false,
+
+	labelNode: null, // the item label
+	titleNode: null, // the item title
+	imgs: null, // an array of icons imgs
+
+	expandLevel: "", // expand to level
+
+	tree: null,
+
+	depth: 0,
+
+	isExpanded: false,
+
+	state: null,  // after creation will change to loadStates: "loaded/loading/unchecked"
+	domNodeInitialized: false,  // domnode is initialized with icons etc
+
+
+	isFirstNode: function() {
+		return this.getParentIndex() == 0 ? true: false;
+	},
+
+	isLastNode: function() {
+		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;
+
+		var disabled = false;
+
+		if (this.tree.strictFolders && action == this.actions.ADDCHILD && !this.isFolder) {
+			disabled = true;
+		}
+
+		if (dojo.lang.inArray(_this.actionsDisabled, action)) {
+			disabled = true;
+		}
+
+		if (this.isLocked()) {
+			disabled = true;
+		}
+
+		return disabled;
+	},
+
+	getInfo: function() {
+		// No title here (title may be widget)
+		var info = {
+			widgetId: this.widgetId,
+			objectId: this.objectId,
+			index: this.getParentIndex(),
+			isFolder: this.isFolder
+		}
+
+		return info;
+	},
+
+	initialize: function(args, frag){
+
+		//dojo.debug(this.title)
+
+		this.state = this.loadStates.UNCHECKED;
+
+		for(var i=0; i<this.actionsDisabled.length; i++) {
+			this.actionsDisabled[i] = this.actionsDisabled[i].toUpperCase();
+		}
+
+		this.expandLevel = parseInt(this.expandLevel);
+
+	},
+
+
+	/**
+	 * Change visible node depth by appending/prepending with blankImgs
+	 * @param depthDiff Integer positive => move right, negative => move left
+	*/
+	adjustDepth: function(depthDiff) {
+
+		for(var i=0; i<this.children.length; i++) {
+			this.children[i].adjustDepth(depthDiff);
+		}
+
+		this.depth += depthDiff;
+
+		if (depthDiff>0) {
+			for(var i=0; i<depthDiff; i++) {
+				var img = this.tree.makeBlankImg();
+				this.imgs.unshift(img);
+				//dojo.debugShallow(this.domNode);
+				dojo.dom.insertBefore(this.imgs[0], this.domNode.firstChild);
+
+			}
+		}
+		if (depthDiff<0) {
+			for(var i=0; i<-depthDiff;i++) {
+				this.imgs.shift();
+				dojo.dom.removeNode(this.domNode.firstChild);
+			}
+		}
+
+	},
+
+
+	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');
+		this.expandIcon.src = this.isExpanded ? this.tree.expandIconSrcMinus : this.tree.expandIconSrcPlus;
+		this.isFolder = true;
+	},
+
+
+	createDOMNode: function(tree, depth){
+
+		this.tree = tree;
+		this.depth = depth;
+
+
+		//
+		// add the tree icons
+		//
+
+		this.imgs = [];
+
+		for(var i=0; i<this.depth+1; i++){
+
+			var img = this.tree.makeBlankImg();
+
+			this.domNode.insertBefore(img, this.labelNode);
+
+			this.imgs.push(img);
+		}
+
+
+		this.expandIcon = this.imgs[this.imgs.length-1];
+
+
+		this.childIcon = this.tree.makeBlankImg();
+
+		// add to images before the title
+		this.imgs.push(this.childIcon);
+
+		dojo.dom.insertBefore(this.childIcon, this.titleNode);
+
+		// node with children(from source html) becomes folder on build stage.
+		if (this.children.length || this.isFolder) {
+			this.setFolder();
+		}
+		else {
+			// leaves are always loaded
+			//dojo.debug("Set "+this+" state to loaded");
+			this.state = this.loadStates.LOADED;
+		}
+
+		dojo.event.connect(this.childIcon, 'onclick', this, 'onIconClick');
+
+
+		//
+		// create the child rows
+		//
+
+
+		for(var i=0; i<this.children.length; i++){
+			this.children[i].parent = this;
+
+			var node = this.children[i].createDOMNode(this.tree, this.depth+1);
+
+			this.containerNode.appendChild(node);
+		}
+
+
+		if (this.children.length) {
+			this.state = this.loadStates.LOADED;
+		}
+
+		this.updateIcons();
+
+		this.domNodeInitialized = true;
+
+		dojo.event.topic.publish(this.tree.eventNames.createDOMNode, { source: this } );
+
+		return this.domNode;
+	},
+
+	onTreeClick: function(e){
+		dojo.event.topic.publish(this.tree.eventNames.treeClick, { source: this, event: e });
+	},
+
+	onIconClick: function(e){
+		dojo.event.topic.publish(this.tree.eventNames.iconClick, { source: this, event: e });
+	},
+
+	onTitleClick: function(e){
+		dojo.event.topic.publish(this.tree.eventNames.titleClick, { source: this, event: e });
+	},
+
+	markSelected: function() {
+		dojo.html.addClass(this.titleNode, 'dojoTreeNodeLabelSelected');
+	},
+
+
+	unMarkSelected: function() {
+		//dojo.debug('unmark')
+		dojo.html.removeClass(this.titleNode, 'dojoTreeNodeLabelSelected');
+	},
+
+	updateExpandIcon: function() {
+		if (this.isFolder){
+			this.expandIcon.src = this.isExpanded ? this.tree.expandIconSrcMinus : this.tree.expandIconSrcPlus;
+		} else {
+			this.expandIcon.src = this.tree.blankIconSrc;
+		}
+	},
+
+	/* set the grid under the expand icon */
+	updateExpandGrid: function() {
+
+		if (this.tree.showGrid){
+			if (this.depth){
+				this.setGridImage(-2, this.isLastNode() ? this.tree.gridIconSrcL : this.tree.gridIconSrcT);
+			}else{
+				if (this.isFirstNode()){
+					this.setGridImage(-2, this.isLastNode() ? this.tree.gridIconSrcX : this.tree.gridIconSrcY);
+				}else{
+					this.setGridImage(-2, this.isLastNode() ? this.tree.gridIconSrcL : this.tree.gridIconSrcT);
+				}
+			}
+		}else{
+			this.setGridImage(-2, this.tree.blankIconSrc);
+		}
+
+	},
+
+	/* set the grid under the child icon */
+	updateChildGrid: function() {
+
+		if ((this.depth || this.tree.showRootGrid) && this.tree.showGrid){
+			this.setGridImage(-1, (this.children.length && this.isExpanded) ? this.tree.gridIconSrcP : this.tree.gridIconSrcC);
+		}else{
+			if (this.tree.showGrid && !this.tree.showRootGrid){
+				this.setGridImage(-1, (this.children.length && this.isExpanded) ? this.tree.gridIconSrcZ : this.tree.blankIconSrc);
+			}else{
+				this.setGridImage(-1, this.tree.blankIconSrc);
+			}
+		}
+
+
+	},
+
+	updateParentGrid: function() {
+		var parent = this.parent;
+
+		//dojo.debug("updateParentGrid "+this);
+
+		for(var i=0; i<this.depth; i++){
+
+			//dojo.debug("Parent "+parent);
+
+			var idx = this.imgs.length-(3+i);
+			var img = (this.tree.showGrid && !parent.isLastNode()) ? this.tree.gridIconSrcV : this.tree.blankIconSrc;
+
+			//dojo.debug("Image "+img+" for "+idx);
+
+			this.setGridImage(idx, img);
+
+			parent = parent.parent;
+		}
+	},
+
+	updateExpandGridColumn: function() {
+		if (!this.tree.showGrid) return;
+
+		var _this = this;
+
+		var icon = this.isLastNode() ? this.tree.blankIconSrc : this.tree.gridIconSrcV;
+
+		dojo.lang.forEach(_this.getDescendants(),
+			function(node) { node.setGridImage(_this.depth, icon); }
+		);
+
+		this.updateExpandGrid();
+	},
+
+	updateIcons: function(){
+
+
+		//dojo.profile.start("updateIcons")
+
+		//dojo.debug("Update icons for "+this)
+		//dojo.debug(this.isFolder)
+
+		this.imgs[0].style.display = this.tree.showRootGrid ? 'inline' : 'none';
+
+
+		//
+		// set the expand icon
+		//
+
+
+		//
+		// set the child icon
+		//
+		this.buildChildIcon();
+
+		this.updateExpandGrid();
+		this.updateChildGrid();
+		this.updateParentGrid();
+
+
+
+		dojo.profile.stop("updateIcons")
+
+	},
+
+	buildChildIcon: function() {
+		// IE (others?) tries to download whatever is on src attribute so setting "url()" like before isnt a good idea
+		// Only results in a 404
+		if(this.childIconSrc){
+			this.childIcon.src = this.childIconSrc;
+		}
+		this.childIcon.style.display = this.childIconSrc ? 'inline' : 'none';
+	},
+
+	setGridImage: function(idx, src){
+
+		if (idx < 0){
+			idx = this.imgs.length + idx;
+		}
+
+		//if (idx >= this.imgs.length-2) return;
+		this.imgs[idx].style.backgroundImage = 'url(' + src + ')';
+	},
+
+
+	updateIconTree: function(){
+		this.tree.updateIconTree.call(this);
+	},
+
+
+
+
+	expand: function(){
+		if (this.isExpanded) return;
+
+		if (this.children.length) {
+			this.showChildren();
+		}
+
+		this.isExpanded = true;
+
+		this.updateExpandIcon();
+
+		dojo.event.topic.publish(this.tree.eventNames.expand, {source: this} );
+	},
+
+	collapse: function(){
+		if (!this.isExpanded) return;
+
+		this.hideChildren();
+		this.isExpanded = false;
+
+		this.updateExpandIcon();
+
+		dojo.event.topic.publish(this.tree.eventNames.collapse, {source: this} );
+	},
+
+	hideChildren: function(){
+		this.tree.toggleObj.hide(
+			this.containerNode, this.toggleDuration, this.explodeSrc, dojo.lang.hitch(this, "onHide")
+		);
+
+		/* if dnd is in action, recalculate changed coordinates */
+		if(dojo.exists(dojo, 'dnd.dragManager.dragObjects') && dojo.dnd.dragManager.dragObjects.length) {
+			dojo.dnd.dragManager.cacheTargetLocations();
+		}
+	},
+
+	showChildren: function(){
+		this.tree.toggleObj.show(
+			this.containerNode, this.toggleDuration, this.explodeSrc, dojo.lang.hitch(this, "onShow")
+		);
+
+		/* if dnd is in action, recalculate changed coordinates */
+		if(dojo.exists(dojo, 'dnd.dragManager.dragObjects') && dojo.dnd.dragManager.dragObjects.length) {
+			dojo.dnd.dragManager.cacheTargetLocations();
+		}
+	},
+
+	addChild: function(){
+		return this.tree.addChild.apply(this, arguments);
+	},
+
+	doAddChild: function(){
+		return this.tree.doAddChild.apply(this, arguments);
+	},
+
+
+
+	/* Edit current node : change properties and update contents */
+	edit: function(props) {
+		dojo.lang.mixin(this, props);
+		if (props.title) {
+			this.titleNode.innerHTML = this.title;
+		}
+
+		if (props.afterLabel) {
+			this.afterLabelNode.innerHTML = this.afterLabel;
+		}
+
+		if (props.childIconSrc) {
+			this.buildChildIcon();
+		}
+
+
+	},
+
+
+	removeNode: function(){ return this.tree.removeNode.apply(this, arguments) },
+	doRemoveNode: function(){ return this.tree.doRemoveNode.apply(this, arguments) },
+
+
+	toString: function() {
+		return "["+this.widgetType+" Tree:"+this.tree+" ID:"+this.widgetId+" Title:"+this.title+"]";
+
+	}
+
+});
+
+
+
+

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeSelector.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeSelector.js?rev=413306&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeSelector.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeSelector.js Sat Jun 10 07:27:44 2006
@@ -0,0 +1,180 @@
+/*
+	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.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) {
+			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/framework/src/js/dojo/src/widget/TreeSelector.js
------------------------------------------------------------------------------
    svn:eol-style = native