Categories
Articles

Actionscript 3.0 Debug Console Lite

By Lon (Alonzo) Hosford

I created this debug console for use in learning and teaching Actionscript programming. This is developed in pure Actionscript without component libraries. For that reason it can be used in Flash, AIR, and Flex. It will work in Flash IDE like Flash CS4 or Flex Builder. It also works creating Flash, Flex or AIR from the Flex SDK command line.

[ad name=”Google Adsense”]

The debug console plays in the published movie. It also outputs the results to the consoles in the respective IDEs: Flex Builder, Flash CS4, etc. You can turn that feature off and make the DebugConsole invisible when you publish if you wish.

This is an ActionScript project created in Flex Builder and updated to Flex Builder 4. Download the example code. You can build this with the free Flex SDK by using the code in the src folder. Same for Flash CS3 and CS4. You need to create a Flash Document in the src folder and set the document class to DebuggerLite.

If you want to use the DebugConsole in a Flash CS4 or CS3 you do not need to set the document class to DebuggerLite. Rather in Actionscript you include this code:

import com.lonhosford.util.debug.lite.DebugConsole
var debugConsole:DebugConsole = DebugConsole.getInstance();
stage.addChild(debugConsole);
debugConsole.width = 200;
debugConsole.height = 200;
debugConsole.write("Hello World");

For your convenience you can download a Flash CS4 ready to go example.

Testing Application In Flex Builder
This is a testing Actionscript application in Flex Builder. No Flash or Flex components are used so there is not need to import libraries. The DebugConsole class is instantiated as _debugConsole on line 23. It is a singleton design pattern so only one exists for the application.

A Timer is used to generate entries to the DebugConsole. The Timer is instantiated on line 24 as _testTimer.

The _testTimeCount variable is used to determine how many generated entries to the DebugConsole. General purpose is to see when vertical scroll bar appears.

The _showWideLineAt variable on line 25 is used add a very wide line of text to trip showing the horizontal scroll bar. The _showWideLineAt variable trips this when it equal _testTimer.currentCount value.

The _testTimeDelay variable on line 26 is the millisecond value for the _testTimer. Just depends on how fast you want to see the automated updates to the DebugConsole.

/**
 *  Purpose: Test Debugger Lite
	<p>Author: Lon Hosford www.lonhosford.com 908 996 3773</p>
	<p>Date: March 12, 2010</p>
 * */
package
{
	import com.lonhosford.util.debug.lite.DebugConsole;
	
	import flash.display.Sprite;
	import flash.events.KeyboardEvent;
	import flash.events.TimerEvent;
	import flash.ui.Keyboard;
	import flash.utils.Timer;
	
	[SWF(width=500, height = 300, frameRate = 30)]
	/**
	 * Testing application for DebugConsole.
	 * @see com.lonhosford.util.debug.lite.DebugConsole  
	 * */
	public class DebuggerLite extends Sprite
	{
		private var _debugConsole:DebugConsole = DebugConsole.getInstance();
		private var _testTimeCount:Number = 15; 
		private var _showWideLineAt:Number = 2; 
		private var _testTimeDelay:Number = 250; 
		private var _testTimer:Timer; 
		public function DebuggerLite()
		{
			stage.addChild(_debugConsole);
			_debugConsole.width = stage.stageWidth;
			_debugConsole.height = stage.stageHeight;
			
			_testTimer = new Timer(_testTimeDelay,_testTimeCount); 
			_testTimer.addEventListener(TimerEvent.TIMER,testTimerEventHandler);
			_testTimer.addEventListener(TimerEvent.TIMER_COMPLETE,testTimerCompleteEventHandler);
			stage.addEventListener(KeyboardEvent.KEY_UP, stageKeyUpEventHandler);
			start();
		
		}
		/**
		 * Starts the automated testing.
		 * */
		private function start():void
		{
		_debugConsole.write("Debugger Lite Tester");
		_debugConsole.write("Hit Space Bar to Clear.");
		_debugConsole.write("Hit Ctr+ Space Bar to Repeat.");
		_debugConsole.write("\n");
		_testTimer.start();
			
		}
		/**
		 * Handles the KeyboardEvent.KEY_UP event for the stage.
		 * */
		private function stageKeyUpEventHandler(event:KeyboardEvent):void 
		{
			// Space bar
			if ( event.keyCode == Keyboard.SPACE )
			{
				// Control key
				if (event.ctrlKey)
				{
					_testTimer.stop();
					_testTimer.reset();
					_debugConsole.clear();
					start();
				}
				// No control key
				else
				{
					_debugConsole.clear();
				}
				
			}
		}
		/**
		 * Handles the TimerEvent.TIMER event.
		 * */
		private function testTimerEventHandler(event:TimerEvent):void 
		{
			_debugConsole.write(new Date().toTimeString());
			if (_testTimer.currentCount == _showWideLineAt)
			{
				_debugConsole.write("START Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. END");
				
			}
		}
		/**
		 * Handles the TimerEvent.TIMER_COMPLETE event.
		 * */
		private function testTimerCompleteEventHandler(event:TimerEvent):void 
		{
			_debugConsole.write("LAST LINE");
		}
	}
}

