Fun with OOP!

Finally caved in and bought Essential ActionScript 2.0. For years now i've been wanting to learn more on object oriented coding. Actionscript 2.0 was a strange beast to me, in which i happily coded oldstyle. No more! Here is the code for the class, which you need to save in a seperate ColorPicker.as file. I simply saved it next to the .fla file, so no need to import it. If you use the ColorPicker class, Flash simply incorporates it. In the .fla file i put in a textfield and a movieclip, added them to the ColorPickerBroadcaster and wrote an onChangeColor function. The code in the .fla file is:

import flash.geom.Transform;
import flash.geom.ColorTransform;

//ColorPicker(target:String, depth:Number, xPos:Number, yPos:Number, rows:Number, w:Number, h:Number)
var picker:ColorPicker = new ColorPicker("picker",100,40,40,36,10,10);

ColorPicker.ColorPickerBroadcaster.addListener(_root.t);
ColorPicker.ColorPickerBroadcaster.addListener(_root.mc);

_root.t.onColorChange = function(colorValue:Number){
	this.text = colorValue;
}

_root.mc.onColorChange = function(colorValue:Number){
	var colorTrans:ColorTransform = new ColorTransform(this);
	colorTrans.rgb = colorValue;
	var trans:Transform = new Transform(this);
	trans.colorTransform = colorTrans;
}
		

The flash.geom.Transform and flash.geom.ColorTransform i used for the first time. I copied and pasted code from the help files, still another area i need to get to grips with.

In the class i was having most trouble with the broadcasting. It seemed to me a sensible and adaptable way of using the colorValues, but the different methods of declaring variables in a class were a bit fuzzy. In the end i had to declare the ColorPickerBroadcaster as a public static var. Static means you can access the variable (or maybe better: method or property) through the class itself. Very similar to the Math class.

Finally i added some rollover effects. I did try to get a 'selected' effect as well, but that was a bit more tricky, and, being a little tired, i decided to leave it out. I'm sure there are better ways of doing this, and maybe i should have made the class more modular, but for now i'm quite happy with it.

class ColorPicker {
	//the hexArray gives the building blocks to fill the websafeColors Array
	//you could actually just type the array, but that is a very boring job
	private var hexArray:Array = new Array("00","33","66","99","CC","FF");
	private var prefix:String = "0x";
	//the rr, gg and bb vars are counters, i named them to make clear what they're supposed to do
	private var rr:Number = 0;
	private var gg:Number = 0;
	private var bb:Number = 0;
	private var row:Number = 0;
	//ws is a counter for going through the websafecolor array
	//because i use a double nested loop, there isn't a single counter going from 0 - 215
	//its ws's job to do that, it also provides the depth for the button
	private var ws:Number = 0;
	
	//initialize the websafeColors array
	private var websafeColors:Array = new Array();
	
	//not sure why i made this static, i do think i copied it out of the book
	private static var inited:Boolean = false;
	
	//the ColorPickerBroadcaster is a static object which you can reference through the class itself
	//ColorPicker.ColorPickerBroadcaster.addListener(mc);
	//the buttons, when clicked, make the object broadcast an 'onColorChange' event with the color as parameter
	//this should make implementation quite easy
	public static var ColorPickerBroadcaster:Object = new Object();
	
	//contructor function
	//target = name movieclip to hold the colorpicker
	//depth in which you want the colorpicker to be placed
	//xPos and yPos: _x and _y position
	//rows: number of rows: defaults to 36, which gives 6 columns
	//best options are multiples of 6
	//w and h are the width of the buttons, defaults to 10
	public function ColorPicker(target:String, depth:Number, xPos:Number, yPos:Number, rows:Number, w:Number, h:Number){
		if(!inited){
			buildWebsafeColors();
		}
		
		AsBroadcaster.initialize(ColorPickerBroadcaster);

		if(rows == undefined){
			rows = 36;
			var columns = 6;
		} else {
			var columns:Number = websafeColors.length / rows;
		}
		
		if(w == undefined){
			w = 10;
		}
		
		if(h == undefined){
			h = 10;
		}
		
		_root.createEmptyMovieClip(target,depth);
		
		var mc:MovieClip = _root[target];
		mc._x = xPos;
		mc._y = yPos;
		

		for(var row:Number = 0; row < rows; row++){
			for(var column:Number = 0; column < columns; column++){
				drawButton(mc, ws, websafeColors[ws], column * w, row * h, w, h);
				ws++;
			}
		}

	}
	
	//build array of websafe color values
	//this has to be done before buttons are build, so there is a little built in check
	//at the end of the function 'inited' is set to true
	private function buildWebsafeColors():Void{
		for(rr = 0; rr < 6; rr++){
			var tmpColor = "0x";
			var tmpColor1 = tmpColor + hexArray[rr];
			for(gg = 0; gg < 6; gg++){
				var tmpColor2 = tmpColor1 + hexArray[gg];
				for(bb = 0; bb < 6; bb++){
					var tmpColor3 = tmpColor2 + hexArray[bb];
					websafeColors.push(tmpColor3);
				}
			}
		}
		inited = true;
	}
	
	private function drawButton(target:Object, depth:Number, btnColor:Number, xPos:Number, yPos:Number, w:Number, h:Number):Void{
		//at first i had the target typed as a movieclip
		//i retyped it as an Object, because i wanted to add a custom property: colorValue
		//the onrelease action can than look up the property and pass it on to the broadcaster
		
		target.createEmptyMovieClip("btn" + depth, depth);
	
		var btn:MovieClip = target["btn" + depth];
		
		//i don't like to see the handcursor when i go over the buttons
		//there is a rollover state which provides feedback
		//most applications dont show a handcursor when you select a colour
		btn.useHandCursor = false;
		
		btn._x = xPos;
		btn._y = yPos;
		
		btn.beginFill(btnColor);
		btn.lineTo(w,0);
		btn.lineTo(w,h);
		btn.lineTo(0,h);
		btn.lineTo(0,0);
		btn.endFill();
		
		btn.colorValue = btnColor;
		
		//the onrelease event makes the broadcaster send out the colorvalue
		btn.onRelease = function(){
			ColorPicker.ColorPickerBroadcaster.broadcastMessage("onColorChange", this.colorValue);
		}
		
		//simple rollover effect
		//maybe add a onColorRollOver broadcastmessage, so the textfield shows the colorvalue on rollover
		//the rolover effect is done in a temporary movieclip, so it can be easily removed in the onRollOut event
		//first i thought i could use clear, but that would wipe out the entire movieclip!
		btn.onRollOver = function(){
			this.createEmptyMovieClip("tmp",1);
			this.tmp.lineStyle(0,0xFFFFFF);
			this.tmp.lineTo(this._width - 1,0);
			this.tmp.lineTo(this._width - 1,this._height - 1);
			this.tmp.lineTo(0,this._height - 1);
			this.tmp.lineTo(0,0);
		}
		
		btn.onRollOut = function(){
			this.tmp.removeMovieClip();
		}
	}
}