Saturday, September 8, 2012

Creating Advanced Alert Window class: Part 6

In this tutorial we'll improve our skinning system by adding a class called SolidColorRect.

We will need to support multiple kinds of rectangle skinning - filling it with solid color, gradient color or a picture - each requires different code to do that so I decided to create separate classes for each type of rectangle skins.

This first one is SolidColorRect - we'll add it today.

But before we start, we actually have to make some changes to our project layout - add another folder inside kircode called AdvAlert. In all "import" lines and in the beginning of each class you need to update the package name to work with the new locations - package com.kircode.AdvAlert.



Create a new class called SolidColorRect.as. It will have the following variables:

public var _backgroundColor:uint;
public var _radius:Array;
public var _lineThickness:Number;
public var _lineColor:uint;
public var _alpha:Number;
public var _lineAlpha:Number;

Set up the constructor so that the user can pass values, but if he dosen't - default values are set.

package com.kircode.AdvAlert 
{
/**
 * ...
 * @author Kirill Poletaev
 */
public class SolidColorRect
{
public var _backgroundColor:uint;
public var _radius:Array;
public var _lineThickness:Number;
public var _lineColor:uint;
public var _alpha:Number;
public var _lineAlpha:Number;

/**
 * Rectangle with solid color fill.
 * @parambackgroundColor Background color fill of the box.
 * @paramcornerRadius Radius of the corners of the box - top left, top right, bottom left, bottom right.
 * @paramlineThickness Thickness of the stroke.
 * @paramlineColor Color of the stroke.
 * @paramalpha Alpha channel of the background fill.
 * @paramlineAlpha Alpha channel of the stroke.
 */

public function SolidColorRect(backgroundColor:uint = 0xE2E2E2, cornerRadius:Array = null, lineThickness:Number = 1, lineColor:uint = 0x333333, alpha:Number = 1, lineAlpha:Number = 1) 
{
if (cornerRadius == null) cornerRadius = [10, 10, 0, 0];
_backgroundColor = backgroundColor;
_radius = cornerRadius;
_lineThickness = lineThickness;
_lineColor = lineColor;
_alpha = alpha
_lineAlpha = lineAlpha;
}

}

}

Now go to AdvAlertSkin.as. Instead of headerColor and bgColor variables, use headerRect and bgRect:

public var headerRect:*;
public var bgRect:*;

Note how I don't set a class, because it is not limited to just SolidColorRect, but will also support future classes.

In the constructor we set up default values:

public function AdvAlertSkin() 
{
// default values
textPadding = new TextPadding(5, 5, 5, 5);
headerPadding = new TextPadding(5, 5, 5, 5);
titlePadding = new TextPadding(2, 2, 2, 2);
headerHeight = 30;
titleFormat = new TextFormat();
titleFormat.size = 20;
titleFormat.font = "Arial";
titleFormat.bold = true;
titleFormat.color = 0xffffff;
textFormat = new TextFormat();
textFormat.size = 16;
textFormat.font = "Arial";
textFormat.color = 0xffffff;
selectable = false;
bgRect = new SolidColorRect(0x7777cc, [10, 10, 10, 10], 2, 0x4444aa, 1, 1);
headerRect = new SolidColorRect(0x9999ff, [10, 10, 0, 0], 0, 0x000000, 1, 0);
}

Full class:

