var Dictionary = new Native({
	
	name: 'Dictionary',
	
	initialize: function(){
		this.keys = [];
		this.values = [];
	}
	
});


Dictionary.implement({
	
	getKey: function(value){
		var idx = this.values.indexOf(value);
		return (idx > -1) ? this.keys[idx] : null;
	},
		
	getValue: function(key){
		var idx = this.keys.indexOf(key);
		return (idx > -1) ? this.values[idx] : null;
	},
		
	forEach: function(fn){
		for (var i = 0, l = this.keys.length; i < l; i++){
			fn.call(this, this.values[i], this.keys[i], this);
		}
	},
	
	set: function(key, value, noforce){
		if (!noforce) this.erase(key);
		else if (this.getValue(key)) return this;
		this.keys.push(key);
		this.values.push(value);
		return this;
	},
	
	include: function(key, value){
		return this.set(key, value, true);
	},
	
	erase: function(key){
		var kIdx = this.keys.indexOf(key);
		if (kIdx > -1){
			this.values.splice(kIdx, 1);
			this.keys.splice(kIdx, 1);
		}
		return this;
	}
	
});

Dictionary.alias('getValue', 'get');
Dictionary.alias('forEach', 'each');Element.implement({
	
	addActions: function(actions){
		
		var doc = this.getDocument();
		
		var count = 0;
		
		var up = function(event){
			if (event.key && (event.key == 'up' || event.key == 'down')) return;
			
			actions.up.call(this, event);
			
			count = 0;

			doc.removeEvent('mouseup', up);
			doc.removeEvent('keyup', up);

		}.bind(this);
		
		var timer;
		
		var down = function(event){
			if (event.key && (event.key != 'space' && event.key != 'enter')) return;
			
			$clear(timer);
			
			actions.down.call(this, event);
			
			count = (count) ? 0 : 1;
			
			if (!count){
				up(event);
				return;
			}
			
			doc.removeEvent('mouseup', up);
			doc.removeEvent('keyup', up);

			timer = (function(){
				doc.addEvents({mouseup: up, keyup: up});
			}).delay(300);
		};
		
		this.addEvents({mousedown: down, keydown: down});
		
	}
	
});/* ART Element */

var ART = {};

Element.implement({
	
	setContent: function(content){
		return (typeof content == 'string') ? this.set('html', content) : this.adopt(content);
	},
	
	forceFocus: function(){
		this.blur();
		this.focus();
	},
	
	forceBlur: function(){
		this.focus();
		this.blur();
	}
	
});

ART.Element = new Class({
	
	Implements: [Events, Options],
	
	options: {
		/* onInject: $empty,
		onDispose: $empty,
		onGrab: $empty,*/
		subject: null,
		grabber: null
	},
	
	initialize: function(options){
		this.setOptions(options);
		this.subject = $(this.options.subject);
		this.grabber = (this.options.grabber) ? $(this.options.grabber) : this.subject;
	},
	
	inject: function(element, how){
		this.subject.inject(element, how);
		this.fireEvent('onInject', [element, this.subject]);
		return this;
	},
	
	grab: function(element, how){
		this.grabber.grab(element, how);
		this.fireEvent('onGrab', [element, this.grabber]);
		return this;
	},
	
	replaces: function(element){
		this.subject.replaces(element);
		return this;
	},
	
	adopt: function(){
		Array.flatten(arguments).each(function(element){
			this.grab(element);
		}, this);
		return this;
	},
	
	dispose: function(){
		this.fireEvent('onDispose', this.subject);
		this.subject.dispose();
		return this;
	},
	
	setStyle: function(style, value){
		this.subject.setStyle(style, value);
		return this;
	},
	
	setStyles: function(properties){
		this.subject.setStyles(properties);
		return this;
	},
	
	resize: function(size){
		this.subject.height = size.height;
		this.subject.width = size.width;
		return this;
	}

});
/* ART Ink */

ART.Ink = new Class({
	
	Extends: ART.Element,

	initialize: function(props){
		props = props || {};
		props.id = props.id || 'ART_Box_' + Native.UID++;
		var element = new Element('canvas', props);
		if (window.G_vmlCanvasManager) element = G_vmlCanvasManager.initElement(element);
		this.paint = element;
		this.canvas = this.paint.getContext('2d');
		arguments.callee.parent({subject: this.paint});
		this.save();
	},
	
	save: function(){
		this.canvas.save();
		return this;
	},
	
	restore: function(){
		this.canvas.restore();
		return this;
	},

	begin: function(p){
		this.canvas.beginPath();
		this.canvas.moveTo(p.x, p.y);
		return this;
	},

	close: function(){
		this.canvas.closePath();
		return this;
	},

	translate: function(p){
		this.canvas.translate(p.x, p.y);
		return this;
	},

	line: function(p){
		this.canvas.lineTo(p.x, p.y);
		return this;
	},

	curve: function(p, c){
		this.canvas.quadraticCurveTo(c.x, c.y, p.x, p.y);
		return this;
	},

	box: function(options){
		options = $extend({radius: 5, height: 200, width: 200}, options);
		
		var radius = options.radius, height = options.height, width = options.width, fill = options.fill;

		var tl = options['top-left-radius'];
		var tr = options['top-right-radius'];
		var bl = options['bottom-left-radius'];
		var br = options['bottom-right-radius'];

		tl = $pick(tl, radius);
		tr = $pick(tr, radius);
		bl = $pick(bl, radius);
		br = $pick(br, radius);

		this.begin({x: 0, y: height - tl});
		this.line({x: 0, y: tl}).curve({x: tl, y: 0}, {x: 0, y: 0});
		this.line({x: width - tr, y: 0}).curve({x: width, y: tr}, {x: width, y: 0});
		this.line({x: width, y: height - br}).curve({x: width - br, y: height}, {x: width, y: height});
		this.line({x: bl, y: height}).curve({x: 0, y: height - bl}, {x: 0, y: height});

		this.close();
		
		return this.fill(fill, height);
	},
	
	arc: function(center, radius, start, end, fill){
		this.canvas.arc(center.x, center.y, radius, Math.radians(start), Math.radians(end), false);
		return this.fill(fill, radius * 2);
	},
	
	block: function(options){
		this.fill(options.fill, options.height);
		this.canvas.fillRect(0, 0, options.width, options.height);
		return this;
	},
	
	draw: function(instructions){
		for (var method in instructions) this[method].run(instructions[method], this);
		return this;
	},

	fill: function(color, height){
		if (typeof color != 'string'){
			var gradient = this.canvas.createLinearGradient(0, 0, 0, height);
			var len = color.length;
			color.each(function(color, i){
				gradient.addColorStop(i / (len - 1), color);
			});
			color = gradient;
		}
		this.canvas.fillStyle = color;
		this.canvas.fill();
		return this;
	}

});

Math.radians = function(degrees){
	return degrees * (Math.PI / 180);
};/* ART Paint */

