code:
/**
 * IndicatorLight.as
 * Keith Peters
 * version 0.9.10
 *
 * An indicator light that can be turned on, off, or set to flash.
 *
 * Copyright (c) 2011 Keith Peters
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.bit101.components
{
	import flash.display.DisplayObjectContainer;
	import flash.display.GradientType;
	import flash.display.Shape;
	import flash.events.TimerEvent;
	import flash.geom.Matrix;
	import flash.utils.Timer;

	public class IndicatorLight extends Component
	{
		protected var _color:uint;
		protected var _lit:Boolean = false;
		protected var _label:Label;
		protected var _labelText:String = "";
		protected var _lite:Shape;
		protected var _timer:Timer;

		/**
		 * Constructor
		 * @param parent The parent DisplayObjectContainer on which to add this CheckBox.
		 * @param xpos The x position to place this component.
		 * @param ypos The y position to place this component.
		 * @param color The color of this light.
		 * @param label String containing the label for this component.
		 */
		public function IndicatorLight(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number =  0, color:uint = 0xff0000, label:String = "")
		{
			_color = color;
			_labelText = label;
			super(parent, xpos, ypos);
		}

		/**
		 * Initializes the component.
		 */
		override protected function init():void
		{
			super.init();
			_timer = new Timer(500);
			_timer.addEventListener(TimerEvent.TIMER, onTimer);
		}

		/**
		 * Creates the children for this component
		 */
		override protected function addChildren():void
		{
			_lite = new Shape();
			addChild(_lite);

			_label = new Label(this, 0, 0, _labelText);
			draw();
		}

		/**
		 * Draw the light.
		 */
		protected function drawLite():void
		{
			var colors:Array;
			if(_lit)
			{
				colors = [0xffffff, _color];
			}
			else
			{
				colors = [0xffffff, 0];
			}

			_lite.graphics.clear();
			var matrix:Matrix = new Matrix();
			matrix.createGradientBox(10, 10, 0, -2.5, -2.5);
			_lite.graphics.beginGradientFill(GradientType.RADIAL, colors, [1, 1], [0, 255], matrix);
			_lite.graphics.drawCircle(5, 5, 5);
			_lite.graphics.endFill();
		}

		///////////////////////////////////
		// event handler
		///////////////////////////////////

		/**
		 * Internal timer handler.
		 * @param event The TimerEvent passed by the system.
		 */
		protected function onTimer(event:TimerEvent):void
		{
			_lit = !_lit;
			draw();
		}

		///////////////////////////////////
		// public methods
		///////////////////////////////////

		/**
		 * Draws the visual ui of the component.
		 */
		override public function draw():void
		{
			super.draw();
			drawLite();

			_label.text = _labelText;
			_label.x = 12;
			_label.y = (10 - _label.height) / 2;
			_width = _label.width + 12;
			_height = 10;
		}

		/**
		 * Causes the light to flash on and off at the specified interval (milliseconds). A value less than 1 stops the flashing.
		 */
		public function flash(interval:int = 500):void
		{
			if(interval < 1)
			{
				_timer.stop();
				isLit = false;
				return;
			}
			_timer.delay = interval;
			_timer.start();
		}

		///////////////////////////////////
		// getter/setters
		///////////////////////////////////

		/**
		 * Sets or gets whether or not the light is lit.
		 */
		public function set isLit(value:Boolean):void
		{
			_timer.stop();
			_lit = value;
			drawLite();
		}
		public function get isLit():Boolean
		{
			return _lit;
		}

		/**
		 * Sets / gets the color of this light (when lit).
		 */
		public function set color(value:uint):void
		{
			_color = value;
			draw();
		}
		public function get color():uint
		{
			return _color;
		}

		/**
		 * Returns whether or not the light is currently flashing.
		 */
		public function get isFlashing():Boolean
		{
			return _timer.running;
		}

		/**
		 * Sets / gets the label text shown on this component.
		 */
		public function set label(str:String):void
		{
			_labelText = str;
			draw();
		}
		public function get label():String
		{
			return _labelText;
		}

	}
}


code:
/**
 * InputText.as
 * Keith Peters
 * version 0.9.10
 *
 * Copyright (c) 2011 Keith Peters
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.bit101.components
{
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.text.TextField;
	import flash.text.TextFieldType;
	import flash.text.TextFormat;

	public class InputText extends Component
	{
		protected var _back:Sprite;
		protected var _password:Boolean = false;
		protected var _text:String = "";
		protected var _tf:TextField;

		/**
		 * Constructor
		 * @param parent The parent DisplayObjectContainer on which to add this InputText.
		 * @param xpos The x position to place this component.
		 * @param ypos The y position to place this component.
		 * @param text The string containing the initial text of this component.
		 * @param defaultHandler The event handling function to handle the default event for this component (change in this case).
		 */
		public function InputText(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number =  0, text:String = "", defaultHandler:Function = null)
		{
			this.text = text;
			super(parent, xpos, ypos);
			if(defaultHandler != null)
			{
				addEventListener(Event.CHANGE, defaultHandler);
			}
		}

		/**
		 * Initializes the component.
		 */
		override protected function init():void
		{
			super.init();
			setSize(100, 16);
		}

		/**
		 * Creates and adds child display objects.
		 */
		override protected function addChildren():void
		{
			_back = new Sprite();
			_back.filters = [getShadow(2, true)];
			addChild(_back);

			_tf = new TextField();
			_tf.embedFonts = Style.embedFonts;
			_tf.selectable = true;
			_tf.type = TextFieldType.INPUT;
			_tf.defaultTextFormat = new TextFormat(Style.fontName, Style.fontSize, Style.INPUT_TEXT);
			addChild(_tf);
			_tf.addEventListener(Event.CHANGE, onChange);

		}

		///////////////////////////////////
		// public methods
		///////////////////////////////////

		/**
		 * Draws the visual ui of the component.
		 */
		override public function draw():void
		{
			super.draw();
			_back.graphics.clear();
			_back.graphics.beginFill(Style.BACKGROUND);
			_back.graphics.drawRect(0, 0, _width, _height);
			_back.graphics.endFill();

			_tf.displayAsPassword = _password;

			if(_text != null)
			{
				_tf.text = _text;
			}
			else
			{
				_tf.text = "";
			}
			_tf.width = _width - 4;
			if(_tf.text == "")
			{
				_tf.text = "X";
				_tf.height = Math.min(_tf.textHeight + 4, _height);
				_tf.text = "";
			}
			else
			{
				_tf.height = Math.min(_tf.textHeight + 4, _height);
			}
			_tf.x = 2;
			_tf.y = Math.round(_height / 2 - _tf.height / 2);
		}

		///////////////////////////////////
		// event handlers
		///////////////////////////////////

		/**
		 * Internal change handler.
		 * @param event The Event passed by the system.
		 */
		protected function onChange(event:Event):void
		{
			_text = _tf.text;
			event.stopImmediatePropagation();
			dispatchEvent(event);
		}

		///////////////////////////////////
		// getter/setters
		///////////////////////////////////

		/**
		 * Gets / sets the text shown in this InputText.
		 */
		public function set text(t:String):void
		{
			_text = t;
			if(_text == null) _text = "";
			invalidate();
		}
		public function get text():String
		{
			return _text;
		}

		/**
		 * Returns a reference to the internal text field in the component.
		 */
		public function get textField():TextField
		{
			return _tf;
		}

		/**
		 * Gets / sets the list of characters that are allowed in this TextInput.
		 */
		public function set restrict(str:String):void
		{
			_tf.restrict = str;
		}
		public function get restrict():String
		{
			return _tf.restrict;
		}

		/**
		 * Gets / sets the maximum number of characters that can be shown in this InputText.
		 */
		public function set maxChars(max:int):void
		{
			_tf.maxChars = max;
		}
		public function get maxChars():int
		{
			return _tf.maxChars;
		}

		/**
		 * Gets / sets whether or not this input text will show up as password (asterisks).
		 */
		public function set password(b:Boolean):void
		{
			_password = b;
			invalidate();
		}
		public function get password():Boolean
		{
			return _password;
		}

        /**
         * Sets/gets whether this component is enabled or not.
         */
        public override function set enabled(value:Boolean):void
        {
            super.enabled = value;
            _tf.tabEnabled = value;
        }

	}
}

license: unknown