package com.kircode.AdvAlert 
{
import flash.text.TextFormat;
/**
 * Object containing skinning data for AdvAlertWindow.
 * @author Kirill Poletaev
 */
public class AdvAlertSkin 
{

public var textPadding:TextPadding;
public var headerPadding:TextPadding;
public var titlePadding:TextPadding;
public var headerHeight:int;
public var titleFormat:TextFormat;
public var textFormat:TextFormat;
public var selectable:Boolean;
public var headerRect:*;
public var bgRect:*;

public function AdvAlertSkin() 
{
// default values
textPadding = new TextPadding(5, 5, 5, 5);
headerPadding = new TextPadding(5, 5, 5, 5);
titlePadding = new TextPadding(2, 2, 2, 2);
headerHeight = 30;
titleFormat = new TextFormat();
titleFormat.size = 20;
titleFormat.font = "Arial";
titleFormat.bold = true;
titleFormat.color = 0xffffff;
textFormat = new TextFormat();
textFormat.size = 16;
textFormat.font = "Arial";
textFormat.color = 0xffffff;
selectable = false;
bgRect = new SolidColorRect(0x7777cc, [10, 10, 10, 10], 2, 0x4444aa, 1, 1);
headerRect = new SolidColorRect(0x9999ff, [10, 10, 0, 0], 0, 0x000000, 1, 0);
}

}

}

Now go to AdvAlertWindow.as. Here we can get rid of headerColor and bgColor values and change them to headerRect and bgRect too:

private var headerRect:*;
private var bgRect:*;

Apply the values in setSkin():

public function setSkin(skin:AdvAlertSkin):void {
textPadding = skin.textPadding;
headerPadding = skin.headerPadding;
titlePadding = skin.titlePadding;
headerHeight = skin.headerHeight;
titleFormat = skin.titleFormat;
textFormat = skin.textFormat;
selectable = skin.selectable;
bgRect = skin.bgRect;
headerRect = skin.headerRect;
}

Now in updateDraw() we need to add if..statements that check if the user has supplied us with SolidColorRect before drawing background or header. If true, draw the elements using the provided data:

public function updateDraw():void {
// bg
this.graphics.clear();
if (bgRect is SolidColorRect) {
this.graphics.beginFill(bgRect._backgroundColor, bgRect._alpha);
this.graphics.lineStyle(bgRect._lineThickness, bgRect._lineColor, bgRect._lineAlpha);
this.graphics.drawRoundRectComplex(pos.x, pos.y, w, h,
bgRect._radius[0], bgRect._radius[1], bgRect._radius[2], bgRect._radius[3]);
this.graphics.endFill();
}
// header
if (headerRect is SolidColorRect) {
this.graphics.beginFill(headerRect._backgroundColor, headerRect._alpha);
this.graphics.lineStyle(headerRect._lineThickness, headerRect._lineColor, headerRect._lineAlpha);
this.graphics.drawRoundRectComplex(pos.x + headerPadding.left, pos.y + headerPadding.top, w - (headerPadding.left + headerPadding.right), headerHeight,
headerRect._radius[0], headerRect._radius[1], headerRect._radius[2], headerRect._radius[3]);
this.graphics.endFill();
}
// title
titleField.width = w - (headerPadding.left + headerPadding.right);
titleField.text = tt;
titleField.height = headerHeight;
titleField.x = pos.x + headerPadding.left + titlePadding.left;
titleField.y = pos.y + headerPadding.top + titlePadding.top;
// text
textField.width = w - (textPadding.right + textPadding.left);
textField.height = h - (textPadding.top + textPadding.bottom + headerPadding.top + headerPadding.bottom + headerHeight);
textField.text = t;
textField.x = pos.x + textPadding.right;
textField.y = pos.y + textPadding.top + headerHeight + headerPadding.bottom + headerPadding.top;
// formats
textField.setTextFormat(textFormat);
titleField.setTextFormat(titleFormat);
textField.selectable = selectable;
titleField.selectable = selectable;
textField.multiline = true;
textField.wordWrap = true;
}

You can see that In the end I also added lines that set textField's multiline value to true and wordWrap to true.

Full class code:

package com.kircode.AdvAlert 
{
import flash.display.MovieClip;
import flash.geom.Point;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.display.GradientType;

/**
 * Advanced Alert window object.
 * @author Kirill Poletaev
 */
public class AdvAlertWindow extends MovieClip
{
private var t:String;
private var tt:String;
private var w:int;
private var h:int;
private var pos:Point;

private var textField:TextField;
private var titleField:TextField;

private var textPadding:TextPadding;
private var headerPadding:TextPadding;
private var titlePadding:TextPadding;
private var headerHeight:int;
private var titleFormat:TextFormat;
private var textFormat:TextFormat;
private var selectable:Boolean;
private var headerRect:*;
private var bgRect:*;

public function AdvAlertWindow(pt:String, ptt:String, pw:int, ph:int, ppos:Point, sk:AdvAlertSkin) 
{
t = pt;
tt = ptt;
w = pw;
h = ph;
pos = ppos;

setSkin(sk);

textField = new TextField();
addChild(textField);

titleField = new TextField();
addChild(titleField);

updateDraw();
}

public function setSkin(skin:AdvAlertSkin):void {
textPadding = skin.textPadding;
headerPadding = skin.headerPadding;
titlePadding = skin.titlePadding;
headerHeight = skin.headerHeight;
titleFormat = skin.titleFormat;
textFormat = skin.textFormat;
selectable = skin.selectable;
bgRect = skin.bgRect;
headerRect = skin.headerRect;
}

public function updateDraw():void {
// bg
this.graphics.clear();
if (bgRect is SolidColorRect) {
this.graphics.beginFill(bgRect._backgroundColor, bgRect._alpha);
this.graphics.lineStyle(bgRect._lineThickness, bgRect._lineColor, bgRect._lineAlpha);
this.graphics.drawRoundRectComplex(pos.x, pos.y, w, h,
bgRect._radius[0], bgRect._radius[1], bgRect._radius[2], bgRect._radius[3]);
this.graphics.endFill();
}
// header
if (headerRect is SolidColorRect) {
this.graphics.beginFill(headerRect._backgroundColor, headerRect._alpha);
this.graphics.lineStyle(headerRect._lineThickness, headerRect._lineColor, headerRect._lineAlpha);
this.graphics.drawRoundRectComplex(pos.x + headerPadding.left, pos.y + headerPadding.top, w - (headerPadding.left + headerPadding.right), headerHeight,
headerRect._radius[0], headerRect._radius[1], headerRect._radius[2], headerRect._radius[3]);
this.graphics.endFill();
}
// title
titleField.width = w - (headerPadding.left + headerPadding.right);
titleField.text = tt;
titleField.height = headerHeight;
titleField.x = pos.x + headerPadding.left + titlePadding.left;
titleField.y = pos.y + headerPadding.top + titlePadding.top;
// text
textField.width = w - (textPadding.right + textPadding.left);
textField.height = h - (textPadding.top + textPadding.bottom + headerPadding.top + headerPadding.bottom + headerHeight);
textField.text = t;
textField.x = pos.x + textPadding.right;
textField.y = pos.y + textPadding.top + headerHeight + headerPadding.bottom + headerPadding.top;
// formats
textField.setTextFormat(textFormat);
titleField.setTextFormat(titleFormat);
textField.selectable = selectable;
titleField.selectable = selectable;
textField.multiline = true;
textField.wordWrap = true;
}


}

}

Now you can go to main.as and alert() a window with default settings and it works and looks nice.

package  
{
import com.kircode.AdvAlert.AdvAlertManager;
import com.kircode.AdvAlert.AdvAlertSkin;
import flash.display.MovieClip;
import flash.events.Event;
import flash.geom.Point;
/**
 * ...
 * @author Kirill Poletaev
 */
public class main extends MovieClip
{
private var AlertManager:AdvAlertManager;

public function main() 
{
addEventListener(Event.ADDED_TO_STAGE, init);
}

private function init(evt:Event):void {
AlertManager = new AdvAlertManager(this, stage.stageWidth, stage.stageHeight);
AlertManager.alert("This is a default alert window with default settings and theme!", "Default alert window");
}

}

}

Thanks for reading!

No comments:

Post a Comment