ART.Paint = new Class({
	
	Extends: ART.Ink,
	
	options: {
		id: false
	},
	
	initialize: function(options){
		this.setOptions(options);
		arguments.callee.parent({id: this.options.id});
	},
	
	colorize: function(color, alpha){
		
		var rgba = function(rgb, a){
			rgb = rgb.hexToRgb(true);
			return 'rgba(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ',' + (a).round(5) + ')';
		};
		
		switch ($type(color)){
			case 'string': return rgba(color, alpha);
			case 'array': return color.map(function(c){
				return rgba(c, alpha);
			});
		}
		
		return '#000';
	},
	
	draw: function(style){
		
		if ($type(style) != 'art:style') style = ART.Style(style);
		
		this.resize({height: style.outerHeight, width: style.outerWidth});
		
		var tl = style.topLeftRadius, tr = style.topRightRadius, bl = style.bottomLeftRadius, br = style.bottomRightRadius;
		
		var shadow = style.shadow, border = style.border, radius = style.radius, height = style.height, width = style.width;
		
		var s2 = shadow * 1.5;
		
		var trs = tr + s2, tls = tl + s2, brs = br + s2, bls = bl + s2;
		
		//shadow
		
		if (style.drawShadow) (shadow).times(function(i){
			var alpha = Fx.Transitions.Quad.easeIn(i / shadow) / shadow * style.shadowOpacity;
			this.box({
				'width': style.outerWidth - i * 2,
				'height': style.outerHeight - i * 2,
				'top-left-radius': tls - i,
				'top-right-radius': trs - i,
				'bottom-left-radius': bls - i,
				'bottom-right-radius': brs - i,
				'fill': this.colorize(style.shadowColor, alpha)
			});
			this.translate({x: 1, y: 1});
		}, this);
		else this.translate({x: shadow, y: shadow});
		
		this.translate({x: (style.shadowOffsetX > 0) ? 0 : style.shadowOffsetX, y: (style.shadowOffsetY > 0) ? 0 : style.shadowOffsetY});
		
		//border
		
		if (style.border) this.box({
			'width': style.innerWidth ,
			'height': style.innerHeight,
			'top-left-radius': tl + border,
			'top-right-radius': tr + border,
			'bottom-left-radius': bl + border,
			'bottom-right-radius': br + border,
			'fill': this.colorize(style.borderColor, style.borderOpacity)
		}).translate({x: border, y: border});
		
		//main overlay
		
		if (style.overlay){
			
			if (!style.title && style.reflection){
				this.box({
					'width': width,
					'height': height,
					'top-left-radius': tl,
					'top-right-radius': tr,
					'bottom-left-radius': bl,
					'bottom-right-radius': br,
					'fill': this.colorize(style.reflectionColors[0], style.overlayOpacity)
				}).translate({x: 0, y: style.reflection});
			}
			
			var mh = (!style.title) ? style.reflection : 0;

			this.translate({x: 0, y: style.title}).box({
				'width': width,
				'height': height - mh,
				'bottom-left-radius': style.status ? 0 : bl,
				'bottom-right-radius': style.status ? 0 : br,
				'top-left-radius': style.title ? 0 : tl,
				'top-right-radius': style.title ? 0 : tr,
				'fill': this.colorize(style.overlayColor, style.overlayOpacity)
			}).translate({x: 0, y: -style.title});

		}
		
		if (style.title){
			
			if (style.reflection) this.box({
				'width': width,
				'height': style.title,
				'top-left-radius': tl,
				'top-right-radius': tr,
				'bottom-left-radius': 0,
				'bottom-right-radius': 0,
				'fill': this.colorize(style.reflectionColors[0], style.titleOpacity)
			}).translate({x: 0, y: style.reflection});
					
			this.box({
				'width': width,
				'height': style.title - style.reflection,
				'top-left-radius': tl,
				'top-right-radius': tr,
				'bottom-left-radius': 0,
				'bottom-right-radius': 0,
				'fill': this.colorize(style.titleColor, style.titleOpacity)
			}).translate({x: 0, y: -style.reflection});
			
			if (style.line) this.translate({x: 0, y: style.title - style.line}).box({
				'width': width,
				'height': style.line,
				'radius': 0,
				'fill': this.colorize(style.lineColors[0], style.titleOpacity)
			}).translate({x: 0, y: - style.title + style.line});
			
		}
		
		if (style.status){
		
			this.translate({x: 0, y: height + style.title}).box({
				'width': width,
				'height': style.status,
				'bottom-left-radius': bl,
				'bottom-right-radius': br,
				'top-left-radius': 0,
				'top-right-radius': 0,
				'fill': this.colorize(style.statusColor, style.statusOpacity)
			});
			
			if (style.line){
				
				this.box({
					'width': width, 'height': style.line, 'radius': 0, 'fill': this.colorize(style.lineColors[1], style.statusOpacity)
				});
				
				if (style.reflection) this.translate({x: 0, y: style.line}).box({
					'width': width, 'height': style.reflection, 'radius': 0, 'fill': this.colorize(style.reflectionColors[1], style.statusOpacity)
				});
				
			}
			
		}
		
		return this;
	}
	
});/* ART Theme */

ART.Style = function(properties){
	
	var style = $merge(ART.Styles, {$family: {name: 'art:style'}}, properties);
	
	if (!style.shadow){
		style.shadowOffsetY = 0;
		style.shadowOffsetX = 0;
	}

	style.innerHeight = style.height + style.status + style.title + (style.border * 2);
	style.innerWidth = style.width + (style.border * 2);

	style.outerHeight = (style.shadow * 2) - Math.abs(style.shadowOffsetY) + style.innerHeight;
	style.outerWidth = (style.shadow * 2) - Math.abs(style.shadowOffsetX) + style.innerWidth;

	var tl = style.topLeftRadius, tr = style.topRightRadius, bl = style.bottomLeftRadius, br = style.bottomRightRadius;

	style.topLeftRadius = $pick(tl, style.radius);
	style.topRightRadius = $pick(tr, style.radius);
	style.bottomLeftRadius = $pick(bl, style.radius);
	style.bottomRightRadius = $pick(br, style.radius);

	return style;
	
};

ART.Styles = {
	
	radius: 0,

	title: 0,
	titleColor: '#CCC',
	titleOpacity: 1,

	status: 0,
	statusColor: '#CCC',
	statusOpacity: 1,

	overlay: true,
	overlayColor: '#FFF',
	overlayOpacity: 1,

	shadow: 10,
	shadowOffsetX: 0,
	shadowOffsetY: -2,
	shadowColor: '#000',
	shadowOpacity: 0.5,
	drawShadow: true,

	border: 1,
	borderColor: '#000',
	borderOpacity: 0.4,

	reflection: 1,
	reflectionColors: ['#FFF', '#FFF'],

	line: 1,
	lineColors: ['#AAA', '#AAA']
	
};

ART.Theme = function(properties){
	
	properties = $unlink(properties);
	
	this.normal = properties.normal;
	
	delete properties.normal;
	
	for (var p in properties) this[p] = $merge(this.normal, properties[p]);
	
};

ART.Themes = new Hash;/* ART Container */