[ad name=”Google Adsense”]
DebugConsole Class
This is the DebugConsole class. It is a singleton and as such can be instantiated anywhere in your code to use the write() method on line 291. The DebugConsole write() method calls the Debugger class write()method. The Debugger class write()method dispatches a DebuggerEvent.WRITE which the DebugConsole listens in the consoleUpdate() on line 308. For this reason you can also instantiate the Debugger class in code and use its write() method if you prefer. You only need to instantiate the DebugConsole where you intend to add it to your display.

package com.lonhosford.util.debug.lite
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;
	
	/**
	 *  UI for debug.lite package
	 * */
	public class DebugConsole extends Sprite
	{
		private static var _instance:DebugConsole;					// Singleton instance
		private var _debugger:Debugger;								
		private var _content_tf:TextField;							// The console content
		private var _lineCount_tf:TextField;						// The line count					
		private var _width:Number = 0;								// Width
		private var _height:Number = 0;								// Height
		private var _scrollVContainer:Sprite;						// Vertical scroller container
		private var _scrollHContainer:Sprite;						// Horizontal scroller container
		private var _scrollLeftButton:DebugConsoleArrowButton;		// Scroll left button
		private var _scrollRightButton:DebugConsoleArrowButton;		// Scroll right button
		private var _scrollUpButton:DebugConsoleArrowButton;		// Scroll up button
		private var _scrollDownButton:DebugConsoleArrowButton;		// Scroll down button
		private var _horizontalScrollIncrement:int = 10;			// Character count increment for horizontal scrolling
		private var _verticalScrollIncrement:int = 1;				// Line count increment for vertical scrolling.
		private var _autoScroll:Boolean = true;						// Autoscroll to last line
		
		/**
		 *  Constructor
		 * 
		 * @param pvt Enforces a singleton pattern.
		 * @see #getInstance() 
		 * */
		public function DebugConsole(pvt:DebugConsolePrivateClass)
		{
			_content_tf = new TextField();
			_lineCount_tf = new TextField();
			
			var format:TextFormat = new TextFormat();
			format.font = "_typewriter";
			format.color = 0x000000;
			format.size = 12;
			format.indent = 2;
			_content_tf.defaultTextFormat = format;
			_content_tf.background= true;
			_content_tf.backgroundColor = 0xffffff;
			
			var format2:TextFormat = new TextFormat();
			format2.font = "_typewriter";
			format2.color = 0x000000;
			format2.size = 12;
			format2.leftMargin = 1
			format2.align = TextFormatAlign.RIGHT;
			//format2.indent = 1;
			
			_lineCount_tf.defaultTextFormat = format2;
			_lineCount_tf.background= true;
			_lineCount_tf.backgroundColor = 0xcccccc;
	
			_content_tf.addEventListener(Event.SCROLL, _console_tfScrollHandler);

			_scrollHContainer = new Sprite();
			_scrollVContainer = new Sprite();
			
			_scrollLeftButton = new DebugConsoleArrowButton();
			_scrollLeftButton.addEventListener(MouseEvent.CLICK,scrollLeftButtonMouseClick);
			_scrollRightButton = new DebugConsoleArrowButton();
			_scrollRightButton.addEventListener(MouseEvent.CLICK,scrollRightButtonMouseClick);
			
			_scrollUpButton = new DebugConsoleArrowButton();
			_scrollUpButton.addEventListener(MouseEvent.CLICK,scrollUpButtonMouseClick);
			_scrollDownButton = new DebugConsoleArrowButton();
			_scrollDownButton.addEventListener(MouseEvent.CLICK,scrollDownButtonMouseClick);
			
			addChild(_content_tf);
			addChild(_lineCount_tf);
			addChild(_scrollHContainer);
			addChild(_scrollVContainer);
			_scrollHContainer.addChild(_scrollLeftButton);
			_scrollHContainer.addChild(_scrollRightButton);
			_scrollVContainer.addChild(_scrollUpButton);
			_scrollVContainer.addChild(_scrollDownButton);
			_debugger = Debugger.getInstance();
			_debugger.addEventListener(DebuggerEvent.WRITE,consoleUpdate);
			
		}
		/**
		 * Singleton instantiation method
		 * */
		public static function getInstance():DebugConsole
		{
			if (DebugConsole._instance == null)
			{
				DebugConsole._instance = new DebugConsole(new DebugConsolePrivateClass());
			}
			return DebugConsole._instance;
		}
		/**
		 * Redraws the components
		 * */
		private function draw():void
		{
			var rightPanelHeight:Number;
			var bottomPanelWidth:Number;
			var lineCount_tf_width:Number = _lineCount_tf.textWidth + 12;// Extra for TextField overhead
			var bottomPanelHeight:Number = 20;
			var rightPanelWidth:Number = 20;
				
			var tfHeight:Number;// = _height;
			var tfWidth:Number = _width;
			// Component border
			graphics.clear();
			graphics.beginFill(0xffffff);
			graphics.lineStyle(2, 0x000000);
			graphics.drawRect(0, 0, _width, _height);
			graphics.endFill();
			_scrollLeftButton.draw(
				bottomPanelHeight,
				bottomPanelHeight,
				0x00ffff,
				1,
				0x000000,
				0x666666,
				90
			);
			_scrollRightButton.draw(
				bottomPanelHeight,
				bottomPanelHeight,
				0x00ffff,
				1,
				0x000000,
				0x666666,
				-90
			);
			
			_scrollUpButton.draw(
				rightPanelWidth,
				rightPanelWidth,
				0x00ffff,
				1,
				0x000000,
				0x666666,
				0
			);
			_scrollDownButton.draw(
				rightPanelWidth,
				rightPanelWidth,
				0x00ffff,
				1,
				0x000000,
				0x666666,
				180
			);
			tfHeight = height
			rightPanelHeight = height-3;
			bottomPanelWidth = width - 3 - lineCount_tf_width;
			if (_content_tf.textHeight > _content_tf.height)
			{
				bottomPanelWidth -= rightPanelWidth - 1;
			}
			if (_content_tf.textWidth > _content_tf.width)
			{
				rightPanelHeight -= bottomPanelHeight - 1;
			}
			// Right scrollbar panel
			if (_content_tf.textHeight > _content_tf.height)
			{
				_scrollUpButton.x = 0;
				_scrollUpButton.y = 0;
				_scrollDownButton.x = 0;
				_scrollDownButton.y = 0;
				_scrollVContainer.graphics.clear();
				
				_scrollVContainer.graphics.beginFill(0xcccccc);
				_scrollVContainer.graphics.lineStyle(1, 0x000000);
				_scrollVContainer.graphics.drawRect(0, 0, rightPanelWidth - 1, rightPanelHeight);
				_scrollVContainer.graphics.endFill();
				_scrollVContainer.x = _width - _scrollVContainer.width + .5;
				_scrollVContainer.y = .5;

				
				_scrollDownButton.x = (_scrollVContainer.width - _scrollDownButton.width) ;
				_scrollDownButton.y = (_scrollVContainer.height - _scrollDownButton.height) ;
				_scrollUpButton.x = _scrollDownButton.x;
				_scrollUpButton.y = 0;
				
				tfWidth -= _scrollVContainer.width - 1;
				
				_scrollVContainer.visible = true;
			}
			else
			{
				_scrollVContainer.visible = false;
			}
			// Bottom scrollbar panel
			if (_content_tf.textWidth > _content_tf.width)
			{
				_scrollLeftButton.x = 0;
				_scrollLeftButton.y = 0;
				_scrollRightButton.x = 0;
				_scrollRightButton.y = 0;
				_scrollHContainer.graphics.clear();
				_scrollHContainer.graphics.beginFill(0xcccccc);
				_scrollHContainer.graphics.lineStyle(1, 0x000000);
				_scrollHContainer.graphics.drawRect(0, 0, bottomPanelWidth, bottomPanelHeight - 1);
				_scrollHContainer.graphics.endFill();
				_scrollHContainer.y = _height - _scrollHContainer.height + .5;
				_scrollHContainer.x = lineCount_tf_width;
				_scrollLeftButton.x = (_scrollHContainer.width - _scrollLeftButton.width) ;
				_scrollLeftButton.y = (_scrollHContainer.height - _scrollLeftButton.height) ;
				_scrollRightButton.x = 0;
				_scrollRightButton.y = _scrollLeftButton.y;

				_scrollHContainer.visible = true;
				tfHeight -= _scrollHContainer.height -1;
			}
			else
			{
				_scrollHContainer.visible = false;
			}
			
			// Left bottom rectangle if horizontal and vertical scroll bars are visible.
			if (_scrollHContainer.visible && _scrollVContainer.visible)
			{
				graphics.beginFill(0xcccccc);
				graphics.lineStyle(0, 0x000000,0);
				graphics.drawRect(_scrollHContainer.x + _scrollHContainer.width, _scrollVContainer.height, bottomPanelHeight-2, bottomPanelHeight-2);
				graphics.endFill();
			}
			// Left bottom rectangle if horizontal scroll bar is visible.
			if (_scrollHContainer.visible)
			{
				graphics.beginFill(0xcccccc);
				graphics.lineStyle(1, 0x000000,100);
				graphics.drawRect( 0, _scrollHContainer.y, lineCount_tf_width, bottomPanelHeight-1);
				graphics.endFill();
			}
			
			// Position and resize line count text field.
			_lineCount_tf.width = lineCount_tf_width;	
			_lineCount_tf.height = tfHeight - 4;			
			_lineCount_tf.x = 1;
			_lineCount_tf.y = 1;
			
			_lineCount_tf.scrollV = _content_tf.scrollV;
			
			// Position and resize line content text field.
			_content_tf.width = tfWidth - 2 - lineCount_tf_width;
			_content_tf.height = _lineCount_tf.height;
			_content_tf.x = _lineCount_tf.x + _lineCount_tf.width ;
			_content_tf.y = _lineCount_tf.y;
			
			_scrollUpButton.enabled =  _content_tf.scrollV != 1;
			_scrollDownButton.enabled =  _content_tf.scrollV != _content_tf.maxScrollV;
			_scrollLeftButton.enabled =  _content_tf.scrollH != _content_tf.maxScrollH;
			_scrollRightButton.enabled =  _content_tf.scrollH != 0;
		}
		/**
		 * Change width
		 * */
		override public function set width(width:Number):void
		{
			_width = width;
			draw();
		}
		/**
		 * Change height
		 * */
		override public function set height(height:Number):void
		{
			_height = height;
			draw();
			
		}
		/**
		 * Scroll to last line. 
		 * @default true  
		 * */
		public function set autoScroll(autoScrollEnabled:Boolean):void
		{
			_autoScroll = autoScrollEnabled;
		}
		/**
		 * Adds one line. Multiple lines can be added inserting \n. A blank line can be added with \n.
		 * <p>The writing is delegated to the Debugger class.</p>
		 * @see com.lonhosford.util.debug.lite.Debugger.write()
		 * */
		public function write(msg:String):void 
		{
			_debugger.write(msg);
		}
		/**
		 * Clears the display. Line count is not reset to 0 and continues to increment.
		 * */
		public function clear():void 
		{
			_lineCount_tf.text = "";
			_content_tf.text = "";
			draw();
		}
		/**
		 * Handles the DebuggerEvent.WRITE event.
		 * */
		private function consoleUpdate(e:DebuggerEvent):void
		{
			var debugMessage:DebugMessage = e.debugMessage;
			
			_lineCount_tf.appendText(debugMessage.lineNumber + "." + "\n");
			if (debugMessage.text == "\n")
			{
				debugMessage.text = "";
			}
			_content_tf.appendText( debugMessage.text + "\n");
			if(_autoScroll)
			{
				_content_tf.scrollV = _content_tf.maxScrollV;
			}			
			draw();
		}
		/**
		 * Handler for the scrollUpButton MouseEvent.CLICK event.
		 * */

		private function scrollUpButtonMouseClick(e:MouseEvent):void
		{
			if (_content_tf.scrollV <= _verticalScrollIncrement)
			{
				_content_tf.scrollV = 1;
			}
			else
			{
				_content_tf.scrollV -= _verticalScrollIncrement;
			}
			draw();
		}
		/**
		 * Handler for the scrollRightButton MouseEvent.CLICK event.
		 * */
		private function scrollRightButtonMouseClick(e:MouseEvent):void
		{
			if (_content_tf.scrollH <= _horizontalScrollIncrement)
			{
				_content_tf.scrollH = 0;
			}
			else
			{
				_content_tf.scrollH -= _horizontalScrollIncrement;
			}
			draw();
		}
		/**
		 * Handler for the scrollDownButton MouseEvent.CLICK event.
		 * */
		private function scrollDownButtonMouseClick(e:MouseEvent):void
		{
			
			if (_content_tf.scrollV + _verticalScrollIncrement >= _content_tf.maxScrollV)
			{
				_content_tf.scrollV = _content_tf.maxScrollV;
				
			}
			else
			{
				_content_tf.scrollV += _verticalScrollIncrement;
			}
			draw();
		}
		/**
		 * Handler for the scrollLeftButton MouseEvent.CLICK event.
		 * */
		private function scrollLeftButtonMouseClick(e:MouseEvent):void
		{
			
			if (_content_tf.scrollH + _horizontalScrollIncrement >= _content_tf.maxScrollH)
			{
				_content_tf.scrollH =_content_tf.maxScrollH;
				
			}
			else
			{
				_content_tf.scrollH += _horizontalScrollIncrement;
			}
			draw();
		}
		/**
		 * Handler for the _content_tf Event.SCROLL event.
		 * */
		public function _console_tfScrollHandler(event:Event):void
		{
			draw();
		}
	}
}
/**
 * Singleton enforcer class
 * */
