text: //>>built
  define("dojo/Stateful", ["./_base/kernel", "./_base/declare", "./_base/lang", "./_base/array"], function(dojo, declare, lang, array) {
  	// module:
  	//		dojo/Stateful
  	// summary:
  	//		TODOC
  
  return dojo.declare("dojo.Stateful", null, {
  	// summary:
  	//		Base class for objects that provide named properties with optional getter/setter
  	//		control and the ability to watch for property changes
  	// example:
  	//	|	var obj = new dojo.Stateful();
  	//	|	obj.watch("foo", function(){
  	//	|		console.log("foo changed to " + this.get("foo"));
  	//	|	});
  	//	|	obj.set("foo","bar");
  	postscript: function(mixin){
  		if(mixin){
  			lang.mixin(this, mixin);
  		}
  	},
  
  	get: function(/*String*/name){
  		// summary:
  		//		Get a property on a Stateful instance.
  		//	name:
  		//		The property to get.
  		//	returns:
  		//		The property value on this Stateful instance.
  		// description:
  		//		Get a named property on a Stateful object. The property may
  		//		potentially be retrieved via a getter method in subclasses. In the base class
  		// 		this just retrieves the object's property.
  		// 		For example:
  		//	|	stateful = new dojo.Stateful({foo: 3});
  		//	|	stateful.get("foo") // returns 3
  		//	|	stateful.foo // returns 3
  
  		return this[name]; //Any
  	},
  	set: function(/*String*/name, /*Object*/value){
  		// summary:
  		//		Set a property on a Stateful instance
  		//	name:
  		//		The property to set.
  		//	value:
  		//		The value to set in the property.
  		//	returns:
  		//		The function returns this dojo.Stateful instance.
  		// description:
  		//		Sets named properties on a stateful object and notifies any watchers of
  		// 		the property. A programmatic setter may be defined in subclasses.
  		// 		For example:
  		//	|	stateful = new dojo.Stateful();
  		//	|	stateful.watch(function(name, oldValue, value){
  		//	|		// this will be called on the set below
  		//	|	}
  		//	|	stateful.set(foo, 5);
  		//
  		//	set() may also be called with a hash of name/value pairs, ex:
  		//	|	myObj.set({
  		//	|		foo: "Howdy",
  		//	|		bar: 3
  		//	|	})
  		//	This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
  		if(typeof name === "object"){
  			for(var x in name){
  				this.set(x, name[x]);
  			}
  			return this;
  		}
  		var oldValue = this[name];
  		this[name] = value;
  		if(this._watchCallbacks){
  			this._watchCallbacks(name, oldValue, value);
  		}
  		return this; //dojo.Stateful
  	},
  	watch: function(/*String?*/name, /*Function*/callback){
  		// summary:
  		//		Watches a property for changes
  		//	name:
  		//		Indicates the property to watch. This is optional (the callback may be the
  		// 		only parameter), and if omitted, all the properties will be watched
  		// returns:
  		//		An object handle for the watch. The unwatch method of this object
  		// 		can be used to discontinue watching this property:
  		//		|	var watchHandle = obj.watch("foo", callback);
  		//		|	watchHandle.unwatch(); // callback won't be called now
  		//	callback:
  		//		The function to execute when the property changes. This will be called after
  		//		the property has been changed. The callback will be called with the |this|
  		//		set to the instance, the first argument as the name of the property, the
  		// 		second argument as the old value and the third argument as the new value.
  
  		var callbacks = this._watchCallbacks;
  		if(!callbacks){
  			var self = this;
  			callbacks = this._watchCallbacks = function(name, oldValue, value, ignoreCatchall){
  				var notify = function(propertyCallbacks){
  					if(propertyCallbacks){
                          propertyCallbacks = propertyCallbacks.slice();
  						for(var i = 0, l = propertyCallbacks.length; i < l; i++){
  							try{
  								propertyCallbacks[i].call(self, name, oldValue, value);
  							}catch(e){
  								console.error(e);
  							}
  						}
  					}
  				};
  				notify(callbacks['_' + name]);
  				if(!ignoreCatchall){
  					notify(callbacks["*"]); // the catch-all
  				}
  			}; // we use a function instead of an object so it will be ignored by JSON conversion
  		}
  		if(!callback && typeof name === "function"){
  			callback = name;
  			name = "*";
  		}else{
  			// prepend with dash to prevent name conflicts with function (like "name" property)
  			name = '_' + name;
  		}
  		var propertyCallbacks = callbacks[name];
  		if(typeof propertyCallbacks !== "object"){
  			propertyCallbacks = callbacks[name] = [];
  		}
  		propertyCallbacks.push(callback);
  		return {
  			unwatch: function(){
  				propertyCallbacks.splice(array.indexOf(propertyCallbacks, callback), 1);
  			}
  		}; //Object
  	}
  
  });
  
  });
  