ART.Container = new Class({
	
	Extends: ART.Element,
	
	options: {
		id: null,
		className: null,
		
		title: null,
		content: null,
		status: null,
		
		styles: {
			height: 'auto',
			width: 'auto',
			position: 'relative',
			overflow: 'hidden'
		},
		
		theme: null,
		morph: {link: 'cancel'}
	},
	
	initialize: function(options, component){
		this.component = (component) ? ' art-' + component : '';
		this.setOptions(options);
		options = this.options;
		
		var absZero = {position: 'absolute', top: 0, left: 0};
		
		this.container = new Element('div', {'class': 'art-container' + this.component}).setStyles({
			position: options.styles.position, top: 0, left: 0
		});
		
		if (!this.component) this.component = 'art-container';
		
		if (options.id) this.container.set('id', options.id);
		if (options.className) $splat(options.className).each(function(cn){
			this.container.addClass(cn);
		}, this);
		
		this.paint = new ART.Paint().setStyles(absZero).inject(this.container);
		
		this.wrapper = new Element('div').setStyles(absZero).inject(this.container);

		this.top = {offsetHeight: 0};
		this.bottom = {offsetHeight: 0};
		this.center = new Element('div').inject(this.wrapper);
		
		this.center.setStyles({width: options.styles.width, height: options.styles.height, overflow: options.styles.overflow});
		
		if (options.title) this.setTitle(options.title);
		if (options.content) this.setContent(options.content);
		if (options.status) this.setStatus(options.status);
		
		this.morpher = new Fx.Morph(this.container, this.options.morph);
		
		arguments.callee.parent({
			subject: this.container,
			onInject: this.onInject
		});
		
	},
	
	wraps: function(element){
		element = $(element);
		if (!element) return this;
		this.container.replaces(element);
		this.setContent(element);
		this.draw();
		return this;
	},
	
	replaces: function(element){
		arguments.callee.parent(element);
		return this.draw();
	},
	
	setTitle: function(content){
		if ($type(this.top) != 'element') this.top = new Element('div').inject(this.wrapper, 'top');
		this.process('title', content, this.top);
		return this;
	},
	
	setContent: function(content){
		this.process('content', content, this.center);
		this.grabber = this.content;
		return this;
	},
	
	setStatus: function(content){
		if ($type(this.bottom) != 'element') this.bottom = new Element('div').inject(this.wrapper, 'bottom');
		this.process('status', content, this.bottom);
		return this;
	},
	
	onInject: function(){
		this.draw();
	},

	process: function(name, part, container){
		var where = this[name];
		if (where) where.dispose();
		if (!part) return;
		where = new Element('div', {'class': this.component + '-' + name}).inject(container);
		where.setContent(part);
		this[name] = where;
	},
	
	draw: function(theme){
		
		theme = $unlink(theme || {});
		
		this.container.setStyles({width: '100%'});
		
		var height = theme.height, width = theme.width;
		
		if ($chk(height)) this.center.setStyles({height: height});
		if ($chk(width)) this.center.setStyles({width: width});
		
		theme = $merge(this.options.theme.normal, theme, {
			title: this.top.offsetHeight,
			status: this.bottom.offsetHeight,
			height: this.center.offsetHeight,
			width: this.center.offsetWidth
		});
		
		theme = ART.Style(theme);
		
		this.container.setStyles({height: theme.outerHeight, width: theme.outerWidth});
		var shadow = theme.shadow, border = theme.border;
		
		this.offsets = {
			x: shadow + ((theme.shadowOffsetX > 0) ? 0 : theme.shadowOffsetX),
			y: shadow + ((theme.shadowOffsetY > 0) ? 0 : theme.shadowOffsetY)
		};
		
		this.wrapper.setStyles({left: this.offsets.x + border, top: this.offsets.y + border});
		
		this.paint.draw(theme);
		return this;
	},
	
	setPosition: function(position){
		this.container.position({x: position.x - this.offsets.x, y: position.y - this.offsets.y});
		return this;
	}
	
});/* ART Scrollbar */

ART.Themes.ScrollBar = new ART.Theme({
	
	normal: {
		radius: 5,
		shadow: 0,
		border: 1,
		borderColor: '#fff',
		borderOpacity: 0.5,
		reflection: 0,
		overlayColor: '#000',
		overlayOpacity: 0.8
	}
	
});


ART.ScrollBar = new Class({

	Extends: ART.Element,

	options: {
		id: null,
		className: null,
		
		autoHide: true,
		
		minThumbSize: 10,
		wheel: 8,
		
		morph: {duration: 200, link: 'cancel'},
		theme: ART.Themes.ScrollBar
	},

	initialize: function(scrolling, content, options){
		
		this.setOptions(options);

		this.scrolling = $(scrolling);
		this.document = this.scrolling.getDocument();
		
		this.content = $(content);
		
		this.container = new Element('div').addClass('art-scrollbar').inject(this.scrolling);
		
		if (this.options.id) this.container.set('id', this.options.id);
		if (this.options.className) this.container.addClass(this.options.className);
		
		this.track = new Element('div').addClass('art-scrollbar-track').inject(this.container);
		
		if (this.options.autoHide){
			this.hidden = true;
			this.container.setStyle('opacity', 0);
		}
		
		this.thumb = new Element('div', {
			'class': 'art-scrollbar-thumb'
		}).inject(this.track);
		
		this.paint = new ART.Paint().setStyles({position: 'absolute', top: 0, left: 0}).inject(this.thumb);
		
		this.scroller = new Fx.Scroll(this.content, this.options.morph);
		
		this.morphContainer = new Fx.Morph(this.container, this.options.morph);
		this.morphThumb = new Fx.Morph(this.thumb, this.options.morph);
		
		this.selection = (Browser.Engine.trident) ? 'selectstart' : 'mousedown';
		
		this.bound = {
			start: this.start.bind(this),
			end: this.end.bind(this),
			drag: this.drag.bind(this),
			wheel: this.wheel.bind(this),
			page: this.page.bind(this),
			show: this.show.bind(this),
			hide: this.hide.bind(this),
			stopSelection: $lambda(false)
		};
		
		this.mousedown = false;

		this.position = {};
		this.mouse = {};
		
		this.update();
		this.attach();
	},

	attach: function(){
		if (this.options.autoHide){
			this.scrolling.addEvent('mouseenter', this.bound.show);
			this.scrolling.addEvent('mouseleave', this.bound.hide);
		}
		
		this.thumb.addEvent('mousedown', this.bound.start);
		if (this.options.wheel) this.scrolling.addEvent('mousewheel', this.bound.wheel);
		this.container.addEvent('mouseup', this.bound.page);
	},
	
	show: function(force){
		if (this.hidden && !this.mousedown && (force === true || this.check())){
			this.hidden = false;
			this.morphContainer.start({opacity: 1});
		}
	},
	
	hide: function(force){
		if (!this.hidden && !this.mousedown && (force === true || this.check())){
			this.hidden = true;
			this.morphContainer.start({opacity: 0});
		}
	},
	
	check: function(){
		return !(this.thumbSize == this.trackSize);
	},

	update: function(){

		this.contentSize = this.content.offsetHeight;
		this.contentScrollSize = this.content.scrollHeight;
		this.trackSize = this.track.offsetHeight;

		this.contentRatio = this.contentSize / this.contentScrollSize;

		this.thumbSize = (this.trackSize * this.contentRatio).limit(this.options.minThumbSize, this.trackSize);

		this.scrollRatio = this.contentScrollSize / this.trackSize;

		this.thumb.setStyle('height', this.thumbSize);
		
		var theme = this.options.theme.normal;
		var border = ((theme.border || 0) * 2);
		
		if (!this.check()){
			this.hide(true);
		} else {
			if (!this.options.autoHide) this.show(true);
			this.paint.draw($extend({
				height: this.thumb.offsetHeight - border,
				width: this.thumb.offsetWidth - border
			}, this.options.theme.normal));
		}
		
		this.updateThumbFromContentScroll();
		this.updateContentFromThumbPosition();
	},

	updateContentFromThumbPosition: function(){
		this.content.scrollTop = this.position.now * this.scrollRatio;
	},

	updateThumbFromContentScroll: function(scroll){
		var scrollValue = $pick(scroll, this.content.scrollTop);
		this.position.now = (scrollValue / this.scrollRatio).limit(0, (this.trackSize - this.thumbSize));
		if ($defined(scroll)) this.morphThumb.start({top: this.position.now});
		else this.thumb.setStyles({top: this.position.now});
	},

	wheel: function(event){
		this.content.scrollTop -= event.wheel.round() * this.options.wheel;
		this.updateThumbFromContentScroll();
	},

	page: function(option){
		if (this.mousedown) return;
		var height = this.content.offsetHeight;
		var page = (($type(option) == 'event' && option.page.y > this.thumb.getPosition().y) || option == 'down') ? height : -height;
		var scroll = this.content.scrollTop + page;
		this.scroller.start(0, scroll);
		this.updateThumbFromContentScroll(scroll);
	},

	start: function(event){
		this.mousedown = true;
		this.mouse.start = event.page.y;
		this.position.start = this.thumb.getStyle('top').toInt();
		document.addEvent('mousemove', this.bound.drag);
		document.addEvent('mouseup', this.bound.end);
		
		this.document.addEvent(this.selection, this.bound.stopSelection);
	},

	end: function(event){
		this.mousedown = false;
		if (this.options.autoHide && event.target != this.scrolling && !this.scrolling.hasChild(event.target)) this.hide();
		this.document.removeEvent('mousemove', this.bound.drag);
		this.document.removeEvent('mouseup', this.bound.end);
		this.document.removeEvent(this.selection, this.bound.stopSelection);
	},

	drag: function(event){
		this.mouse.now = event.page.y;
		this.position.now = (this.position.start + (this.mouse.now - this.mouse.start)).limit(0, (this.trackSize - this.thumbSize));
		this.updateContentFromThumbPosition();
		this.updateThumbFromContentScroll();
	}

});/* ART Window */

