(function($){
// create the master widget
$.widget("ui.widget",{
	// Aspect Oriented Programming tools from Justin Palmer's article
	yield: null,
	returnValues: { },
	before: function(method, f) {
		var original = this[method];
		this[method] = function() {
			f.apply(this, arguments);
			return original.apply(this, arguments);
		};
	},
	after: function(method, f) {
		var original = this[method];
		this[method] = function() {
			this.returnValues[method] = original.apply(this, arguments);
			return f.apply(this, arguments);
		}
	},
	around: function(method, f) {
		var original = this[method];
		this[method] = function() {
			var tmp = this.yield;
			this.yield = original;
			var ret = f.apply(this, arguments);
			this.yield = tmp;
			return ret;
		}
	}
});

// allow extending the defaults object
$.ui.widget.defaults = {extend: $.extend};

// from http://groups.google.com/group/comp.lang.javascript/msg/e04726a66face2a2 and
// http://webreflection.blogspot.com/2008/10/big-douglas-begetobject-revisited.html
var object = (function(F){
	return (function(o){
			F.prototype = o;
			return new F();
	});
})(function (){});

// create a widget subclass
var OVERRIDE = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

$.ui.widget.subclass = function subclass(name){
	$.widget(name); // Slightly inefficient to create a widget only to discard its prototype, but it's not too bad
	name = name.split('.');
	var widget = $[name[0]][name[1]], superclass = this, superproto = superclass.prototype;
	
	var proto = arguments[0] = widget.prototype = object(superproto); // inherit from the superclass
	$.extend.apply(null, arguments); // and add other add-in methods to the prototype
	widget.subclass = subclass;
	widget.defaults = object(superclass.defaults);
	widget.getter = this.getter;
	widget.getterSetter = this.getterSetter;
	// getter/setter methods need to be extended by hand, since they are added later. Supposedly
	// this will improve in a future version of UI
	// (http://groups.google.com/group/jquery-ui/browse_thread/thread/986806814429be9a/9140780072dc4393#msg_688741428cd19a25)
	
	// Subtle point: we want to call superclass init and destroy if they exist
	// (otherwise the user of this function would have to keep track of all that)
	proto.super_ = superproto;
	for (key in proto) if (proto.hasOwnProperty(key)) switch (key){
		case '_init':
			var init = proto._init;
			proto._init = function(){
				superproto._init.apply(this);
				init.apply(this);
			};
		break;
		case 'destroy':
			var destroy = proto.destroy;
			proto.destroy = function(){
				destroy.apply(this);
				superproto.destroy.apply(this);
			};
		break;
		default: 
			if ($.isFunction(proto[key]) && $.isFunction(superproto[key]) && OVERRIDE.test(proto[key])){
				proto[key] = (function(name, fn){
					return function() {
						var tmp = this._super;
						this._super = superproto[name];
						try { var ret = fn.apply(this, arguments); }   
						finally { this._super = tmp;}					
						return ret;
					};
				})(key, proto[key]);
			}
		break;
	}
};
})(jQuery)