class DebugConsolePrivateClass
{
	public function DebugConsolePrivateClass()
	{
		
	}
}

Debugger Class
This class receives write messages and dispatches them. It also will write to the IDE debug console on line 60.

package com.lonhosford.util.debug.lite
{
	import flash.events.EventDispatcher;
	/**
	 * Singleton for receiving and dispatching debugging messages
	 * */
	public class Debugger extends EventDispatcher
	{
		private static var _instance:Debugger;
		private var _msg:String;
		private var _isTracing:Boolean = true;		// State of using the trace() function.
		private var _lineCount:Number = 0;			// Line count of tracing messages
		private var _lang_productName:String = "Actionscript 3 Debugger Lite";
		private var _lang_productVersion:String = "Version";
		/**
		 *  Constructor
		 * 
		 * @param pvt Enforces a singleton pattern.
		 * @see #getInstance() 
		 * */
		public function Debugger(pvt:DebuggerPrivateClass)
		{
		}
		/**
		 * Singleton instantiation method
		 * */
		public static function getInstance():Debugger
		{
			if (Debugger._instance == null)
			{
				Debugger._instance = new Debugger(new DebuggerPrivateClass());
			}
			return Debugger._instance;
		}
		/**
		 * Turns on or off tracing to the Flash or Flex IDE console.
		 * @default true
		 * */
		public function set isTracing(value:Boolean):void
		{
			_isTracing = value;
		}
		/**
		 * Adds one line. Multiple lines can be added inserting \n. A blank line can be added with \n.		 * <p>The writing is delegated to the Debugger class.</p>
		 * */
		public function write(msg:String):void 
		{
			var messageLines:Array = new Array();
			if (msg == "\n") 
			{
				messageLines.push("");
			}
			else
			{
				messageLines = msg.split("\n")
			}
			
			
			if (_isTracing)
			{
				trace(msg);
			}
			if ( _lineCount == 0 )
			{
				messageLines.splice(0,0,_lang_productName + "\t" + _lang_productVersion + " " + DebugVersion.VERSION);
				messageLines.splice(1,0, DebugVersion.AUTHOR + "\t" + DebugVersion.AUTHOR_WEB_SITE);
				messageLines.splice(2,0,"\n");
			}
			for (var msgLinesIndex:uint = 0; msgLinesIndex <= messageLines.length - 1; msgLinesIndex++)
			{
				dispatchMessageEvent(messageLines[msgLinesIndex]);
			}
		}
		/**
		 * Dispatches a DebuggerEvent.WRITE
		 * @see DebuggerEvent
		 * @see DebugMessage
		 * */
		private function dispatchMessageEvent(msg:String):void
		{
			var debugMessage:DebugMessage = new DebugMessage();
			debugMessage.text = msg;
			debugMessage.lineNumber = ++_lineCount;
			var e:DebuggerEvent = new DebuggerEvent(DebuggerEvent.WRITE,  debugMessage);
			dispatchEvent(e);
		}
	}
}
/**
 * Singleton enforcer class
 * */