ART.WM = {
	
	windows: [],
	
	init: function(){
		
		if (ART.WM.initialized) return;
		ART.WM.initialized = true;
		
		document.addEvent('mousedown', function(e){
			
			var found = false;
			
			ART.WM.windows.each(function(win){
				if (found) return;
				if (ART.WM.checkAgainst(win.wrapper, e)){
					found = true;
					ART.WM.refocus(win);
				}
			});
			
			if (!found) ART.WM.refocus();
			
		});
	},
	
	checkAgainst: function(el, event){
		el = el.getCoordinates();
		var now = {x: event.page.x, y: event.page.y};
		return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top);
	},
	
	include: function(win){
		ART.WM.init();
		ART.WM.refocus(win);
	},
	
	remove: function(win){
		ART.WM.windows.remove(win);
	},
	
	refocus: function(win){
		if (win){
			ART.WM.windows.remove(win).unshift(win);
			win.focus();
		}
		ART.WM.windows.each(function(w, i){
			w.container.setStyle('z-index', ART.WM.windows.length - i + 1);
			if (w != win) w.blur();
		});
	}
	
};

ART.Themes.MetalWindow = new ART.Theme({
	
	normal: {
		radius: 5,

		titleColor: ['#DDD', '#AAA'],

		statusColor: ['#DDD', '#AAA'],

		overlayColor: '#FFF',

		shadowColor: '#000',
		shadowOpacity: 1,

		borderColor: ['#333', '#000'],
		borderOpacity: 0.3,

		reflectionColors: ['#F6F6F6', '#EEEEEE'],

		lineColors: ['#999', '#AAA']
	},
	
	blur: {
		titleColor: '#EEE',
		statusColor: '#EEE',

		shadowColor: '#000',
		shadowOpacity: 0.5,

		borderColor: '#000',
		borderOpacity: 0.1,

		reflectionColors: ['#FFF', '#FFF'],

		lineColors: ['#DDD', '#DDD']
	}
	
});

ART.Themes.HUDWindow = new ART.Theme({
	
	normal: {
		radius: 5,

		overlayColor: '#111',
		overlayOpacity: 0.9,

		reflection: 0,

		borderColor: '#777',
		borderOpacity: 0.6,

		titleColor: ['#444', '#222'],
		titleOpacity: 0.9,

		lineColors: ['#333', '#555'],

		statusColor: ['#444', '#222'],
		statusOpacity: 0.9,

		shadow: 10,
		shadowOpacity: 1
	},
	
	blur: {
		overlayColor: '#111',
		overlayOpacity: 0.8,

		borderColor: '#777',
		borderOpacity: 0.3,

		titleColor: '#111',
		titleOpacity: 0.8,

		lineColors: ['#333', '#333'],

		statusColor: '#111',
		statusOpacity: 0.8,

		shadowOpacity: 0.5
	}
	
});