code:
/**
 * Knob.as
 * Keith Peters
 * version 0.9.10
 *
 * A knob component for choosing a numerical value.
 *
 * Copyright (c) 2011 Keith Peters
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

 package com.bit101.components
{
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;

	[Event(name="change", type="flash.events.Event")]
	public class Knob extends Component
	{
		public static const VERTICAL:String = "vertical";
		public static const HORIZONTAL:String = "horizontal";
		public static const ROTATE:String = "rotate";

		protected var _knob:Sprite;
		protected var _label:Label;
		protected var _labelText:String = "";
		protected var _max:Number = 100;
		protected var _min:Number = 0;
		protected var _mode:String = VERTICAL;
		protected var _mouseRange:Number = 100;
		protected var _precision:int = 1;
		protected var _radius:Number = 20;
		protected var _startX:Number;
		protected var _startY:Number;
		protected var _value:Number = 0;
		protected var _valueLabel:Label;

		/**
		 * Constructor
		 * @param parent The parent DisplayObjectContainer on which to add this Knob.
		 * @param xpos The x position to place this component.
		 * @param ypos The y position to place this component.
		 * @param label String containing the label for this component.
		 * @param defaultHandler The event handling function to handle the default event for this component (change in this case).
		 */
		public function Knob(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number =  0, label:String = "", defaultHandler:Function = null)
		{
			_labelText = label;
			super(parent, xpos, ypos);
			if(defaultHandler != null)
			{
				addEventListener(Event.CHANGE, defaultHandler);
			}
		}

		/**
		 * Initializes the component.
		 */
		override protected function init():void
		{
			super.init();
		}

		/**
		 * Creates the children for this component
		 */
		override protected function addChildren():void
		{
			_knob = new Sprite();
			_knob.buttonMode = true;
			_knob.useHandCursor = true;
			_knob.addEventListener(MouseEvent.MOUSE_DOWN, onMouseGoDown);
			addChild(_knob);

			_label = new Label();
			_label.autoSize = true;
			addChild(_label);

			_valueLabel = new Label();
			_valueLabel.autoSize = true;
			addChild(_valueLabel);

			_width = _radius * 2;
			_height = _radius * 2 + 40;		}

		/**
		 * Draw the knob at the specified radius.
		 */
		protected function drawKnob():void
		{
			_knob.graphics.clear();
			_knob.graphics.beginFill(Style.BACKGROUND);
			_knob.graphics.drawCircle(0, 0, _radius);
			_knob.graphics.endFill();

			_knob.graphics.beginFill(Style.BUTTON_FACE);
			_knob.graphics.drawCircle(0, 0, _radius - 2);
			_knob.graphics.endFill();

			_knob.graphics.beginFill(Style.BACKGROUND);
			var s:Number = _radius * .1;
			_knob.graphics.drawRect(_radius, -s, s*1.5, s * 2);
			_knob.graphics.endFill();

			_knob.x = _radius;
			_knob.y = _radius + 20;
			updateKnob();
		}

		/**
		 * Updates the rotation of the knob based on the value, then formats the value label.
		 */
		protected function updateKnob():void
		{
			_knob.rotation = -225 + (_value - _min) / (_max - _min) * 270;
			formatValueLabel();
		}

		/**
		 * Adjusts value to be within minimum and maximum.
		 */
		protected function correctValue():void
		{
			if(_max > _min)
			{
				_value = Math.min(_value, _max);
				_value = Math.max(_value, _min);
			}
			else
			{
				_value = Math.max(_value, _max);
				_value = Math.min(_value, _min);
			}
		}

		/**
		 * Formats the value of the knob to a string based on the current level of precision.
		 */
		protected function formatValueLabel():void
		{
			var mult:Number = Math.pow(10, _precision);
			var val:String = (Math.round(_value * mult) / mult).toString();
			var parts:Array = val.split(".");
			if(parts[1] == null)
			{
				if(_precision > 0)
				{
					val += ".";
				}
				for(var i:uint = 0; i < _precision; i++)
				{
					val += "0";
				}
			}
			else if(parts[1].length < _precision)
			{
				for(i = 0; i < _precision - parts[1].length; i++)
				{
					val += "0";
				}
			}
			_valueLabel.text = val;
			_valueLabel.draw();
			_valueLabel.x = width / 2 - _valueLabel.width / 2;
		}

		///////////////////////////////////
		// public methods
		///////////////////////////////////

		/**
		 * Draws the visual ui of the component.
		 */
		override public function draw():void
		{
			super.draw();

			drawKnob();

			_label.text = _labelText;
			_label.draw();
			_label.x = _radius - _label.width / 2;
			_label.y = 0;

			formatValueLabel();
			_valueLabel.x = _radius - _valueLabel.width / 2;
			_valueLabel.y = _radius * 2 + 20;

			_width = _radius * 2;
			_height = _radius * 2 + 40;
		}

		///////////////////////////////////
		// event handler
		///////////////////////////////////

		/**
		 * Internal handler for when user clicks on the knob. Starts tracking up/down motion of the mouse.
		 */
		protected function onMouseGoDown(event:MouseEvent):void
		{
			_startX = mouseX;
			_startY = mouseY;
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMoved);
			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseGoUp);
		}

		/**
		 * Internal handler for mouse move event. Updates value based on how far mouse has moved up or down.
		 */
		protected function onMouseMoved(event:MouseEvent):void
		{
			var oldValue:Number = _value;
			if(_mode == ROTATE)
			{
				var angle:Number = Math.atan2(mouseY - _knob.y, mouseX - _knob.x);
				var rot:Number = angle * 180 / Math.PI - 135;
				while(rot > 360) rot -= 360;
				while(rot < 0) rot += 360;
				if(rot > 270 && rot < 315) rot = 270;
				if(rot >= 315 && rot <= 360) rot = 0;
				_value = rot / 270 * (_max - _min) + _min;
				if(_value != oldValue)
				{
					dispatchEvent(new Event(Event.CHANGE));
				}
				_knob.rotation = rot + 135;
				formatValueLabel();
			}
			else if(_mode == VERTICAL)
			{
				var diff:Number = _startY - mouseY;
				var range:Number = _max - _min;
				var percent:Number = range / _mouseRange;
				_value += percent * diff;
				correctValue();
				if(_value != oldValue)
				{
					updateKnob();
					dispatchEvent(new Event(Event.CHANGE));
				}
				_startY = mouseY;
			}
			else if(_mode == HORIZONTAL)
			{
				diff = _startX - mouseX;
				range = _max - _min;
				percent = range / _mouseRange;
				_value -= percent * diff;
				correctValue();
				if(_value != oldValue)
				{
					updateKnob();
					dispatchEvent(new Event(Event.CHANGE));
				}
				_startX = mouseX;
			}
		}

		/**
		 * Internal handler for mouse up event. Stops mouse tracking.
		 */
		protected function onMouseGoUp(event:MouseEvent):void
		{
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMoved);
			stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseGoUp);
		}

		///////////////////////////////////
		// getter/setters
		///////////////////////////////////

		/**
		 * Gets / sets the maximum value of this knob.
		 */
		public function set maximum(m:Number):void
		{
			_max = m;
			correctValue();
			updateKnob();
		}
		public function get maximum():Number
		{
			return _max;
		}

		/**
		 * Gets / sets the minimum value of this knob.
		 */
		public function set minimum(m:Number):void
		{
			_min = m;
			correctValue();
			updateKnob();
		}
		public function get minimum():Number
		{
			return _min;
		}

		/**
		 * Sets / gets the current value of this knob.
		 */
		public function set value(v:Number):void
		{
			_value = v;
			correctValue();
			updateKnob();
		}
		public function get value():Number
		{
			return _value;
		}

		/**
		 * Sets / gets the number of pixels the mouse needs to move to make the value of the knob go from min to max.
		 */
		public function set mouseRange(value:Number):void
		{
			_mouseRange = value;
		}
		public function get mouseRange():Number
		{
			return _mouseRange;
		}

		/**
		 * Gets / sets the number of decimals to format the value label.
		 */
		public function set labelPrecision(decimals:int):void
		{
			_precision = decimals;
		}
		public function get labelPrecision():int
		{
			return _precision;
		}

		/**
		 * Gets / sets whether or not to show the value label.
		 */
		public function set showValue(value:Boolean):void
		{
			_valueLabel.visible = value;
		}
		public function get showValue():Boolean
		{
			return _valueLabel.visible;
		}

		/**
		 * Gets / sets the text shown in this component's label.
		 */
		public function set label(str:String):void
		{
			_labelText = str;
			draw();
		}
		public function get label():String
		{
			return _labelText;
		}

		public function set mode(value:String):void
		{
			_mode = value;
		}
		public function get mode():String
		{
			return _mode;
		}

        public function get radius():Number
        {
            return _radius;
        }

        public function set radius(value:Number):void
        {
            _radius = value;
 			_width = _radius * 2;
			_height = _radius * 2 + 40;
            invalidate();
        }
    }
}


code:
/**
 * Label.as
 * Keith Peters
 * version 0.9.10
 *
 * A Label component for displaying a single line of text.
 *
 * Copyright (c) 2011 Keith Peters
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.bit101.components
{
	import flash.display.DisplayObjectContainer;
	import flash.events.Event;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;

	[Event(name="resize", type="flash.events.Event")]
	public class Label extends Component
	{
		protected var _autoSize:Boolean = true;
		protected var _text:String = "";
		protected var _tf:TextField;

		/**
		 * Constructor
		 * @param parent The parent DisplayObjectContainer on which to add this Label.
		 * @param xpos The x position to place this component.
		 * @param ypos The y position to place this component.
		 * @param text The string to use as the initial text in this component.
		 */
		public function Label(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number =  0, text:String = "")
		{
			this.text = text;
			super(parent, xpos, ypos);
		}

		/**
		 * Initializes the component.
		 */
		override protected function init():void
		{
			super.init();
			mouseEnabled = false;
			mouseChildren = false;
		}

		/**
		 * Creates and adds the child display objects of this component.
		 */
		override protected function addChildren():void
		{
			_height = 18;
			_tf = new TextField();
			_tf.height = _height;
			_tf.embedFonts = Style.embedFonts;
			_tf.selectable = false;
			_tf.mouseEnabled = false;
			_tf.defaultTextFormat = new TextFormat(Style.fontName, Style.fontSize, Style.LABEL_TEXT);
			_tf.text = _text;
			addChild(_tf);
			draw();
		}

		///////////////////////////////////
		// public methods
		///////////////////////////////////

		/**
		 * Draws the visual ui of the component.
		 */
		override public function draw():void
		{
			super.draw();
			_tf.text = _text;
			if(_autoSize)
			{
				_tf.autoSize = TextFieldAutoSize.LEFT;
				_width = _tf.width;
				dispatchEvent(new Event(Event.RESIZE));
			}
			else
			{
				_tf.autoSize = TextFieldAutoSize.NONE;
				_tf.width = _width;
			}
			_height = _tf.height = 18;
		}

		///////////////////////////////////
		// event handlers
		///////////////////////////////////

		///////////////////////////////////
		// getter/setters
		///////////////////////////////////

		/**
		 * Gets / sets the text of this Label.
		 */
		public function set text(t:String):void
		{
			_text = t;
			if(_text == null) _text = "";
			invalidate();
		}
		public function get text():String
		{
			return _text;
		}

		/**
		 * Gets / sets whether or not this Label will autosize.
		 */
		public function set autoSize(b:Boolean):void
		{
			_autoSize = b;
		}
		public function get autoSize():Boolean
		{
			return _autoSize;
		}

		/**
		 * Gets the internal TextField of the label if you need to do further customization of it.
		 */
		public function get textField():TextField
		{
			return _tf;
		}
	}
}