class DebuggerPrivateClass
{
	public function DebuggerPrivateClass()
	{
		
	}
}

[ad name=”Google Adsense”]
DebugConsoleArrowButton Class
UI for the scroll buttons. Simple shapes using a triangle to indicate direction of scroll.

package com.lonhosford.util.debug.lite
{
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	/**
	 * Arrow button UI and logic
	 * */
	public class DebugConsoleArrowButton extends Sprite
	{
		private var _container:Sprite = new Sprite();
		private var _triangle:DebugTriangleShape = new DebugTriangleShape();
		private var _backgroundRect:Sprite = new Sprite();
		private var _width:Number;
		private var _height:Number;
		private var _color:int;										// Color of arrow.
		private var _borderWidth:Number;							// Border width of button.
		private var _borderColor:int;								// Border color of button.
		private var _backgroundColor:int;							// Background color of button.
		private var _direction:Number;								// Rotation of the UI.
		private var _mouseDownStartTimeDelay:Number = 350; 			// Initial delay before starting repeating MouseEvent.CLICK events.
		private var _mouseDownTimeDelay:Number = 100; 				// Delay between each MouseEvent.CLICK event.
		private var _mouseDownTimer:Timer; 							// Timer for repeating MouseEvent.CLICK events.
		/**
		 * Constructor
		 * */
		public function DebugConsoleArrowButton()
		{
			_mouseDownTimer = new Timer(_mouseDownTimeDelay,0); 
			_mouseDownTimer.addEventListener(TimerEvent.TIMER,mouseDownTimerEventHandler);
			_container.addChild(_backgroundRect);			
			_backgroundRect.addChild(_triangle);
			addChild(_container);
		}
		/**
		 * Handler for TimerEvent.TIMER event. Resets the delay interval once the default delay 
		 * is reached.
		 * */
		private function mouseDownTimerEventHandler(event:TimerEvent):void 
		{
			if (_mouseDownTimer.delay == _mouseDownStartTimeDelay)
			{
				_mouseDownTimer.delay = _mouseDownTimeDelay;
			}
			
			var e:MouseEvent = new MouseEvent(MouseEvent.CLICK);
			dispatchEvent(e);
		}
		/**
		 * Sets enabled state.
		 * */
		internal function set enabled(enabledState:Boolean):void
		{
			alpha = enabledState ? 1 : .25;
			if (enabledState)
			{
				addEventListener(MouseEvent.MOUSE_UP,mouseUpEventHandler);
				addEventListener(MouseEvent.MOUSE_DOWN,mouseDownEventHandler);
				addEventListener(MouseEvent.MOUSE_OUT,mouseOutEventHandler);
			}		
		}
		/**
		 * Handler for MouseEvent.MOUSE_OUT event. Stops the mouse down repeat timer.
		 * */
		private function mouseOutEventHandler(e:MouseEvent):void
		{
			_mouseDownTimer.stop();		
		}
		/**
		 * Handler for MouseEvent.MOUSE_UP event. Stops the mouse down repeat timer.
		 * */
		private function mouseUpEventHandler(e:MouseEvent):void
		{
			_mouseDownTimer.stop();		
		}
		/**
		 * Handler for MouseEvent.MOUSE_DOWN event. Starts mouse down timer.
		 * */
		private function mouseDownEventHandler(e:MouseEvent):void
		{
			_mouseDownTimer.delay = _mouseDownStartTimeDelay;
			_mouseDownTimer.start();
		}
		/**
		 * Draw the button UI.
		 * */
		internal function draw(
			p_width:Number, 
			p_height:Number, 
			color:int,
			borderWidth:Number,
			borderColor:int,
			backgroundColor:int,
			direction:Number = 0):void
		{
			_width = p_width;
			_height = p_height;
			_color = color;
			_borderWidth = borderWidth;
			_borderColor = borderColor;
			_backgroundColor = backgroundColor;
			_direction = direction;
		
			_backgroundRect.graphics.clear();
			_backgroundRect.graphics.beginFill(_backgroundColor);
			_backgroundRect.graphics.lineStyle(_borderWidth, _borderColor); 
			_backgroundRect.graphics.drawRect(0, 0, _width - _borderWidth, _height - _borderWidth); 
			_backgroundRect.graphics.endFill();
			
			_triangle.draw( _width  , 0,_color, _color);
			_triangle.scaleX = _triangle.scaleY = .6;
			_triangle.x =  (_triangle.width / 2) + ((_width - _triangle.width - _borderWidth) / 2) ;
			_triangle.y =  (_triangle.height / 2) + ((_height - _triangle.height - _borderWidth) / 2);
			_triangle.rotation = _direction;
		}
	}
}