ART.Window = new Class({
	
	Extends: ART.Container,
	
	options: {
		
		styles: {
			width: 200,
			height: 200,
			overflow: 'auto',
			position: 'absolute'
		},
		
		resizable: true,
		draggable: true,
		showContentWhileResizing: true,
		
		limit: {x: [200, 400], y: [200, 300]},
		
		buttons: {
			close: true,
			mini: true,
			maxi: true
		},
		
		theme: ART.Themes.MetalWindow

	},
	
	initialize: function(options){

		arguments.callee.parent(options, 'window');
		
		this.centerWrapper = new Element('div').wraps(this.center).setStyle('position', 'relative');
		
		var buttons = this.options.buttons;
		
		if (buttons){
			
			this.buttons = {};
			
			this.buttonsWrapper = new Element('div', {
				'class': 'art-window-buttons'
			}).setStyles({position: 'absolute', overflow: 'hidden'}).inject(this.wrapper);
			
			for (var button in buttons){
				if (!buttons[button]) continue;
				this.buttons[button] = new Element('div', {
					'class': 'art-window-button art-window-button-' + button
				}).setStyles({overflow: 'hidden', position: 'absolute', 'background-repeat': 'no-repeat'}).inject(this.buttonsWrapper);
			}
			
		}
		
		if (this.options.resizable){
			
			this.handle = new Element('div', {
				'class': 'art-window-button-handle'
			}).setStyles({
				position: 'absolute',
				overflow: 'hidden',
				bottom: 0,
				right: 0
			}).inject(this.wrapper);
			
			this.mask = new Element('div', {styles: {
				position: 'absolute',
				display: 'none'
			}}).inject(this.container);
			
		}
		
	},
	
	onInject: function(){
		this.computeSizes();
		if (this.options.buttons) this.attachButtonEvents();
		if (this.options.draggable) this.makeDraggable();
		if (this.options.resizable) this.makeResizable();
		arguments.callee.parent();
	},
	
	focus: function(){
		if (this.focused) return;
		this.focused = true;
		
		ART.WM.refocus(this);
		
		this.wrapper.removeClass('art-window-blur');
		this.showOverflow();
		this.draw(this.options.theme.normal);
	},
	
	blur: function(){
		if (!this.focused) return;
		this.focused = false;

		this.wrapper.addClass('art-window-blur');
		this.hideOverflow();
		this.draw(this.options.theme.blur);
	},
	
	open: function(element, position){
		
		if (this.opened) return this;
		this.opened = true;
		ART.WM.include(this);
		
		position = position || {x: 0, y: 0};
		this.setPosition(position);
		
		this.hideOverflow();
		this.setStyle('opacity', 0).inject(element);
		
		this.morpher.start({opacity: 1}).chain(function(){
			this.showOverflow();
		}.bind(this));
		
		return this;
	},
	
	close: function(){
		if (!this.opened) return this;
		this.opened = false;
		
		ART.WM.remove(this);
		
		this.hideOverflow();

		this.morpher.start({opacity: 0}).chain(function(){
			this.container.dispose();
		}.bind(this));
		
		return this;
	},
	
	maximize: function(){
		var size = window.getSize();
		document.body.setStyle('overflow', 'hidden');
		var oversize = this.bottom.offsetHeight + this.top.offsetHeight;
		return this.container.morph({
			height: size.y - oversize,
			width: size.x,
			top: -1,
			left: -1
		});
	},
	
	showMask: function(){
		
		this.mask.setStyles({
			height: this.wrapper.offsetHeight,
			width: this.wrapper.offsetWidth,
			top: this.wrapper.style.top.toInt(),
			left: this.wrapper.style.left.toInt(),
			display: 'block'
		});
	},
	
	hideMask: function(){
		this.mask.setStyles({display: 'none'});
	},
	
	showCenter: function(){
		this.center.setStyle('visibility', 'visible');
	},
	
	hideCenter: function(){
		this.center.setStyle('visibility', 'hidden');
	},
	
	hideOverflow: function(){
		if (Browser.Engine.gecko && Browser.Platform.mac) this.center.setStyle('overflow', 'hidden');
	},
	
	showOverflow: function(){
		if (this.focused) this.center.setStyle('overflow', this.options.styles.overflow);
	},
	
	remask: function(drawShadow){
		this.draw({
			height: this.mask.clientHeight - this.top.offsetHeight - this.bottom.offsetHeight,
			width: this.mask.clientWidth, drawShadow: (Browser.Engine.webkit420) ? true : drawShadow
		});
	},
	
	computeSizes: function(){
		var tbh = this.top.offsetHeight + this.bottom.offsetHeight, lim = this.options.limit;
		this.minh = lim.y[0] + tbh;
		this.maxh = lim.y[1] + tbh;
		this.minw = lim.x[0];
		this.maxw = lim.x[1];
	},
	
	attachButtonEvents: function(){
		var self = this, lim = this.options.limit, buttons = this.options.buttons;
		
		if (buttons.maxi) this.buttons.maxi.addEvents({
			mouseup: function(){
				self.draw({height: lim.y[1], width: lim.x[1]});
				self.fireEvent('onSizeChange');
			}
		});
		
		if (buttons.mini) this.buttons.mini.addEvents({
			mouseup: function(){
				self.draw({height: lim.y[0], width: lim.x[0]});
				self.fireEvent('onSizeChange');
			}
		});
		
		if (buttons.close) this.buttons.close.addEvents({
			mouseup: function(){
				self.close();
			}
		});
	},
	
	makeResizable: function(){
		
		if (this.madeResizable) return;
		this.madeResizable = true;
		
		var self = this;
		
		new Drag(this.mask, {
			limit: {x: [this.minw, this.maxw], y: [this.minh, this.maxh]},
			modifiers: {x: 'width', y: 'height'},
			onBeforeStart: function(){
				self.showMask();
			},
			onStart: function(){
				if (!self.options.showContentWhileResizing) self.hideCenter();
				self.hideOverflow();
			},
			onCancel: function(){
				self.hideMask();
			},
			onDrag: function(){
				self.remask(false);
				self.fireEvent('onSizeChange');
			},
			onComplete: function(){
				self.showCenter();
				self.showOverflow();
				self.remask(true);
				self.hideMask();
				self.fireEvent('onSizeChange');
			},
			handle: this.handle
		});
		
	},
	
	makeDraggable: function(){
		
		if (this.madeDraggable) return;
		this.madeDraggable = true;
		
		new Drag.Move(this.container, {handle: [this.top, this.bottom]});
		
	}
	
});/* ART Button */

ART.Themes.MetalButton = new ART.Theme({
	
	normal: {
		shadow: 2,
		reflection: 0,
		shadowColor: '#FFF',
		shadowOpacity: 1,
		overlayColor: ['#fafafa', '#a9a9a9'],
		borderColor: ['#000', '#222'],
		borderOpacity: 0.5,
		shadowOffsetY: -1,
		overlayOpacity: 1,
		radius: 4
	},
	
	active: {
		reflection: 1,
		reflectionColors: ['#444'],
		overlayColor: ['#555', '#bbb'],
		borderOpacity: 0.7,
		borderColor: ['#000', '#444']
	},
	
	focus: {
		borderOpacity: 0.7,
		borderColor: ['#0C81CE', '#0C81CE'],
		overlayOpacity: 0.95
	},
	
	disabled: {
		overlayOpacity: 0.5,
		borderOpacity: 0.25
	}
	
});

ART.Button = new Class({
	
	Extends: ART.Container,
	
	options: {
		
		// onAction: $empty,
		
		theme: ART.Themes.MetalButton
	},
	
	initialize: function(options, component){
		this.bound = {
			down: this.down.bind(this),
			up: this.up.bind(this),
			focus: this.focus.bind(this),
			blur: this.blur.bind(this)
		};
		
		arguments.callee.parent(options, component || 'button');
		
		this.input = new Element('a', {href: '#'}).addEvent('click', function(e){
			e.preventDefault();
		});
		
		this.setContent(this.input);
		
		if (!this.options.preventActions) this.input.addEvents({

			keydown: function(e){
				if (e.key == 'enter' || e.key == 'space') this.down(e);
			}.bind(this),
			
			keyup: function(e){
				if (e.key == 'enter' || e.key == 'space') this.up(e);
			}.bind(this),
			
			mousedown: this.bound.down
			
		});
		
		this.enableFocus();
	},
	
	load: function(input, force){
		var elementInput = $(input),
			replaces = false,
			isTag = elementInput && ['input', 'button'].contains(elementInput.get('tag'));
		
		if (elementInput && (force || isTag)) {
			if (elementInput.get('type') != 'file' && isTag) this.input.set('html', elementInput.value);
			if (elementInput.parentNode) replaces = true;
		} else {
			this.input.setContent(input);
		}

		if (replaces) this.replaces(input);
		
		return this;
	},
	
	enableFocus: function(){
		this.input.addEvent('focus', this.bound.focus);
		this.input.addEvent('blur', this.bound.blur);
	},
	
	disableFocus: function(){
		this.input.removeEvent('focus', this.bound.focus);
		this.input.removeEvent('blur', this.bound.blur);
	},
	
	down: function(e){
		e.preventDefault();
		if(this.disabled) return false;
		
		this.disableFocus();
		this.input.forceFocus();
		
		if (!this.options.preventActions) document.addEvent('mouseup', this.bound.up);
		
		this.draw(this.options.theme.active);
		this.wrapper.addClass('art-button-active');
		return false;
	},
	
	up: function(e){
		if (!this.options.preventActions) document.removeEvent('mouseup', this.bound.up);
		this.input.forceFocus();
		this.enableFocus();
		this.focus();
		
		this.wrapper.removeClass('art-button-active');
		if (e.target == this.input) this.fireEvent('onAction', e);
	},
	
	focus: function(){
		this.draw(this.options.theme.focus);
		this.wrapper.addClass('art-button-focus');
	},
	
	blur: function(){
		this.draw(this.options.theme.normal);
		this.wrapper.removeClass('art-button-focus');
	},
	
	enable: function(){
		if (!this.disabled) return this;
		this.disabled = false;
		this.draw(this.options.theme.normal);
		this.wrapper.removeClass('art-button-disabled');
		return this;
	},
	
	disable: function(){
		if (this.disabled) return this;
		this.disabled = true;
		this.draw(this.options.theme.disabled);
		this.wrapper.addClass('art-button-disabled');
		return this;
	}
	
});ART.File = new Class({
	
	Extends: ART.Button,
	
	options: {
		caption: '',
		showValue: false
	},
	
	initialize: function(options){
		arguments.callee.parent(options);
	},
	
	load: function(input){
		var el = this.file = $(input).clone().setOpacity(0).addClass('art-file');
		
		if (this.options.caption) this.input.set('html', this.options.caption);
		arguments.callee.parent(input);
		el.inject(this.content);
		
		this.container.addEvent('mousemove', function(e){
			var pos = this.getCoordinates();
			el.setStyles({
				top: (e.page.y-pos.top-pos.height)-(el.offsetHeight/2)+5+'px',
				left: (e.page.x-pos.left)-(el.offsetWidth - 30)+'px'
			});
		});
		
		if ($(this.options.showValue)){
			this.updateValue = $(this.options.showValue);
			this.check.create({periodical: 500, bind: this})();
		}
		
		return this;
	},
	
	check: function(){
		if (!this.file.value || this.updateValue.get('text')==this.file.value)
			return;
		
		this.updateValue.set('text', this.file.value);
	},
	
	draw: function(theme){
		this.file.setStyle('display', 'none');
		arguments.callee.parent(theme);
		this.file.setStyle('display', '');
	},
	
	disable: function(){
		arguments.callee.parent();
		this.file.setStyle('display', 'none');
	},
	
	enable: function(){
		arguments.callee.parent();
		this.file.setStyle('display', '');
	}
	
});/* ART TextInput */