code:
/**
 * List.as
 * Keith Peters
 * version 0.9.10
 *
 * A scrolling list of selectable items.
 *
 * Copyright (c) 2011 Keith Peters
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.bit101.components
{
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;

	[Event(name="select", type="flash.events.Event")]
	public class List extends Component
	{
		protected var _items:Array;
		protected var _itemHolder:Sprite;
		protected var _panel:Panel;
		protected var _listItemHeight:Number = 20;
		protected var _listItemClass:Class =ListItem;
		protected var _scrollbar:VScrollBar;
		protected var _selectedIndex:int = -1;
		protected var _defaultColor:uint = Style.LIST_DEFAULT;
		protected var _alternateColor:uint = Style.LIST_ALTERNATE;
		protected var _selectedColor:uint = Style.LIST_SELECTED;
		protected var _rolloverColor:uint = Style.LIST_ROLLOVER;
		protected var _alternateRows:Boolean = false;

		/**
		 * Constructor
		 * @param parent The parent DisplayObjectContainer on which to add this List.
		 * @param xpos The x position to place this component.
		 * @param ypos The y position to place this component.
		 * @param items An array of items to display in the list. Either strings or objects with label property.
		 */
		public function List(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0, items:Array=null)
		{
			if(items != null)
			{
				_items = items;
			}
			else
			{
				_items = new Array();
			}
			super(parent, xpos, ypos);
		}

		/**
		 * Initilizes the component.
		 */
		protected override function init() : void
		{
			super.init();
			setSize(100, 100);
			addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
            addEventListener(Event.RESIZE, onResize);
            makeListItems();
            fillItems();
		}

		/**
		 * Creates and adds the child display objects of this component.
		 */
		protected override function addChildren() : void
		{
			super.addChildren();
			_panel = new Panel(this, 0, 0);
			_panel.color = _defaultColor;
			_itemHolder = new Sprite();
			_panel.content.addChild(_itemHolder);
			_scrollbar = new VScrollBar(this, 0, 0, onScroll);
            _scrollbar.setSliderParams(0, 0, 0);
		}

		/**
		 * Creates all the list items based on data.
		 */
		protected function makeListItems():void
		{
			var item:ListItem;
			while(_itemHolder.numChildren > 0)
			{
				item = ListItem(_itemHolder.getChildAt(0));
				item.removeEventListener(MouseEvent.CLICK, onSelect);
				_itemHolder.removeChildAt(0);
			}

            var numItems:int = Math.ceil(_height / _listItemHeight);
			numItems = Math.min(numItems, _items.length);
            numItems = Math.max(numItems, 1);
			for(var i:int = 0; i < numItems; i++)
			{

				item = new _listItemClass(_itemHolder, 0, i * _listItemHeight);
				item.setSize(width, _listItemHeight);
				item.defaultColor = _defaultColor;

				item.selectedColor = _selectedColor;
				item.rolloverColor = _rolloverColor;
				item.addEventListener(MouseEvent.CLICK, onSelect);
			}
		}

        protected function fillItems():void
        {
            var offset:int = _scrollbar.value;
            var numItems:int = Math.ceil(_height / _listItemHeight);
			numItems = Math.min(numItems, _items.length);
            for(var i:int = 0; i < numItems; i++)
            {

                var item:ListItem;
				try {
					item = _itemHolder.getChildAt(i) as ListItem;
				} catch (e:*) {
					item = new ListItem();
				}
				if(offset + i < _items.length)
				{
	                item.data = _items[offset + i];
				}
				else
				{
					item.data = "";
				}
				if(_alternateRows)
				{
					item.defaultColor = ((offset + i) % 2 == 0) ? _defaultColor : _alternateColor;
				}
				else
				{
					item.defaultColor = _defaultColor;
				}
                if(offset + i == _selectedIndex)
                {
                    item.selected = true;
                }
                else
                {
                    item.selected = false;
                }
            }
        }

		/**
		 * If the selected item is not in view, scrolls the list to make the selected item appear in the view.
		 */
		protected function scrollToSelection():void
		{
            var numItems:int = Math.ceil(_height / _listItemHeight);
			if(_selectedIndex != -1)
			{
				if(_scrollbar.value + numItems < _selectedIndex)
				{
                    _scrollbar.value = _selectedIndex - numItems + 1;
				}
			}
			else
			{
				_scrollbar.value = 0;
			}
            fillItems();
		}

		///////////////////////////////////
		// public methods
		///////////////////////////////////

		/**
		 * Draws the visual ui of the component.
		 */
		public override function draw() : void
		{
			super.draw();

			_selectedIndex = Math.min(_selectedIndex, _items.length - 1);

			// panel
			_panel.setSize(_width, _height);
			_panel.color = _defaultColor;
			_panel.draw();

			// scrollbar
			_scrollbar.x = _width - 10;
			var contentHeight:Number = _items.length * _listItemHeight;
			_scrollbar.setThumbPercent(_height / contentHeight);
			var pageSize:Number = Math.floor(_height / _listItemHeight);
            _scrollbar.maximum = Math.max(0, _items.length - pageSize);
			_scrollbar.pageSize = pageSize;
			_scrollbar.height = _height;
			_scrollbar.draw();
            scrollToSelection();
		}

		/**
		 * Adds an item to the list.
		 * @param item The item to add. Can be a string or an object containing a string property named label.
		 */
		public function addItem(item:Object):void
		{
			_items.push(item);
			invalidate();
			makeListItems();
      		fillItems();
		}

		/**
		 * Adds an item to the list at the specified index.
		 * @param item The item to add. Can be a string or an object containing a string property named label.
		 * @param index The index at which to add the item.
		 */
		public function addItemAt(item:Object, index:int):void
		{
			index = Math.max(0, index);
			index = Math.min(_items.length, index);
			_items.splice(index, 0, item);
			invalidate();
      makeListItems();
      fillItems();
		}

		/**
		 * Removes the referenced item from the list.
		 * @param item The item to remove. If a string, must match the item containing that string. If an object, must be a reference to the exact same object.
		 */
		public function removeItem(item:Object):void
		{
			var index:int = _items.indexOf(item);
			removeItemAt(index);
		}

		/**
		 * Removes the item from the list at the specified index
		 * @param index The index of the item to remove.
		 */
		public function removeItemAt(index:int):void
		{
			if(index < 0 || index >= _items.length) return;
			_items.splice(index, 1);
			invalidate();
      makeListItems();
      fillItems();
		}

		/**
		 * Removes all items from the list.
		 */
		public function removeAll():void
		{
			_items.length = 0;
			invalidate();
      makeListItems();
      fillItems();
		}

		///////////////////////////////////
		// event handlers
		///////////////////////////////////

		/**
		 * Called when a user selects an item in the list.
		 */
		protected function onSelect(event:Event):void
		{
			if(! (event.target is ListItem)) return;

			var offset:int = _scrollbar.value;

			for(var i:int = 0; i < _itemHolder.numChildren; i++)
			{
				if(_itemHolder.getChildAt(i) == event.target) _selectedIndex = i + offset;
				ListItem(_itemHolder.getChildAt(i)).selected = false;
			}
			ListItem(event.target).selected = true;
			dispatchEvent(new Event(Event.SELECT));
		}

		/**
		 * Called when the user scrolls the scroll bar.
		 */
		protected function onScroll(event:Event):void
		{
            fillItems();
		}

		/**
		 * Called when the mouse wheel is scrolled over the component.
		 */
		protected function onMouseWheel(event:MouseEvent):void
		{
			_scrollbar.value -= event.delta;
            fillItems();
		}

        protected function onResize(event:Event):void
        {
            makeListItems();
            fillItems();
        }
		///////////////////////////////////
		// getter/setters
		///////////////////////////////////

		/**
		 * Sets / gets the index of the selected list item.
		 */
		public function set selectedIndex(value:int):void
		{
			if(value >= 0 && value < _items.length)
			{
				_selectedIndex = value;
			}
			else
			{
				_selectedIndex = -1;
			}
			invalidate();
			dispatchEvent(new Event(Event.SELECT));
		}
		public function get selectedIndex():int
		{
			return _selectedIndex;
		}

		/**
		 * Sets / gets the item in the list, if it exists.
		 */
		public function set selectedItem(item:Object):void
		{
			var index:int = _items.indexOf(item);
				selectedIndex = index;
				invalidate();
				dispatchEvent(new Event(Event.SELECT));
		}
		public function get selectedItem():Object
		{
			if(_selectedIndex >= 0 && _selectedIndex < _items.length)
			{
				return _items[_selectedIndex];
			}
			return null;
		}

		/**
		 * Sets/gets the default background color of list items.
		 */
		public function set defaultColor(value:uint):void
		{
			_defaultColor = value;
			invalidate();
		}
		public function get defaultColor():uint
		{
			return _defaultColor;
		}

		/**
		 * Sets/gets the selected background color of list items.
		 */
		public function set selectedColor(value:uint):void
		{
			_selectedColor = value;
			invalidate();
		}
		public function get selectedColor():uint
		{
			return _selectedColor;
		}

		/**
		 * Sets/gets the rollover background color of list items.
		 */
		public function set rolloverColor(value:uint):void
		{
			_rolloverColor = value;
			invalidate();
		}
		public function get rolloverColor():uint
		{
			return _rolloverColor;
		}

		/**
		 * Sets the height of each list item.
		 */
		public function set listItemHeight(value:Number):void
		{
			_listItemHeight = value;
            makeListItems();
			invalidate();
		}
		public function get listItemHeight():Number
		{
			return _listItemHeight;
		}

		/**
		 * Sets / gets the list of items to be shown.
		 */
		public function set items(value:Array):void
		{
			_items = value;
			invalidate();
		}
		public function get items():Array
		{
			return _items;
		}

		/**
		 * Sets / gets the class used to render list items. Must extend ListItem.
		 */
		public function set listItemClass(value:Class):void
		{
			_listItemClass = value;
			makeListItems();
			invalidate();
		}
		public function get listItemClass():Class
		{
			return _listItemClass;
		}

		/**
		 * Sets / gets the color for alternate rows if alternateRows is set to true.
		 */
		public function set alternateColor(value:uint):void
		{
			_alternateColor = value;
			invalidate();
		}
		public function get alternateColor():uint
		{
			return _alternateColor;
		}

		/**
		 * Sets / gets whether or not every other row will be colored with the alternate color.
		 */
		public function set alternateRows(value:Boolean):void
		{
			_alternateRows = value;
			invalidate();
		}
		public function get alternateRows():Boolean
		{
			return _alternateRows;
		}

        /**
         * Sets / gets whether the scrollbar will auto hide when there is nothing to scroll.
         */
        public function set autoHideScrollBar(value:Boolean):void
        {
            _scrollbar.autoHide = value;
        }
        public function get autoHideScrollBar():Boolean
        {
            return _scrollbar.autoHide;
        }

	}
}