DebugTriangleShape Class
Utility to draw a rectangle shape with a center registration point.

package com.lonhosford.util.debug.lite
{
	import flash.display.Shape;
	import flash.display.Sprite;
	/**
	 * Utility to draw a triangle shape with a center registration point.
	 * */	
	public class DebugTriangleShape extends Sprite
	{
		
		public function DebugTriangleShape(
		)
		{
		}
		internal function draw(
			size:Number, 
			borderWidth:Number,
			borderColor:int,
			backgroundColor:int
				):void
		{
			graphics.clear();
			graphics.beginFill(backgroundColor);
			graphics.lineStyle(borderWidth, borderColor);
			size = size / 2;
			graphics.moveTo(-size, size);
			graphics.lineTo(-0, -size);  
			graphics.lineTo(size, size );
			
			graphics.endFill();
			
		}
	}
}

DebuggerEvent Class
Events for the Debugger class.

package com.lonhosford.util.debug.lite
{import flash.events.Event;
	/**
	 * Events for the Debugger
	 * @see DebugMessage
	 * @see Debugger
	 * */
	public class DebuggerEvent extends Event
	{
		public static const WRITE:String = "debug.DebuggerEvent.Write";
		public var debugMessage:DebugMessage;
		public function DebuggerEvent(type:String, debugMessage:DebugMessage)
		{
			super(type, bubbles);
			this.debugMessage = debugMessage
		}
		override public function clone():Event 
		{
			return new DebuggerEvent(type, debugMessage);
		}
	}
}

DebugMessage Class
The data values sent with the DebuggerEvent.

package com.lonhosford.util.debug.lite
{
	/**
	 * Data for a DebuggerEvent.
	 * @see DebuggerEvent
	 * */
	public class DebugMessage
	{
		public var text:String;
		public var lineNumber:Number;
		public function DebugMessage()
		{
		}
	}
}

DebugVersion Class
A place to hold the static values for the code.

package com.lonhosford.util.debug.lite
{
	/**
	 * Common version data.
	 * */	
	public final class DebugVersion 
	{
		public static const VERSION:String = "1.00.01";
		public static const AUTHOR:String = "Lon (Alonzo) Hosford";
		public static const AUTHOR_WEB_SITE:String = "https://www.lonhosford.com";
	}
}