text: dojo.provide("dijit.layout._LayoutWidget");
  
  dojo.require("dijit._Widget");
  dojo.require("dijit._Container");
  
  dojo.declare("dijit.layout._LayoutWidget",
  	[dijit._Widget, dijit._Container, dijit._Contained],
  	{
  		// summary
  		//		Mixin for widgets that contain a list of children like SplitContainer.
  		//		Widgets which mixin this code must define layout() to lay out the children
  
  		// baseClass: String
  		//		This class name is applied to the widget's domNode
  		//		and also may be used to generate names for sub nodes,
  		//		like for example dijitTabContainer-content.
  		baseClass: "dijitLayoutContainer",
  
  		isLayoutContainer: true,
  
  		postCreate: function(){
  			dojo.addClass(this.domNode, "dijitContainer");
  			dojo.addClass(this.domNode, this.baseClass);
  		},
  
  		startup: function(){
  			// summary:
  			//		Called after all the widgets have been instantiated and their
  			//		dom nodes have been inserted somewhere under dojo.doc.body.
  			//
  			//		Widgets should override this method to do any initialization
  			//		dependent on other widgets existing, and then call
  			//		this superclass method to finish things off.
  			//
  			//		startup() in subclasses shouldn't do anything
  			//		size related because the size of the widget hasn't been set yet.
  
  			if(this._started){ return; }
  
  			dojo.forEach(this.getChildren(), function(child){ child.startup(); });
  
  			// If I am a top level widget
  			if(!this.getParent || !this.getParent()){
  				// Do recursive sizing and layout of all my descendants
  				// (passing in no argument to resize means that it has to glean the size itself)
  				this.resize();
  
  				// since my parent isn't a layout container, and my style is width=height=100% (or something similar),
  				// then I need to watch when the window resizes, and size myself accordingly
  				// (passing in no argument to resize means that it has to glean the size itself)
  				this.connect(dojo.global, 'onresize', 'resize');
  			}
  			
  			this.inherited(arguments);
  		},
  
  		resize: function(changeSize, resultSize){
  			// summary:
  			//		Call this to resize a widget, or after it's size has changed.
  			// description:
  			//		Change size mode:
  			//			When changeSize is specified, changes the marginBox of this widget
  			//			 and forces it to relayout it's contents accordingly.
  			//			changeSize may specify height, width, or both.
  			//
  			//			If resultSize is specified it indicates the size the widget will
  			//			become after changeSize has been applied.
  			//
  			//		Notification mode:
  			//			When changeSize is null, indicates that the caller has already changed
  			//			the size of the widget, or perhaps it changed because the browser
  			//			window was resized.  Tells widget to relayout it's contents accordingly.
  			//
  			//			If resultSize is also specified it indicates the size the widget has
  			//			become.
  			//
  			//		In either mode, this method also:
  			//			1. Sets this._borderBox and this._contentBox to the new size of
  			//				the widget.  Queries the current domNode size if necessary.
  			//			2. Calls layout() to resize contents (and maybe adjust child widgets).	
  			//
  			// changeSize: Object?
  			//		Sets the widget to this margin-box size and position.
  			//		May include any/all of the following properties:
  			//	|	{w: int, h: int, l: int, t: int}
  			//
  			// resultSize: Object?
  			//		The margin-box size of this widget after applying changeSize (if 
  			//		changeSize is specified).  If caller knows this size and
  			//		passes it in, we don't need to query the browser to get the size.
  			//	|	{w: int, h: int}
  
  			var node = this.domNode;
  
  			// set margin box size, unless it wasn't specified, in which case use current size
  			if(changeSize){
  				dojo.marginBox(node, changeSize);
  
  				// set offset of the node
  				if(changeSize.t){ node.style.top = changeSize.t + "px"; }
  				if(changeSize.l){ node.style.left = changeSize.l + "px"; }
  			}
  
  			// If either height or width wasn't specified by the user, then query node for it.
  			// But note that setting the margin box and then immediately querying dimensions may return
  			// inaccurate results, so try not to depend on it.
  			var mb = resultSize || {};
  			dojo.mixin(mb, changeSize || {});	// changeSize overrides resultSize
  			if ( !("h" in mb) || !("w" in mb) ){
  				mb = dojo.mixin(dojo.marginBox(node), mb);	// just use dojo.marginBox() to fill in missing values
  			}
  
  			// Compute and save the size of my border box and content box
  			// (w/out calling dojo.contentBox() since that may fail if size was recently set)
  			var cs = dojo.getComputedStyle(node);
  			var me = dojo._getMarginExtents(node, cs);
  			var be = dojo._getBorderExtents(node, cs);
  			var bb = this._borderBox = {
  				w: mb.w - (me.w + be.w),
  				h: mb.h - (me.h + be.h)
  			};
  			var pe = dojo._getPadExtents(node, cs);
  			this._contentBox = {
  				l: dojo._toPixelValue(node, cs.paddingLeft),
  				t: dojo._toPixelValue(node, cs.paddingTop),
  				w: bb.w - pe.w,
  				h: bb.h - pe.h
  			};
  
  			// Callback for widget to adjust size of it's children
  			this.layout();
  		},
  
  		layout: function(){
  			//	summary
  			//		Widgets override this method to size & position their contents/children.
  			//		When this is called this._contentBox is guaranteed to be set (see resize()).
  			//
  			//		This is called after startup(), and also when the widget's size has been
  			//		changed.
  		},
  
  		_setupChild: function(/*Widget*/child){
  			// summary: common setup for initial children or children which are added after startup
  			if(child.baseClass){
  				dojo.addClass(child.domNode, this.baseClass+"-"+child.baseClass);
  			}
  		},
  
  		addChild: function(/*Widget*/ child, /*Integer?*/ insertIndex){
  			this.inherited(arguments);
  			if(this._started){
  				this._setupChild(child);
  			}
  		},
  
  		removeChild: function(/*Widget*/ child){
  			if(child.baseClass){
  				dojo.removeClass(child.domNode, this.baseClass+"-"+child.baseClass);
  			}
  			this.inherited(arguments);
  		}
  	}
  );
  
  dijit.layout.marginBox2contentBox = function(/*DomNode*/ node, /*Object*/ mb){
  	// summary:
  	//		Given the margin-box size of a node, return it's content box size.
  	//		Functions like dojo.contentBox() but is more reliable since it doesn't have
  	//		to wait for the browser to compute sizes.
  	var cs = dojo.getComputedStyle(node);
  	var me = dojo._getMarginExtents(node, cs);
  	var pb = dojo._getPadBorderExtents(node, cs);
  	return {
  		l: dojo._toPixelValue(node, cs.paddingLeft),
  		t: dojo._toPixelValue(node, cs.paddingTop),
  		w: mb.w - (me.w + pb.w),
  		h: mb.h - (me.h + pb.h)
  	};
  };
  
  (function(){
  	var capitalize = function(word){
  		return word.substring(0,1).toUpperCase() + word.substring(1);
  	};
  
  	var size = function(widget, dim){
  		// size the child
  		widget.resize ? widget.resize(dim) : dojo.marginBox(widget.domNode, dim);
  
  		// record child's size, but favor our own numbers when we have them.
  		// the browser lies sometimes
  		dojo.mixin(widget, dojo.marginBox(widget.domNode));
  		dojo.mixin(widget, dim);
  	};
  
  	dijit.layout.layoutChildren = function(/*DomNode*/ container, /*Object*/ dim, /*Object[]*/ children){
  		/**
  		 * summary
  		 *		Layout a bunch of child dom nodes within a parent dom node
  		 * container:
  		 *		parent node
  		 * dim:
  		 *		{l, t, w, h} object specifying dimensions of container into which to place children
  		 * children:
  		 *		an array like [ {domNode: foo, layoutAlign: "bottom" }, {domNode: bar, layoutAlign: "client"} ]
  		 */
  
  		// copy dim because we are going to modify it
  		dim = dojo.mixin({}, dim);
  
  		dojo.addClass(container, "dijitLayoutContainer");
  
  		// Move "client" elements to the end of the array for layout.  a11y dictates that the author
  		// needs to be able to put them in the document in tab-order, but this algorithm requires that
  		// client be last.
  		children = dojo.filter(children, function(item){ return item.layoutAlign != "client"; })
  			.concat(dojo.filter(children, function(item){ return item.layoutAlign == "client"; }));
  
  		// set positions/sizes
  		dojo.forEach(children, function(child){
  			var elm = child.domNode,
  				pos = child.layoutAlign;
  
  			// set elem to upper left corner of unused space; may move it later
  			var elmStyle = elm.style;
  			elmStyle.left = dim.l+"px";
  			elmStyle.top = dim.t+"px";
  			elmStyle.bottom = elmStyle.right = "auto";
  
  			dojo.addClass(elm, "dijitAlign" + capitalize(pos));
  
  			// set size && adjust record of remaining space.
  			// note that setting the width of a <div> may affect it's height.
  			if(pos == "top" || pos == "bottom"){
  				size(child, { w: dim.w });
  				dim.h -= child.h;
  				if(pos=="top"){
  					dim.t += child.h;
  				}else{
  					elmStyle.top = dim.t + dim.h + "px";
  				}
  			}else if(pos == "left" || pos == "right"){
  				size(child, { h: dim.h });
  				dim.w -= child.w;
  				if(pos == "left"){
  					dim.l += child.w;
  				}else{
  					elmStyle.left = dim.l + dim.w + "px";
  				}
  			}else if(pos == "client"){
  				size(child, dim);
  			}
  		});
  	};
  
  })();
  