code:
/**
 * ListItem.as
 * Keith Peters
 * version 0.9.10
 *
 * A single item in a list.
 *
 * Copyright (c) 2011 Keith Peters
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.bit101.components
{
	import flash.display.DisplayObjectContainer;
	import flash.events.MouseEvent;

	public class ListItem extends Component
	{
		protected var _data:Object;
		protected var _label:Label;
		protected var _defaultColor:uint = 0xffffff;
		protected var _selectedColor:uint = 0xdddddd;
		protected var _rolloverColor:uint = 0xeeeeee;
		protected var _selected:Boolean;
		protected var _mouseOver:Boolean = false;

		/**
		 * Constructor
		 * @param parent The parent DisplayObjectContainer on which to add this ListItem.
		 * @param xpos The x position to place this component.
		 * @param ypos The y position to place this component.
		 * @param data The string to display as a label or object with a label property.
		 */
		public function ListItem(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0, data:Object = null)
		{
			_data = data;
			super(parent, xpos, ypos);
		}

		/**
		 * Initilizes the component.
		 */
		protected override function init() : void
		{
			super.init();
			addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
			setSize(100, 20);
		}

		/**
		 * Creates and adds the child display objects of this component.
		 */
		protected override function addChildren() : void
		{
			super.addChildren();
			_label = new Label(this, 5, 0);
            _label.draw();
		}

		///////////////////////////////////
		// public methods
		///////////////////////////////////

		/**
		 * Draws the visual ui of the component.
		 */
		public override function draw() : void
		{
			super.draw();
			graphics.clear();

			if(_selected)
			{
				graphics.beginFill(_selectedColor);
			}
			else if(_mouseOver)
			{
				graphics.beginFill(_rolloverColor);
			}
			else
			{
				graphics.beginFill(_defaultColor);
			}
			graphics.drawRect(0, 0, width, height);
			graphics.endFill();

            if(_data == null) return;

			if(_data is String)
			{
                _label.text = _data as String;
			}
			else if(_data.hasOwnProperty("label") && _data.label is String)
			{
				_label.text = _data.label;
			}
			else
            {
				_label.text = _data.toString();
			}
		}

		///////////////////////////////////
		// event handlers
		///////////////////////////////////

		/**
		 * Called when the user rolls the mouse over the item. Changes the background color.
		 */
		protected function onMouseOver(event:MouseEvent):void
		{
			addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
			_mouseOver = true;
			invalidate();
		}

		/**
		 * Called when the user rolls the mouse off the item. Changes the background color.
		 */
		protected function onMouseOut(event:MouseEvent):void
		{
			removeEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
			_mouseOver = false;
			invalidate();
		}

		///////////////////////////////////
		// getter/setters
		///////////////////////////////////

		/**
		 * Sets/gets the string that appears in this item.
		 */
		public function set data(value:Object):void
		{
			_data = value;
			invalidate();
		}
		public function get data():Object
		{
			return _data;
		}

		/**
		 * Sets/gets whether or not this item is selected.
		 */
		public function set selected(value:Boolean):void
		{
			_selected = value;
			invalidate();
		}
		public function get selected():Boolean
		{
			return _selected;
		}

		/**
		 * Sets/gets the default background color of list items.
		 */
		public function set defaultColor(value:uint):void
		{
			_defaultColor = value;
			invalidate();
		}
		public function get defaultColor():uint
		{
			return _defaultColor;
		}

		/**
		 * Sets/gets the selected background color of list items.
		 */
		public function set selectedColor(value:uint):void
		{
			_selectedColor = value;
			invalidate();
		}
		public function get selectedColor():uint
		{
			return _selectedColor;
		}

		/**
		 * Sets/gets the rollover background color of list items.
		 */
		public function set rolloverColor(value:uint):void
		{
			_rolloverColor = value;
			invalidate();
		}
		public function get rolloverColor():uint
		{
			return _rolloverColor;
		}

	}
}


code:
/**
 * Meter.as
 * Keith Peters
 * version 0.9.10
 *
 * A meter component similar to a voltage meter, with a dial and a needle that indicates a value.
 *
 * Copyright (c) 2011 Keith Peters
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.bit101.components
{
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filters.DropShadowFilter;

	public class Meter extends Component
	{
		protected var _damp:Number = .8;
		protected var _dial:Sprite;
		protected var _label:Label;
		protected var _labelText:String;
		protected var _maximum:Number = 1.0;
		protected var _maxLabel:Label;
		protected var _minimum:Number = 0.0;
		protected var _minLabel:Label;
		protected var _needle:Sprite;
		protected var _needleMask:Sprite;
		protected var _showValues:Boolean = true;
		protected var _targetRotation:Number = 0;
		protected var _value:Number = 0.0;
		protected var _velocity:Number = 0;

		/**
		 * Constructor
		 * @param parent The parent DisplayObjectContainer on which to add this Meter.
		 * @param xpos The x position to place this component.
		 * @param ypos The y position to place this component.
		 * @param text The string to use as the initial text in this component.
		 */
		public function Meter(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number =  0, text:String = "")
		{
			_labelText = text;
			super(parent, xpos, ypos);
		}

		/**
		 * Initializes the component.
		 */
		override protected function init():void
		{
			super.init();
			_width = 200;
			_height = 100;
		}

		/**
		 * Creates and adds the child display objects of this component.
		 */
		override protected function addChildren():void
		{
			_dial = new Sprite();
			addChild(_dial);

			_needle = new Sprite();
			_needle.rotation = -50;
			_dial.addChild(_needle);

			_needleMask = new Sprite();
			addChild(_needleMask);
			_dial.mask = _needleMask;

			_minLabel = new Label(this);
			_minLabel.text = _minimum.toString();

			_maxLabel = new Label(this);
			_maxLabel.autoSize = true;
			_maxLabel.text = _maximum.toString();

			_label = new Label(this);
			_label.text = _labelText;
		}

		///////////////////////////////////
		// public methods
		///////////////////////////////////

		/**
		 * Draws the visual ui of the component.
		 */
		override public function draw():void
		{
			var startAngle:Number = -140 * Math.PI / 180;
			var endAngle:Number = -40 * Math.PI / 180;

			drawBackground();
			drawDial(startAngle, endAngle);
			drawTicks(startAngle, endAngle);
			drawNeedle();

			_minLabel.move(10, _height - _minLabel.height - 4);
			_maxLabel.move(_width - _maxLabel.width - 10, _height - _maxLabel.height - 4);
			_label.move((_width - _label.width) / 2, _height * .5);
			update();
		}

		/**
		 * Sets the size of the component. Adjusts height to be 1/2 width.
		 * @param w The width of the component.
		 * @param h The height of the component.
		 */
		override public function setSize(w:Number, h:Number):void
		{
			h = w / 2;
			super.setSize(w, h);
		}

		///////////////////////////////////
		// public methods
		///////////////////////////////////

		/**
		 * Draws the background of the component.
		 */
		protected function drawBackground():void
		{
			graphics.clear();
			graphics.beginFill(Style.BACKGROUND);
			graphics.drawRect(0, 0, _width, _height);
			graphics.endFill();

			graphics.beginFill(Style.PANEL);
			graphics.drawRect(1, 1, _width - 2, _height - 2);
			graphics.endFill();
		}

		/**
		 * Draws the dial.
		 */
		protected function drawDial(startAngle:Number, endAngle:Number):void
		{
			_dial.x = _width / 2;
			_dial.y = _height * 1.25;
			_dial.graphics.clear();
			_dial.graphics.lineStyle(0, Style.BACKGROUND);
			_dial.graphics.beginFill(Style.BUTTON_FACE);
			var r1:Number = _height * 1.05;
			var r2:Number = _height * 0.96;

			_dial.graphics.moveTo(Math.cos(startAngle) * r1, Math.sin(startAngle) * r1);
			for(var i:Number = startAngle; i < endAngle; i += .1)
			{
				_dial.graphics.lineTo(Math.cos(i) * r1, Math.sin(i) * r1);
			}
			_dial.graphics.lineTo(Math.cos(endAngle) * r1, Math.sin(endAngle) * r1);

			_dial.graphics.lineTo(Math.cos(endAngle) * r2, Math.sin(endAngle) * r2);
			for(i = endAngle; i > startAngle; i -= .1)
			{
				_dial.graphics.lineTo(Math.cos(i) * r2, Math.sin(i) * r2);
			}
			_dial.graphics.lineTo(Math.cos(startAngle) * r2, Math.sin(startAngle) * r2);
			_dial.graphics.lineTo(Math.cos(startAngle) * r1, Math.sin(startAngle) * r1);

		}

		/**
		 * Draws the tick marks on the dial.
		 */
		protected function drawTicks(startAngle:Number, endAngle:Number):void
		{
			var r1:Number = _height * 1.05;
			var r2:Number = _height * 0.96;
			var r3:Number = _height * 1.13;
			var tick:Number = 0;
			for(var i:int = 0; i < 9; i++)
			{
				var angle:Number = startAngle + i * (endAngle - startAngle) / 8;
				_dial.graphics.moveTo(Math.cos(angle) * r2, Math.sin(angle) * r2);
				if(tick++ % 2 == 0)
				{
					_dial.graphics.lineTo(Math.cos(angle) * r3, Math.sin(angle) * r3);
				}
				else
				{
					_dial.graphics.lineTo(Math.cos(angle) * r1, Math.sin(angle) * r1);
				}
			}
		}

		/**
		 * Draws the needle.
		 */
		protected function drawNeedle():void
		{
			_needle.graphics.clear();
			_needle.graphics.beginFill(0xff0000);
			_needle.graphics.drawRect(-0.5, -_height * 1.10, 1, _height * 1.10);
			_needle.filters = [new DropShadowFilter(4, 0, 0, 1, 3, 3, .2)];

			_needleMask.graphics.clear();
			_needleMask.graphics.beginFill(0);
			_needleMask.graphics.drawRect(0, 0, _width, _height);
			_needleMask.graphics.endFill();
		}

		/**
		 * Updates the target rotation of the needle and starts an enterframe handler to spring it to that point.
		 */
		protected function update():void
		{
			_value = Math.max(_value, _minimum);
			_value = Math.min(_value, _maximum);
			_targetRotation = -50 + (_value - _minimum) / (_maximum - _minimum) * 100;
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}

		///////////////////////////////////
		// event handlers
		///////////////////////////////////

		/**
		 * Handles the enterFrame event to spring the needle to the target rotation.
		 */
		protected function onEnterFrame(event:Event):void
		{
			var dist:Number = _targetRotation - _needle.rotation;
			_velocity += dist * .05;
			_velocity *= _damp;
			if(Math.abs(_velocity) < .1 && Math.abs(dist) < .1)
			{
				_needle.rotation = _targetRotation;
				removeEventListener(Event.ENTER_FRAME, onEnterFrame);
			}
			else
			{
				_needle.rotation += _velocity;
			}
		}

		///////////////////////////////////
		// getter/setters
		///////////////////////////////////

		/**
		 * Gets / sets the maximum value for the meter.
		 */
		public function set maximum(value:Number):void
		{
			_maximum = value;
			_maxLabel.text = _maximum.toString();
			update();
		}
		public function get maximum():Number
		{
			return _maximum;
		}

		/**
		 * Gets / sets the minimum value for the meter.
		 */
		public function set minimum(value:Number):void
		{
			_minimum = value;
			_minLabel.text = _minimum.toString();
			update();
		}
		public function get minimum():Number
		{
			return _minimum;
		}

		/**
		 * Gets / sets the current value for the meter.
		 */
		public function set value(val:Number):void
		{
			_value = val;
			update();
		}
		public function get value():Number
		{
			return _value;
		}

		/**
		 * Gets / sets the label shown on the meter.
		 */
		public function set label(value:String):void
		{
			_labelText = value;
			_label.text = _labelText;
		}
		public function get label():String
		{
			return _labelText;
		}

		/**
		 * Gets / sets whether or not value labels will be shown for max and min values.
		 */
		public function set showValues(value:Boolean):void
		{
			_showValues = value;
			_minLabel.visible = _showValues;
			_maxLabel.visible = _showValues;
		}
		public function get showValues():Boolean
		{
			return _showValues;
		}

		/**
		 * Gets / sets the damping value for the meter.
		 */
		public function set damp(value:Number):void
		{
			_damp = value;
		}
		public function get damp():Number
		{
			return _damp;
		}

	}
}