ART.Themes.MetalTextInput = new ART.Theme({
	
	normal: {
		shadow: 2,
		reflection: 1,
		reflectionColors: ['#ccc', '#ccc'],
		shadowColor: '#FFF',
		shadowOpacity: 1,
		overlayColor: '#fff',
		borderColor: ['#000', '#333'],
		borderOpacity: 0.5,
		shadowOffsetY: -1,
		radius: 1
	},
	
	focus: {
		borderOpacity: 0.7,
		borderColor: ['#0C81CE', '#2BA2F1']
	},
	
	disabled: {
		
	}
	
});

ART.TextInput = new Class({
	
	Extends: ART.Container,
	
	options: {
		theme: ART.Themes.MetalTextInput,
		input: null,
		name: null,
		type: null,
		changeDelay: 500
	},
	
	initialize: function(options){
		arguments.callee.parent(options, 'textinput');
		
		this.input = $(this.options.input) || new Element('input', {type: this.options.type || 'text', name: this.options.name || ''});
		
		this.input.setStyles({
			outline: 'none',
			background: 'none',
			resize: 'none',
			border: 0,
			margin: 0,
			cursor: 'text'
		}).addEvents({
			focus: this.onFocus.bind(this),
			blur: this.onBlur.bind(this),
			keyup: this.checkChange.bind(this)
		});
		
		(this.input.parentNode) ? this.wraps(this.input) : this.setContent(this.input);
		
		this.value = this.getValue();
	},
	
	getValue: function(){
		return this.input.value.trim();
	},
	
	focus: function(){
		this.input.focus();
		this.onFocus();
	},
	
	checkChange: function(e){
		if (!this.$events.onChange) return;
		$clear(this.changeTimer);
		if (this.value != this.getValue()) this.changeTimer = this.onChange.delay(this.options.changeDelay, this);
	},
	
	onChange: function(){
		this.value = this.getValue();
		this.fireEvent('onChange');
	},
	
	blur: function(){
		this.input.blur();
		this.onBlur();
	},
	
	onFocus: function(){
		this.wrapper.addClass('art-textinput-focus');
		return this.draw(this.options.theme.focus);
	},
	
	onBlur: function(){
		this.wrapper.removeClass('art-textinput-focus');
		return this.draw(this.options.theme.normal);
	},
	
	enable: function(){
		
	},
	
	disable: function(){
		
	}
	
});/* ART ToolTip */

ART.Themes.MetalToolTip = new ART.Theme({
	normal: {
		shadow: 5,
		shadowOpacity: 0.3,
		topLeftRadius: 0,
		topRightRadius: 3,
		bottomLeftRadius: 3,
		bottomRightRadius: 3,
		titleColor: '#F9F4DE',
		overlayColor: ['#F9F4DE', '#F9EFBD'],
		statusColor: '#F9EFBD',
		reflectionColors: ['#F9F8F3', '#F9F8F3']
	}
});


ART.ToolTip = new Class({
	
	Extends: ART.Container,

	options: {
		
		onShow: function(){
			this.setStyle('visibility', 'visible');
		},
		
		onHide: function(){
			this.setStyle('visibility', 'hidden');
		},
		
		// onStart: $empty,
		
		showDelay: 200,
		hideDelay: 100,

		offsets: {'x': 16, 'y': 16},
		fixed: false,
		
		theme: ART.Themes.MetalToolTip,
		
		contents: [],
		titles: [],
		statuses: []
	},

	initialize: function(elements, options){
		
		arguments.callee.parent(options, 'tooltip');
		
		this.elements = $$(elements);
		this.contents = this.options.contents;
		this.titles = this.options.titles;
		this.statuses = this.options.statuses;
		
		this.setStyles({position: 'absolute', visibility: 'hidden'}).inject(document.body);
		
		this.bound = {end: this.end.bind(this), locate: this.locate.bind(this), hide: this.hide.bind(this)};
		this.elements.each(this.build, this);
		
		this.fireEvent('onStart');
	},

	build: function(el, i){
		
		var enter = function(event){
			this.start(el, i);
			
			if (!this.options.fixed){
				this.locate(event);
				el.addEvent('mousemove', this.bound.locate);
			} else {
				this.position(el);
			}
		}.bind(this);
		
		var leave = this.end.bind(this, el);

		el.addEvents({
			mouseenter: enter,
			mousedown: leave,
			mouseleave: leave
		});
	},

	start: function(el, i){
		
		var title = this.titles[i], content = this.contents[i], status = this.statuses[i];
		
		this.setContent(content);
		
		if (title) this.setTitle(title);
		if (status) this.setStatus(status);
		
		this.draw();
		
		$clear(this.timer);
		this.timer = this.show.delay(this.options.showDelay, this);
	},

	end: function(el){
		el.removeEvent('mousemove', this.bound.locate);
		$clear(this.timer);
		this.timer = this.hide.delay(this.options.hideDelay, this);
	},
	
	show: function(){
		this.fireEvent('onShow');
	},

	hide: function(){
		this.fireEvent('onHide');
	},

	position: function(element){
		var pos = element.getPosition();
		this.setStyles({
			'left': pos.x + this.options.offsets.x,
			'top': pos.y + this.options.offsets.y
		});
	},

	locate: function(event){
		var doc = window.getSize();
		var scroll = window.getScroll();
		var tip = {'x': this.container.offsetWidth, 'y': this.container.offsetHeight};
		var prop = {'x': 'left', 'y': 'top'};
		for (var z in prop){
			var pos = event.page[z] + this.options.offsets[z];
			if ((pos + tip[z] - scroll[z]) > doc[z]) pos = event.page[z] - this.options.offsets[z] - tip[z];
			this.setStyle(prop[z], pos);
		}
	}
	
	
});/* ART Menu */