code:
/**
 * NumericStepper.as
 * Keith Peters
 * version 0.9.10
 *
 * A component allowing for entering a numeric value with the keyboard, or by pressing up/down buttons.
 *
 * Copyright (c) 2011 Keith Peters
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.bit101.components
{

	import flash.display.DisplayObjectContainer;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.utils.Timer;

	[Event(name="change", type="flash.events.Event")]
	public class NumericStepper extends Component
	{
		protected const DELAY_TIME:int = 500;
		protected const UP:String = "up";
        protected const DOWN:String = "down";
		protected var _minusBtn:PushButton;

        protected var _repeatTime:int = 100;
        protected var _plusBtn:PushButton;
		protected var _valueText:InputText;
		protected var _value:Number = 0;
		protected var _step:Number = 1;
		protected var _labelPrecision:int = 1;
		protected var _maximum:Number = Number.POSITIVE_INFINITY;
		protected var _minimum:Number = Number.NEGATIVE_INFINITY;
		protected var _delayTimer:Timer;
		protected var _repeatTimer:Timer;
		protected var _direction:String;

		/**
		 * Constructor
		 * @param parent The parent DisplayObjectContainer on which to add this Slider.
		 * @param xpos The x position to place this component.
		 * @param ypos The y position to place this component.
		 * @param defaultHandler The event handling function to handle the default event for this component (change in this case).
		 */
		public function NumericStepper(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0, defaultHandler:Function = null)
		{
			super(parent, xpos, ypos);
			if(defaultHandler != null)
			{
				addEventListener(Event.CHANGE, defaultHandler);
			}
		}

		/**
		 * Initializes the component.
		 */
		protected override function init():void
		{
			super.init();
			setSize(80, 16);
			_delayTimer = new Timer(DELAY_TIME, 1);
			_delayTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onDelayComplete);
			_repeatTimer = new Timer(_repeatTime);
			_repeatTimer.addEventListener(TimerEvent.TIMER, onRepeat);
		}

		/**
		 * Creates and adds the child display objects of this component.
		 */
		protected override function addChildren():void
		{
			_valueText = new InputText(this, 0, 0, "0", onValueTextChange);
			_valueText.restrict = "-0123456789.";
			_minusBtn = new PushButton(this, 0, 0, "-");
			_minusBtn.addEventListener(MouseEvent.MOUSE_DOWN, onMinus);
			_minusBtn.setSize(16, 16);
			_plusBtn = new PushButton(this, 0, 0, "+");
			_plusBtn.addEventListener(MouseEvent.MOUSE_DOWN, onPlus);
			_plusBtn.setSize(16, 16);
		}

		protected function increment():void
		{
			if(_value + _step <= _maximum)
			{
				_value += _step;
				invalidate();
				dispatchEvent(new Event(Event.CHANGE));
			}
		}

		protected function decrement():void
		{
			if(_value - _step >= _minimum)
			{
				_value -= _step;
				invalidate();
				dispatchEvent(new Event(Event.CHANGE));
			}
		}

		///////////////////////////////////
		// public methods
		///////////////////////////////////

		/**
		 * Draws the visual ui of the component.
		 */
		public override function draw():void
		{
			_plusBtn.x = _width - 16;
			_minusBtn.x = _width - 32;
			_valueText.text = (Math.round(_value * Math.pow(10, _labelPrecision)) / Math.pow(10, _labelPrecision)).toString();
			_valueText.width = _width - 32;
			_valueText.draw();
		}

		///////////////////////////////////
		// event handlers
		///////////////////////////////////

		/**
		 * Called when the minus button is pressed. Decrements the value by the step amount.
		 */
		protected function onMinus(event:MouseEvent):void
		{
			decrement();
			_direction = DOWN;
			_delayTimer.start();
			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseGoUp);
		}

		/**
		 * Called when the plus button is pressed. Increments the value by the step amount.
		 */
		protected function onPlus(event:MouseEvent):void
		{
			increment();
			_direction = UP;
			_delayTimer.start();
			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseGoUp);
		}

		protected function onMouseGoUp(event:MouseEvent):void
		{
			_delayTimer.stop();
			_repeatTimer.stop();
		}

		/**
		 * Called when the value is changed manually.
		 */
		protected function onValueTextChange(event:Event):void
		{
			event.stopImmediatePropagation();
			var newVal:Number = Number(_valueText.text);
			if(newVal <= _maximum && newVal >= _minimum)
			{
				_value = newVal;
				invalidate();
				dispatchEvent(new Event(Event.CHANGE));
			}
		}

		protected function onDelayComplete(event:TimerEvent):void
		{
			_repeatTimer.start();
		}

		protected function onRepeat(event:TimerEvent):void
		{
			if(_direction == UP)
			{
				increment();
			}
			else
			{
				decrement();
			}
		}

		///////////////////////////////////
		// getter/setters
		///////////////////////////////////

		/**
		 * Sets / gets the current value of this component.
		 */
		public function set value(val:Number):void
		{
			if(val <= _maximum && val >= _minimum)
			{
				_value = val;
				invalidate();
			}
		}
		public function get value():Number
		{
			return _value;
		}

		/**
		 * Sets / gets the amount the value will change when the up or down button is pressed. Must be zero or positive.
		 */
		public function set step(value:Number):void
		{
			if(value < 0)
			{
				throw new Error("NumericStepper step must be positive.");
			}
			_step = value;
		}
		public function get step():Number
		{
			return _step;
		}

		/**
		 * Sets / gets how many decimal points of precision will be shown.
		 */
		public function set labelPrecision(value:int):void
		{
			_labelPrecision = value;
			invalidate();
		}
		public function get labelPrecision():int
		{
			return _labelPrecision;
		}

		/**
		 * Sets / gets the maximum value for this component.
		 */
		public function set maximum(value:Number):void
		{
			_maximum = value;
			if(_value > _maximum)
			{
				_value = _maximum;
				invalidate();
			}
		}
		public function get maximum():Number
		{
			return _maximum;
		}

		/**
		 * Sets / gets the maximum value for this component.
		 */
		public function set minimum(value:Number):void
		{
			_minimum = value;
			if(_value < _minimum)
			{
				_value = _minimum;
				invalidate();
			}
		}
		public function get minimum():Number
		{
			return _minimum;
		}

        /**
         * Gets/sets the update rate that the stepper will change its value if a button is held down.
         */
        public function get repeatTime():int
        {
            return _repeatTime;
        }

        public function set repeatTime(value:int):void
        {
            // shouldn't be any need to set it faster than 10 ms. guard against negative.
            _repeatTime = Math.max(value, 10);
            _repeatTimer.delay = _repeatTime;
        }
    }
}


code:
/**
 * Panel.as
 * Keith Peters
 * version 0.9.10
 *
 * A rectangular panel. Can be used as a container for other components.
 *
 * Copyright (c) 2011 Keith Peters
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.bit101.components
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;

	public class Panel extends Component
	{
		protected var _mask:Sprite;
		protected var _background:Sprite;
		protected var _color:int = -1;
		protected var _alpha:int = 100;
		protected var _shadow:Boolean = true;
		protected var _gridSize:int = 10;
		protected var _showGrid:Boolean = false;
		protected var _gridColor:uint = 0xd0d0d0;

		/**
		 * Container for content added to this panel. This is masked, so best to add children to content, rather than directly to the panel.
		 */
		public var content:Sprite;

		/**
		 * Constructor
		 * @param parent The parent DisplayObjectContainer on which to add this Panel.
		 * @param xpos The x position to place this component.
		 * @param ypos The y position to place this component.
		 */
		public function Panel(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number =  0)
		{
			super(parent, xpos, ypos);
		}

		/**
		 * Initializes the component.
		 */
		override protected function init():void
		{
			super.init();
			setSize(100, 100);
		}

		/**
		 * Creates and adds the child display objects of this component.
		 */
		override protected function addChildren():void
		{
			_background = new Sprite();
			super.addChild(_background);

			_mask = new Sprite();
			_mask.mouseEnabled = false;
			super.addChild(_mask);

			content = new Sprite();
			super.addChild(content);
			content.mask = _mask;

			filters = [getShadow(2, true)];
		}

		///////////////////////////////////
		// public methods
		///////////////////////////////////

		/**
		 * Overridden to add new child to content.
		 */
		public override function addChild(child:DisplayObject):DisplayObject
		{
			content.addChild(child);
			return child;
		}

		/**
		 * Access to super.addChild
		 */
		public function addRawChild(child:DisplayObject):DisplayObject
		{
			super.addChild(child);
			return child;
		}

		/**
		 * Draws the visual ui of the component.
		 */
		override public function draw():void
		{
			super.draw();
			_background.graphics.clear();
			_background.graphics.lineStyle(1, 0, 0.1);
			if(_color == -1)
			{
				_background.graphics.beginFill(Style.PANEL);
			}
			else if(_alpha == 100)
			{
				_background.graphics.beginFill(_color);
			} else {
				_background.graphics.beginFill(_color,_alpha);
			}
			_background.graphics.drawRect(0, 0, _width, _height);
			_background.graphics.endFill();

			drawGrid();

			_mask.graphics.clear();
			_mask.graphics.beginFill(0xff0000);
			_mask.graphics.drawRect(0, 0, _width, _height);
			_mask.graphics.endFill();
		}

		protected function drawGrid():void
		{
			if(!_showGrid) return;

			_background.graphics.lineStyle(0, _gridColor);
			for(var i:int = 0; i < _width; i += _gridSize)
			{
				_background.graphics.moveTo(i, 0);
				_background.graphics.lineTo(i, _height);
			}
			for(i = 0; i < _height; i += _gridSize)
			{
				_background.graphics.moveTo(0, i);
				_background.graphics.lineTo(_width, i);
			}
		}

		///////////////////////////////////
		// event handlers
		///////////////////////////////////

		///////////////////////////////////
		// getter/setters
		///////////////////////////////////

		/**
		 * Gets / sets whether or not this Panel will have an inner shadow.
		 */
		public function set shadow(b:Boolean):void
		{
			_shadow = b;
			if(_shadow)
			{
				filters = [getShadow(2, true)];
			}
			else
			{
				filters = [];
			}
		}
		public function get shadow():Boolean
		{
			return _shadow;
		}

		/**
		 * Gets / sets the backgrond color of this panel.
		 */
		public function set color(c:int):void
		{
			_color = c;
			invalidate();
		}
		public function get color():int
		{
			return _color;
		}

		/**
		 * Sets / gets the size of the grid.
		 */
		public function set gridSize(value:int):void
		{
			_gridSize = value;
			invalidate();
		}
		public function get gridSize():int
		{
			return _gridSize;
		}

		/**
		 * Sets / gets whether or not the grid will be shown.
		 */
		public function set showGrid(value:Boolean):void
		{
			_showGrid = value;
			invalidate();
		}
		public function get showGrid():Boolean
		{
			return _showGrid;
		}

		/**
		 * Sets / gets the color of the grid lines.
		 */
		public function set gridColor(value:uint):void
		{
			_gridColor = value;
			invalidate();
		}
		public function get gridColor():uint
		{
			return _gridColor;
		}
	}
}


code:
/**
 * ProgressBar.as
 * Keith Peters
 * version 0.9.10
 *
 * A progress bar component for showing a changing value in relation to a total.
 *
 * Copyright (c) 2011 Keith Peters
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.bit101.components
{
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;

	public class ProgressBar extends Component
	{
		protected var _back:Sprite;
		protected var _bar:Sprite;
		protected var _value:Number = 0;
		protected var _max:Number = 1;

		/**
		 * Constructor
		 * @param parent The parent DisplayObjectContainer on which to add this ProgressBar.
		 * @param xpos The x position to place this component.
		 * @param ypos The y position to place this component.
		 */
		public function ProgressBar(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number =  0)
		{
			super(parent, xpos, ypos);
		}

		/**
		 * Initializes the component.
		 */
		override protected function init():void
		{
			super.init();
			setSize(100, 10);
		}

		/**
		 * Creates and adds the child display objects of this component.
		 */
		override protected function addChildren():void
		{
			_back = new Sprite();
			_back.filters = [getShadow(2, true)];
			addChild(_back);

			_bar = new Sprite();
			_bar.x = 1;
			_bar.y = 1;
			_bar.filters = [getShadow(1)];
			addChild(_bar);
		}

		/**
		 * Updates the size of the progress bar based on the current value.
		 */
		protected function update():void
		{
			_bar.scaleX = _value / _max;
		}

		///////////////////////////////////
		// public methods
		///////////////////////////////////

		/**
		 * Draws the visual ui of the component.
		 */
		override public function draw():void
		{
			super.draw();
			_back.graphics.clear();
			_back.graphics.beginFill(Style.BACKGROUND);
			_back.graphics.drawRect(0, 0, _width, _height);
			_back.graphics.endFill();

			_bar.graphics.clear();
			_bar.graphics.beginFill(Style.PROGRESS_BAR);
			_bar.graphics.drawRect(0, 0, _width - 2, _height - 2);
			_bar.graphics.endFill();
			update();
		}

		///////////////////////////////////
		// event handlers
		///////////////////////////////////

		///////////////////////////////////
		// getter/setters
		///////////////////////////////////

		/**
		 * Gets / sets the maximum value of the ProgressBar.
		 */
		public function set maximum(m:Number):void
		{
			_max = m;
			_value = Math.min(_value, _max);
			update();
		}
		public function get maximum():Number
		{
			return _max;
		}

		/**
		 * Gets / sets the current value of the ProgressBar.
		 */
		public function set value(v:Number):void
		{
			_value = Math.min(v, _max);
			update();
		}
		public function get value():Number
		{
			return _value;
		}

	}
}


code:
/**
 * PushButton.as
 * Keith Peters
 * version 0.9.10
 *
 * A basic button component with a label.
 *
 * Copyright (c) 2011 Keith Peters
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.bit101.components
{
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.events.MouseEvent;

	public class PushButton extends Component
	{
		protected var _back:Sprite;
		protected var _face:Sprite;
		protected var _label:Label;
		protected var _labelText:String = "";
		protected var _over:Boolean = false;
		protected var _down:Boolean = false;
		protected var _selected:Boolean = false;
		protected var _toggle:Boolean = false;

		/**
		 * Constructor
		 * @param parent The parent DisplayObjectContainer on which to add this PushButton.
		 * @param xpos The x position to place this component.
		 * @param ypos The y position to place this component.
		 * @param label The string to use for the initial label of this component.
 		 * @param defaultHandler The event handling function to handle the default event for this component (click in this case).
		 */
		public function PushButton(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number =  0, label:String = "", defaultHandler:Function = null)
		{
			super(parent, xpos, ypos);
			if(defaultHandler != null)
			{
				addEventListener(MouseEvent.CLICK, defaultHandler);
			}
			this.label = label;
		}

		/**
		 * Initializes the component.
		 */
		override protected function init():void
		{
			super.init();
			buttonMode = true;
			useHandCursor = true;
			setSize(100, 20);
		}

		/**
		 * Creates and adds the child display objects of this component.
		 */
		override protected function addChildren():void
		{
			_back = new Sprite();
			_back.filters = [getShadow(2, true)];
			_back.mouseEnabled = false;
			addChild(_back);

			_face = new Sprite();
			_face.mouseEnabled = false;
			_face.filters = [getShadow(1)];
			_face.x = 1;
			_face.y = 1;
			addChild(_face);

			_label = new Label();
			addChild(_label);

			addEventListener(MouseEvent.MOUSE_DOWN, onMouseGoDown);
			addEventListener(MouseEvent.ROLL_OVER, onMouseOver);
		}

		/**
		 * Draws the face of the button, color based on state.
		 */
		protected function drawFace():void
		{
			_face.graphics.clear();
			if(_down)
			{
				_face.graphics.beginFill(Style.BUTTON_DOWN);
			}
			else
			{
				_face.graphics.beginFill(Style.BUTTON_FACE);
			}
			_face.graphics.drawRect(0, 0, _width - 2, _height - 2);
			_face.graphics.endFill();
		}

		///////////////////////////////////
		// public methods
		///////////////////////////////////

		/**
		 * Draws the visual ui of the component.
		 */
		override public function draw():void
		{
			super.draw();
			_back.graphics.clear();
			_back.graphics.beginFill(Style.BACKGROUND);
			_back.graphics.drawRect(0, 0, _width, _height);
			_back.graphics.endFill();

			drawFace();

			_label.text = _labelText;
			_label.autoSize = true;
			_label.draw();
			if(_label.width > _width - 4)
			{
				_label.autoSize = false;
				_label.width = _width - 4;
			}
			else
			{
				_label.autoSize = true;
			}
			_label.draw();
			_label.move(_width / 2 - _label.width / 2, _height / 2 - _label.height / 2);

		}

		///////////////////////////////////
		// event handlers
		///////////////////////////////////

		/**
		 * Internal mouseOver handler.
		 * @param event The MouseEvent passed by the system.
		 */
		protected function onMouseOver(event:MouseEvent):void
		{
			_over = true;
			addEventListener(MouseEvent.ROLL_OUT, onMouseOut);
		}

		/**
		 * Internal mouseOut handler.
		 * @param event The MouseEvent passed by the system.
		 */
		protected function onMouseOut(event:MouseEvent):void
		{
			_over = false;
			if(!_down)
			{
				_face.filters = [getShadow(1)];
			}
			removeEventListener(MouseEvent.ROLL_OUT, onMouseOut);
		}

		/**
		 * Internal mouseOut handler.
		 * @param event The MouseEvent passed by the system.
		 */
		protected function onMouseGoDown(event:MouseEvent):void
		{
			_down = true;
			drawFace();
			_face.filters = [getShadow(1, true)];
			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseGoUp);
		}

		/**
		 * Internal mouseUp handler.
		 * @param event The MouseEvent passed by the system.
		 */
		protected function onMouseGoUp(event:MouseEvent):void
		{
			if(_toggle  && _over)
			{
				_selected = !_selected;
			}
			_down = _selected;
			drawFace();
			_face.filters = [getShadow(1, _selected)];
			stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseGoUp);
		}

		///////////////////////////////////
		// getter/setters
		///////////////////////////////////

		/**
		 * Sets / gets the label text shown on this Pushbutton.
		 */
		public function set label(str:String):void
		{
			_labelText = str;
			draw();
		}
		public function get label():String
		{
			return _labelText;
		}

		public function set selected(value:Boolean):void
		{
			if(!_toggle)
			{
				value = false;
			}

			_selected = value;
			_down = _selected;
			_face.filters = [getShadow(1, _selected)];
			drawFace();
		}
		public function get selected():Boolean
		{
			return _selected;
		}

		public function set toggle(value:Boolean):void
		{
			_toggle = value;
		}
		public function get toggle():Boolean
		{
			return _toggle;
		}

	}
}