ART.Themes.MetalMenu = new ART.Theme({
	
	normal: {

		radius: 4,
		reflection: 0,

		overlayColor: '#fff',
		overlayOpacity: 0.9,
		borderOpacity: 0.2

	}
	
});

ART.Menu = new Class({
	
	Extends: ART.Container,
	
	options: {
		theme: ART.Themes.MetalMenu,
		
		target: null,
		relative: null,
		
		relative: 'mouse'
	},
	
	initialize: function(options){
		arguments.callee.parent($merge(options, {styles: {position: 'absolute'}}), 'menu');
		
		var target = $(this.options.target), relative = this.options.relative;
		
		if (target) target.addActions({
			
			up: function(event){
				this.close();
			}.bind(this),
			
			down: function(event){
				event.preventDefault();
				var c = target.getCoordinates();
				var p = (event.page && this.options.relative == 'mouse') ? event.page : {x: c.left, y: c.bottom};
				this.open(p);
			}.bind(this)
			
		});
		
		document.addEvent('keydown', function(event){
			if (this.opened) this.moveFocus(event);
		}.bind(this));
		
	},
	
	moveFocus: function(event){
		if (!event.key.match(/up|down/)) return;
		switch (event.key){
			case 'down': this.active++; break;
			case 'up': this.active--;
		}
		
		if (this.active < 0) this.active = 0;
		if (this.active > this.links.length - 1) this.active = this.links.length - 1;
		
		this.focusItem(this.links[this.active], true);
	},
	
	load: function(data){
		
		if (this.list) this.list.destroy();
		
		if ($type(data) != 'array'){
			
			this.list = $(data);
			this.links = this.list.getElements('a');
			this.lis = this.list.getElements('li');
			
		} else {
			
			this.list = new Element('ul');
			var links = [], lis = [];
			
			data.each(function(object){

				var li = new Element('li').inject(this.list);
				
				lis.push(li);

				var text = object.text, action = object.action;

				if (text == '-'){
					li.addClass('art-menu-separator');
					return;
				}

				var link = new Element('a', {href: '#', html: text}).inject(li);
				
				if ($type(action) == 'function'){
					
					link.addEvents({
						mouseup: action,

						keyup: function(e){
							if (e.key == 'space' || e.key == 'enter') action(e);
						},

						click: function(e){
							e.preventDefault();
						},
						
						keydown: function(e){
							e.preventDefault();
						}
					});
				}

				links.push(link);

			}, this);
			
			this.links = $$(links);
			this.lis = $$(lis);
			
		}
		
		var self = this;
		
		this.links.addEvents({
			mouseenter: function(){
				self.focusItem(this, true);
			},
			mouseleave: function(){
				self.blurItem(this, true);
			},
			focus: function(){
				self.focusItem(this, false);
			},
			blur: function(){
				self.blurItem(this, false);
			}
		});
		
		return this.setContent(this.list).draw();
		
	},
	
	focusItem: function(link, force){
		if (!this.opened) return;
		if (force) link.forceFocus();
		link.getParent('li').addClass('art-menu-selected');
	},
	
	blurItem: function(link, force){
		if (!this.opened) return;
		if (force) link.forceBlur();
		link.getParent('li').removeClass('art-menu-selected');
	},
	
	open: function(position){
		if (this.opened) return this;
		this.opened = true;
		
		this.active = -1;
		
		this.links.each(function(link){
			this.blurItem(link, true);
		}, this);
		
		this.inject(document.body);

		this.setStyle('opacity', 0).setPosition(position);
		
		return this.morpher.start({opacity: 1});
	},
	
	close: function(){
		if (!this.opened) return this;
		this.opened = false;		
				
		return this.morpher.start({opacity: 0}).chain(function(){
			this.links.removeClass('art-menu-selected');
			this.container.dispose();
		}.bind(this));
	}
	
});ART.Select = new Class({
	
	Extends: ART.Element,
	
	options: {
		buttonTheme: ART.Themes.MetalButton,
		menuTheme: ART.Themes.MetalMenu,
		className: '',
		morph: {duration: 150}
	},
	
	initialize: function(options){
		
		this.setOptions(options, {className: this.options.className + ' art-select'});
		
		this.button = new ART.Button($merge(this.options, {
			theme: this.options.buttonTheme,
			preventActions: true
		}));
		
		this.menu = new ART.Menu($merge(this.options, {
			theme: this.options.menuTheme,
			relative: 'element'
		}));
		
		arguments.callee.parent({
			subject: this.button.container,
			onInject: this.onInject
		});
		
	},
	
	onInject: function(){
		this.button.draw();
	},
	
	select: function(link){
		this.button.input.set('html', link.get('html'));
		link.getParent('ul').getElements('a').removeClass('art-menu-current');
		link.addClass('art-menu-current');
	},
	
	load: function(data){
		
		var select = false;
		
		if ($type(data) != 'array'){
			
			select = $(data);
			data = [];
			
			select.getElements('option').each(function(option){
				data.push({text: option.get('html')});
			});
			
			select.setStyle('display', 'none');
		}
		
		this.menu.load(data);
		
		this.menu.links.each(function(link){
			
			link.addEvent('mouseup', function(){
				this.select(link);
			}.bind(this));
			
			link.addEvent('keyup', function(e){
				if (e.key == 'enter' || e.key == 'space') this.select(link);
			}.bind(this));
			
		}, this);
		
		this.select(this.menu.links[0]);
		
		this.button.input.addActions({
			
			up: function(e){
				this.menu.close();
				this.button.up(e);
			}.bind(this),

			down: function(e){
				this.button.down(e);
				var c = this.button.wrapper.getCoordinates();
				this.menu.open({x: c.left - 1, y: c.bottom});
			}.bind(this)
		});
		
		if (select) this.inject(select, 'after');
		
		return this;
	}

});ART.Checkbox = new Class({
	Extends: ART.Container,
	
	options: {
		theme: ART.Themes.MetalButton,
		caption: '',
		captionStyle: {},
		label: false
	},
	
	initialize: function(options, component){
		this.bound = {
			toggle: this.toggle.bind(this)
		};
		
		arguments.callee.parent(options, component || 'checkbox');
		
		this.input = new Element('a', {href: '#'}).addEvent('click', (function(e){
			if (!this.disabled) this.toggle();
			e.preventDefault();
		}).bind(this));
		this.handle = new Element('div', {'class': this.component+'-button'}).setStyles({'position': 'absolute', 'background-repeat': 'no-repeat'}).inject(this.input);
		this.setContent(this.input);
	},
	
	load: function(input){
		input = $(input);
		
		if (this.options.label)
			var parent = $(this.options.label) || input.getParent();
		
		if (input && input.get('tag') == 'input'){
			this.elementInput = input.setStyle('display', 'none');
			if(input.parentNode) this.replaces(this.elementInput);
			this.input.adopt(this.elementInput);
			if(this.elementInput.checked) this.check();
		}
		
		if (this.options.caption)
			new Element('div', {'class': this.component.trim()+'-caption', text: this.options.caption, styles: $merge({marginLeft: this.subject.getSize().x+5}, this.options.captionStyle)}).addEvent('click', this.bound.toggle).inject(this.subject);
			
		if (parent) parent.addEvent('click', this.bound.toggle);
		return this;
	},
	
	toggle: function(){
		this[(this.elementInput.checked ? 'un' : '')+'check']();
	},
	
	check: function(){
		this.handle.addClass(this.component.trim()+'-checked');
		this.elementInput.checked = true;
	},
	
	uncheck: function(){
		this.handle.removeClass(this.component.trim()+'-checked');
		this.elementInput.checked = false;
	},
	
	enable: function(){
		if (!this.disabled) return this;
		this.disabled = false;
		this.draw(this.options.theme.normal);
		this.wrapper.removeClass(this.component.trim()+'-disabled');
		return this;
	},
	
	disable: function(){
		if (this.disabled) return this;
		this.disabled = true;
		this.draw(this.options.theme.disabled);
		this.wrapper.addClass(this.component.trim()+'-disabled');
		return this;
	},
	
	getValue: function(){
		return (this.elementInput.checked) ? this.elementInput.get('value') : false;
	}
});ART.Themes.MetalRadio = new ART.Theme($merge(ART.Themes.MetalButton, {
	
	normal: {
		radius: 7
	},
	
	active: {
		radius: 7
	},
	
	focus: {
		radius: 7
	},
	
	disabled: {
		radius: 7
	}
	
}));