code:
/**
 * RadioButton.as
 * Keith Peters
 * version 0.9.10
 *
 * A basic radio button component, meant to be used in groups, where only one button in the group can be selected.
 * Currently only one group can be created.
 *
 * Copyright (c) 2011 Keith Peters
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.bit101.components
{
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.events.MouseEvent;

	public class RadioButton extends Component
	{
		protected var _back:Sprite;
		protected var _button:Sprite;
		protected var _selected:Boolean = false;
		protected var _label:Label;
		protected var _labelText:String = "";
		protected var _groupName:String = "defaultRadioGroup";

		protected static var buttons:Array;

		/**
		 * Constructor
		 * @param parent The parent DisplayObjectContainer on which to add this RadioButton.
		 * @param xpos The x position to place this component.
		 * @param ypos The y position to place this component.
		 * @param label The string to use for the initial label of this component.
		 * @param defaultHandler The event handling function to handle the default event for this component (click in this case).
		 */
		public function RadioButton(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number =  0, label:String = "", checked:Boolean = false, defaultHandler:Function = null)
		{
			RadioButton.addButton(this);
			_selected = checked;
			_labelText = label;
			super(parent, xpos, ypos);
			if(defaultHandler != null)
			{
				addEventListener(MouseEvent.CLICK, defaultHandler);
			}
		}

		/**
		 * Static method to add the newly created RadioButton to the list of buttons in the group.
		 * @param rb The RadioButton to add.
		 */
		protected static function addButton(rb:RadioButton):void
		{
			if(buttons == null)
			{
				buttons = new Array();
			}
			buttons.push(rb);
		}

		/**
		 * Unselects all RadioButtons in the group, except the one passed.
		 * This could use some rethinking or better naming.
		 * @param rb The RadioButton to remain selected.
		 */
		protected static function clear(rb:RadioButton):void
		{
			for(var i:uint = 0; i < buttons.length; i++)
			{
				if(buttons[i] != rb && buttons[i].groupName == rb.groupName)
				{
					buttons[i].selected = false;
				}
			}
		}

		/**
		 * Initializes the component.
		 */
		override protected function init():void
		{
			super.init();

			buttonMode = true;
			useHandCursor = true;

			addEventListener(MouseEvent.CLICK, onClick, false, 1);
			selected = _selected;
		}

		/**
		 * Creates and adds the child display objects of this component.
		 */
		override protected function addChildren():void
		{
			_back = new Sprite();
			_back.filters = [getShadow(2, true)];
			addChild(_back);

			_button = new Sprite();
			_button.filters = [getShadow(1)];
			_button.visible = false;
			addChild(_button);

			_label = new Label(this, 0, 0, _labelText);
			draw();

			mouseChildren = false;
		}

		///////////////////////////////////
		// public methods
		///////////////////////////////////

		/**
		 * Draws the visual ui of the component.
		 */
		override public function draw():void
		{
			super.draw();
			_back.graphics.clear();
			_back.graphics.beginFill(Style.BACKGROUND);
			_back.graphics.drawCircle(5, 5, 5);
			_back.graphics.endFill();

			_button.graphics.clear();
			_button.graphics.beginFill(Style.BUTTON_FACE);
			_button.graphics.drawCircle(5, 5, 3);

			_label.x = 12;
			_label.y = (10 - _label.height) / 2;
			_label.text = _labelText;
			_label.draw();
			_width = _label.width + 12;
			_height = 10;
		}

		///////////////////////////////////
		// event handlers
		///////////////////////////////////

		/**
		 * Internal click handler.
		 * @param event The MouseEvent passed by the system.
		 */
		protected function onClick(event:MouseEvent):void
		{
			selected = true;
		}

		///////////////////////////////////
		// getter/setters
		///////////////////////////////////

		/**
		 * Sets / gets the selected state of this CheckBox.
		 */
		public function set selected(s:Boolean):void
		{
			_selected = s;
			_button.visible = _selected;
			if(_selected)
			{
				RadioButton.clear(this);
			}
		}
		public function get selected():Boolean
		{
			return _selected;
		}

		/**
		 * Sets / gets the label text shown on this CheckBox.
		 */
		public function set label(str:String):void
		{
			_labelText = str;
			invalidate();
		}
		public function get label():String
		{
			return _labelText;
		}

		/**
		 * Sets / gets the group name, which allows groups of RadioButtons to function seperately.
		 */
		public function get groupName():String
		{
			return _groupName;
		}

		public function set groupName(value:String):void
		{
			_groupName = value;
		}

	}
}