ART.Radio = new Class({
	Extends: ART.Checkbox,
	
	options: {
		theme: ART.Themes.MetalRadio
	},
	
	initialize: function(options, list){
		arguments.callee.parent(options, 'radio');
		
		this.list = list || [];
	},
	
	loadElements: function(input){
		input = $(input);
		if (input){
			if (input.get('tag') == 'input' && input.get('type')=='radio')
				this.list.push(input);
			else
				this.list = input.getElements('input[type="radio"]');
		}
		if (this.list.length)
			this.list.each(function(v, i){
				var options = $unlink(this.options);
				if(options.options[i])
					options = $merge(options, options.options[i]);
				v.store('art:radio', new ART.Radio(options, this.list).load(v));
			}, this);
		
		return this;
	},
	
	load: function(input){
		arguments.callee.parent(input);
		return this;
	},
	
	check: function(){
		this.list.each(function(el){
			if (!el.checked) return;
			el.checked = false;
			//this is to make sure the list element already has been created!
			if (el.retrieve('art:radio'))
				el.retrieve('art:radio').uncheck(true);
		});
		arguments.callee.parent();
	},
	
	uncheck: function(force){
		if(force) arguments.callee.parent();
	},
	
	getValue: function(){
		var value = false;
		this.list.each(function(el){
			if(el.checked) value = el.get('value');
		});
		return value;
	}
	
});ART.Themes.MetalTab = new ART.Theme($merge(ART.Themes.MetalButton, {
	
	normal: {
		radius: 0,
		topLeftRadius: 4,
		topRightRadius: 4
	},
	
	active: {
		radius: 0,
		topLeftRadius: 4,
		topRightRadius: 4
	},
	
	focus: {
		radius: 0,
		topLeftRadius: 4,
		topRightRadius: 4
	},
	
	disabled: {
		radius: 0,
		topLeftRadius: 4,
		topRightRadius: 4
	},
	
	blur: {
		overlayColor: ['#EEE', '#EEE'],

		borderColor: '#000',
		borderOpacity: 0.1
	}

}));

ART.TabElement = new Class({
	
	Extends: ART.Button,
	
	options: {
		theme: ART.Themes.MetalTab,
		close: false
	},
	
	initialize: function(options, tabs, index){
		this.tabs = tabs;
		this.index = index;
		
		arguments.callee.parent(options, 'tab');
	},
	
	load: function(input){
		input = $(input);
		
		if (input.hasClass('art-close')) this.options.close = true;
		
		this.input.set('html', input.get('text'));
		
		if (this.options.close) {
			new Element('img', {
				'class': 'art-tab-button-close',
				events: {
					mouseup: this.close.bind(this)
				}
			}).inject(this.input, 'top');
		}
		
		arguments.callee.parent(input, true);
		
		return this;
	},
	
	show: function(){
		this.draw(this.options.theme.normal);
		this.wrapper.removeClass('art-tab-blur');
		this.opened = true;
		
		this.tabs.contentElements.each(function(el, i){
			el.setStyle('display', this.index==i ? '' : 'none');
		}, this);
		
		return this;
	},
	
	hide: function(){
		this.draw(this.options.theme.blur);
		this.wrapper.addClass('art-tab-blur');
		this.opened = false;
		
		return this;
	},
	
	close: function(){
		this.tabs.remove(this.index);
	},
	
	focus: function(){
		arguments.callee.parent();
	},
	
	blur: function(){
		this.draw(this.options.theme[this.opened ? 'normal' : 'blur']);
	},
	
	down: function(e){
		this.tabs.open(this.index);
		
		arguments.callee.parent(e);
		return false;
	}
	
});

ART.Tabs = new Class({
	
	Implements: [Options],
	
	options: {
		tabOptions: {}
	},
	
	initialize: function(el, options){
		this.setOptions(options);
		
		this.el = $(el);
		this.container = this.el.getElement('.art-tabcontainer');
		this.content = this.el.getElement('.art-tabcontent');
		this.contentElements = this.content.getChildren().setStyle('display', 'none');
		this.children = [];
		
		this.container.getChildren().each(function(el, i){
			this.children.push(new ART.TabElement(this.options.tabOptions, this, i).load(el));
		}, this);
	},
	
	open: function(index){
		if(!this.children[index])
			return this;
		
		this.children.each(function(child, i){
			child[index==i ? 'show' : 'hide']();
		}, this);
		
		return this;
	},
	
	add: function(title, content, options){
		this.children.push(new ART.TabElement(options || this.options.tabOptions, this, this.children.length).load((typeof title == 'string' ? new Element('span', {text: title}) : $(title)).inject(this.container)).hide());
		this.contentElements.push((typeof content == 'string' ? new Element('div', {html: content}) : $(content)).setStyle('display', 'none').inject(this.content));
		
		return this;
	},
	
	remove: function(index){
		var opened;
		if (!this.children[index])
			return this;
		
		if (this.children[index].opened)
			opened = true;
		
		this.children[index].container.dispose();
		
		this.children.remove(this.children[index]);
		this.contentElements.remove(this.contentElements[index].dispose());
		
		this.children.each(function(child, i){
			this.children[i].index = i;
		}, this);
		
		if(opened && this.children.length) this.open(0);
		
		return this;
	}
	
});/* Fx Draw */

Fx.Draw = new Class({
	
	Extends: Fx,
	
	initialize: function(paint, options){
		this.paint = paint;
		arguments.callee.parent(options);
	},
	
	set: function(style){
		this.paint.draw(style);
		return this;
	},
	
	compute: function(from, to, delta){
		var now = {};
		for (var p in from) now[p] = arguments.callee.parent(from[p], to[p], delta);
		return now;
	},
	
	start: function(properties){
		if (!this.check(properties)) return this;
		var from = {}, to = {};
		for (var p in properties){
			from[p] = this.paint.theme[p];
			to[p] = properties[p];
		}
		return arguments.callee.parent(from, to);
	}
	
});