code:
/**
 * RangeSlider.as
 * Keith Peters
 * version 0.9.10
 *
 * Abstract base class for HRangeSlider and VRangeSlider.
 *
 * Copyright (c) 2011 Keith Peters
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.bit101.components
{
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;

	[Event(name="change", type="flash.events.Event")]
	public class RangeSlider extends Component
	{
		protected var _back:Sprite;
		protected var _highLabel:Label;
		protected var _highValue:Number = 100;
		protected var _labelMode:String = ALWAYS;
		protected var _labelPosition:String;
		protected var _labelPrecision:int = 0;
		protected var _lowLabel:Label;
		protected var _lowValue:Number = 0;
		protected var _maximum:Number = 100;
		protected var _maxHandle:Sprite;
		protected var _minimum:Number = 0;
		protected var _minHandle:Sprite;
		protected var _orientation:String = VERTICAL;
		protected var _tick:Number = 1;

		public static const ALWAYS:String = "always";
		public static const BOTTOM:String = "bottom";
		public static const HORIZONTAL:String = "horizontal";
		public static const LEFT:String = "left";
		public static const MOVE:String = "move";
		public static const NEVER:String = "never";
		public static const RIGHT:String = "right";
		public static const TOP:String = "top";
		public static const VERTICAL:String = "vertical";

		/**
		 * Constructor
		 * @param orientation Whether the slider will be horizontal or vertical.
		 * @param parent The parent DisplayObjectContainer on which to add this Slider.
		 * @param xpos The x position to place this component.
		 * @param ypos The y position to place this component.
		 * @param defaultHandler The event handling function to handle the default event for this component (change in this case).
		 */
		public function RangeSlider(orientation:String, parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0, defaultHandler:Function = null)
		{
			_orientation = orientation;
			super(parent, xpos, ypos);
			if(defaultHandler != null)
			{
				addEventListener(Event.CHANGE, defaultHandler);
			}
		}

		/**
		 * Initializes the component.
		 */
		protected override function init():void
		{
			super.init();
			if(_orientation == HORIZONTAL)
			{
				setSize(110, 10);
				_labelPosition = TOP;
			}
			else
			{
				setSize(10, 110);
				_labelPosition = RIGHT;
			}
		}

		/**
		 * Creates and adds the child display objects of this component.
		 */
		protected override function addChildren():void
		{
			super.addChildren();
			_back = new Sprite();
			_back.filters = [getShadow(2, true)];
			addChild(_back);

			_minHandle = new Sprite();
			_minHandle.filters = [getShadow(1)];
			_minHandle.addEventListener(MouseEvent.MOUSE_DOWN, onDragMin);
			_minHandle.buttonMode = true;
			_minHandle.useHandCursor = true;
			addChild(_minHandle);

			_maxHandle = new Sprite();
			_maxHandle.filters = [getShadow(1)];
			_maxHandle.addEventListener(MouseEvent.MOUSE_DOWN, onDragMax);
			_maxHandle.buttonMode = true;
			_maxHandle.useHandCursor = true;
			addChild(_maxHandle);

			_lowLabel = new Label(this);
			_highLabel = new Label(this);
			_lowLabel.visible = (_labelMode == ALWAYS);
		}

		/**
		 * Draws the back of the slider.
		 */
		protected function drawBack():void
		{
			_back.graphics.clear();
			_back.graphics.beginFill(Style.BACKGROUND);
			_back.graphics.drawRect(0, 0, _width, _height);
			_back.graphics.endFill();
		}

		/**
		 * Draws the handles of the slider.
		 */
		protected function drawHandles():void
		{
			_minHandle.graphics.clear();
			_minHandle.graphics.beginFill(Style.BUTTON_FACE);
			_maxHandle.graphics.clear();
			_maxHandle.graphics.beginFill(Style.BUTTON_FACE);
			if(_orientation == HORIZONTAL)
			{
				_minHandle.graphics.drawRect(1, 1, _height - 2, _height - 2);
				_maxHandle.graphics.drawRect(1, 1, _height - 2, _height - 2);
			}
			else
			{
				_minHandle.graphics.drawRect(1, 1, _width - 2, _width - 2);
				_maxHandle.graphics.drawRect(1, 1, _width - 2, _width - 2);
			}
			_minHandle.graphics.endFill();
			positionHandles();
		}

		/**
		 * Adjusts positions of handles when value, maximum or minimum have changed.
		 * TODO: Should also be called when slider is resized.
		 */
		protected function positionHandles():void
		{
			var range:Number;
			if(_orientation == HORIZONTAL)
			{
				range = _width - _height * 2;
				_minHandle.x = (_lowValue - _minimum) / (_maximum - _minimum) * range;
				_maxHandle.x = _height + (_highValue - _minimum) / (_maximum - _minimum) * range;
			}
			else
			{
				range = _height - _width * 2;
				_minHandle.y = _height - _width - (_lowValue - _minimum) / (_maximum - _minimum) * range;
				_maxHandle.y = _height - _width * 2 - (_highValue - _minimum) / (_maximum - _minimum) * range;
			}
			updateLabels();
		}

		/**
		 * Sets the text and positions the labels.
		 */
		protected function updateLabels():void
		{
			_lowLabel.text = getLabelForValue(lowValue);
			_highLabel.text = getLabelForValue(highValue);
			_lowLabel.draw();
			_highLabel.draw();

			if(_orientation == VERTICAL)
			{
				_lowLabel.y = _minHandle.y + (_width - _lowLabel.height) * 0.5;
				_highLabel.y = _maxHandle.y + (_width - _highLabel.height) * 0.5;
				if(_labelPosition == LEFT)
				{
					_lowLabel.x = -_lowLabel.width - 5;
					_highLabel.x = -_highLabel.width - 5;
				}
				else
				{
					_lowLabel.x = _width + 5;
					_highLabel.x = _width + 5;
				}
			}
			else
			{
				_lowLabel.x = _minHandle.x - _lowLabel.width + _height;
				_highLabel.x = _maxHandle.x;
				if(_labelPosition == BOTTOM)
				{
					_lowLabel.y = _height + 2;
					_highLabel.y = _height + 2;
				}
				else
				{
					_lowLabel.y = -_lowLabel.height;
					_highLabel.y = -_highLabel.height;
				}

			}
		}

		/**
		 * Generates a label string for the given value.
		 * @param value The number to create a label for.
		 */
		protected function getLabelForValue(value:Number):String
		{
			var str:String = (Math.round(value * Math.pow(10, _labelPrecision)) / Math.pow(10, _labelPrecision)).toString();
			if(_labelPrecision > 0)
			{
				var decimal:String = str.split(".")[1] || "";
				if(decimal.length == 0) str += ".";
				for(var i:int = decimal.length; i < _labelPrecision; i++)
				{
					str += "0";
				}
			}
			return str;
		}

		///////////////////////////////////
		// public methods
		///////////////////////////////////

		/**
		 * Draws the visual ui of the component.
		 */
		override public function draw():void
		{
			super.draw();
			drawBack();
			drawHandles();
		}

		///////////////////////////////////
		// event handlers
		///////////////////////////////////

		/**
		 * Internal mouseDown handler for the low value handle. Starts dragging the handle.
		 * @param event The MouseEvent passed by the system.
		 */
		protected function onDragMin(event:MouseEvent):void
		{
			stage.addEventListener(MouseEvent.MOUSE_UP, onDrop);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onMinSlide);
			if(_orientation == HORIZONTAL)
			{
				_minHandle.startDrag(false, new Rectangle(0, 0, _maxHandle.x - _height, 0));
			}
			else
			{
				_minHandle.startDrag(false, new Rectangle(0, _maxHandle.y + _width, 0, _height - _maxHandle.y - _width * 2));
			}
			if(_labelMode == MOVE)
			{
				_lowLabel.visible = true;
				_highLabel.visible = true;
			}
		}

		/**
		 * Internal mouseDown handler for the high value handle. Starts dragging the handle.
		 * @param event The MouseEvent passed by the system.
		 */
		protected function onDragMax(event:MouseEvent):void
		{
			stage.addEventListener(MouseEvent.MOUSE_UP, onDrop);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onMaxSlide);
			if(_orientation == HORIZONTAL)
			{
				_maxHandle.startDrag(false, new Rectangle(_minHandle.x + _height, 0, _width - _height - _minHandle.x - _height, 0));
			}
			else
			{
				_maxHandle.startDrag(false, new Rectangle(0, 0, 0, _minHandle.y - _width));
			}
			if(_labelMode == MOVE)
			{
				_lowLabel.visible = true;
				_highLabel.visible = true;
			}
		}

		/**
		 * Internal mouseUp handler. Stops dragging the handle.
		 * @param event The MouseEvent passed by the system.
		 */
		protected function onDrop(event:MouseEvent):void
		{
			stage.removeEventListener(MouseEvent.MOUSE_UP, onDrop);
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMinSlide);
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMaxSlide);
			stopDrag();
			if(_labelMode == MOVE)
			{
				_lowLabel.visible = false;
				_highLabel.visible = false;
			}
		}

		/**
		 * Internal mouseMove handler for when the low value handle is being moved.
		 * @param event The MouseEvent passed by the system.
		 */
		protected function onMinSlide(event:MouseEvent):void
		{
			var oldValue:Number = _lowValue;
			if(_orientation == HORIZONTAL)
			{
				_lowValue = _minHandle.x / (_width - _height * 2) * (_maximum - _minimum) + _minimum;
			}
			else
			{
				_lowValue = (_height - _width - _minHandle.y) / (height - _width * 2) * (_maximum - _minimum) + _minimum;
			}
			if(_lowValue != oldValue)
			{
				dispatchEvent(new Event(Event.CHANGE));
			}
			updateLabels();
		}

		/**
		 * Internal mouseMove handler for when the high value handle is being moved.
		 * @param event The MouseEvent passed by the system.
		 */
		protected function onMaxSlide(event:MouseEvent):void
		{
			var oldValue:Number = _highValue;
			if(_orientation == HORIZONTAL)
			{
				_highValue = (_maxHandle.x - _height) / (_width - _height * 2) * (_maximum - _minimum) + _minimum;
			}
			else
			{
				_highValue = (_height - _width * 2 - _maxHandle.y) / (_height - _width * 2) * (_maximum - _minimum) + _minimum;
			}
			if(_highValue != oldValue)
			{
				dispatchEvent(new Event(Event.CHANGE));
			}
			updateLabels();
		}

		/**
		 * Gets / sets the minimum value of the slider.
		 */
		public function set minimum(value:Number):void
		{
			_minimum = value;
			_maximum = Math.max(_maximum, _minimum);
			_lowValue = Math.max(_lowValue, _minimum);
			_highValue = Math.max(_highValue, _minimum);
			positionHandles();
		}
		public function get minimum():Number
		{
			return _minimum;
		}

		/**
		 * Gets / sets the maximum value of the slider.
		 */
		public function set maximum(value:Number):void
		{
			_maximum = value;
			_minimum = Math.min(_minimum, _maximum);
			_lowValue = Math.min(_lowValue, _maximum);
			_highValue = Math.min(_highValue, _maximum);
			positionHandles();
		}
		public function get maximum():Number
		{
			return _maximum;
		}

		/**
		 * Gets / sets the low value of this slider.
		 */
		public function set lowValue(value:Number):void
		{
			_lowValue = value;
			_lowValue = Math.min(_lowValue, _highValue);
			_lowValue = Math.max(_lowValue, _minimum);
			positionHandles();
			dispatchEvent(new Event(Event.CHANGE));
		}
		public function get lowValue():Number
		{
			return Math.round(_lowValue / _tick) * _tick;
		}

		/**
		 * Gets / sets the high value for this slider.
		 */
		public function set highValue(value:Number):void
		{
			_highValue = value;
			_highValue = Math.max(_highValue, _lowValue);
			_highValue = Math.min(_highValue, _maximum);
			positionHandles();
			dispatchEvent(new Event(Event.CHANGE));
		}
		public function get highValue():Number
		{
			return Math.round(_highValue / _tick) * _tick;
		}

		/**
		 * Sets / gets when the labels will appear. Can be "never", "move", or "always"
		 */
		public function set labelMode(value:String):void
		{
			_labelMode = value;
			_highLabel.visible = (_labelMode == ALWAYS);
			_lowLabel.visible = (_labelMode == ALWAYS);
		}
		public function get labelMode():String
		{
			return _labelMode;
		}

		/**
		 * Sets / gets where the labels will appear. "left" or "right" for vertical sliders, "top" or "bottom" for horizontal.
		 */
		public function set labelPosition(value:String):void
		{
			_labelPosition = value;
			updateLabels();
		}
		public function get labelPosition():String
		{
			return _labelPosition;
		}

		/**
		 * Sets / gets how many decimal points of precisions will be displayed on the labels.
		 */
		public function set labelPrecision(value:int):void
		{
			_labelPrecision = value;
			updateLabels();
		}
		public function get labelPrecision():int
		{
			return _labelPrecision;
		}

		/**
		 * Gets / sets the tick value of this slider. This round the value to the nearest multiple of this number.
		 */
		public function set tick(value:Number):void
		{
			_tick = value;
			updateLabels();
		}
		public function get tick():Number
		{
			return _tick;
		}

	}
}