Monday, September 17, 2012

Creating Advanced Alert Window class: Part 15

In this tutorial we will start working on the ability to add buttons to the alert window.

Start by going to the AdvAlertManager.as and adding another optional parameter to the alert() window - a buttons Array. Set its default value to null, in the function check if the value is null, and if so - set it to an empty array. Pass the buttons array as the final parameter to AdvAlertWindow constructor:

public function alert(text:String, title:String = "", buttons:Array = null, width:int = 300, height:int = 200, position:Point = null):void {
if (position == null) position = new Point((pWidth / 2) - (width / 2), (pHeight / 2) - (height / 2));
if (buttons == null) buttons = [];
var w:AdvAlertWindow = new AdvAlertWindow(text, title, width, height, position, skin, buttons);
var b:AdvAlertBlur = new AdvAlertBlur(pWidth, pHeight, skin);
windows.push( { window:w, blur:b } );
defaultContainer.addChild(b);
defaultContainer.addChild(w);

trace("Message: " + text);
}

Full class code:

package com.kircode.AdvAlert 
{
import flash.display.DisplayObjectContainer;
import flash.display.MovieClip;
import flash.geom.Point;
/**
 * Advanced Alert window manager.
 * @author Kirill Poletaev
 */
public class AdvAlertManager 
{
private var windows:Array;
private var defaultContainer:DisplayObjectContainer;
private var pWidth:int;
private var pHeight:int;
private var skin:AdvAlertSkin;

/**
 * AdvAlertManager constructor.
 * @paramdefaultWindowContainer Parent container of alert windows.
 * @paramparentWidth Container's width.
 * @paramparentHeight Container's height.
 */

public function AdvAlertManager(defaultWindowContainer:DisplayObjectContainer, parentWidth:int, parentHeight:int, windowSkin:AdvAlertSkin = null) 
{
trace(": AdvAlertManager instance created.");
skin = windowSkin;
if (skin == null) skin = new AdvAlertSkin();
defaultContainer = defaultWindowContainer;
pWidth = parentWidth;
pHeight = parentHeight;
windows = [];
}

/**
 * Set skin of all future created alert windows.
 * @paramwindowSkin Reference to a skin object.
 */

public function setSkin(windowSkin:AdvAlertSkin):void {
skin = windowSkin;
}

/**
 * Create an alert window.
 * @paramtext Text value of the alert window.
 * @paramtitle Title value of the alert window.
 * @parambuttons (Optional) Array of AdvAlertButton objects that represent buttons in the alert window.
 * @paramwidth (Optional) Width of the alert window. 300 by default.
 * @paramheight (Optional) Height of the alert window. 200 by default.
 * @paramposition (Optional) Coordinates of top-left corner of the alert window. If not specified - the window is centered.
 */

public function alert(text:String, title:String = "", buttons:Array = null, width:int = 300, height:int = 200, position:Point = null):void {
if (position == null) position = new Point((pWidth / 2) - (width / 2), (pHeight / 2) - (height / 2));
if (buttons == null) buttons = [];
var w:AdvAlertWindow = new AdvAlertWindow(text, title, width, height, position, skin, buttons);
var b:AdvAlertBlur = new AdvAlertBlur(pWidth, pHeight, skin);
windows.push( { window:w, blur:b } );
defaultContainer.addChild(b);
defaultContainer.addChild(w);

trace("Message: " + text);
}

}

}

The buttons array will be filled with instances of AdvAlertButton class. Create AdvAlertButton.as class right now. Temporarily we will fill it with a little piece of code that draws a 80x30 rectangle. Even though we do that, we still won't be able to see it in action in this tutorial - so leave whatever placeholder you want.

package com.kircode.AdvAlert 
{
import flash.display.MovieClip;

/**
 * Advanced Alert window object.
 * @author Kirill Poletaev
 */
public class AdvAlertButton extends MovieClip
{

private var _w:Number = 80;
private var _h:Number = 30;

public function AdvAlertButton() 
{
updateDraw();
}

public function updateDraw():void {
this.graphics.clear();
// draw
this.graphics.beginFill(0x3333aa, 1);
this.graphics.drawRect(0, 0, _w, _h);
}


}

}

The buttons will be added to the array, then the code will read them and add them to the alert window, positioning them properly. For positioning, we will reserve a special spot for all the buttons. We'll refer to this spot as button bar from now on. The button bar by default will be a 30 pixel height box, located in the alert window on the very bottom of it, under the main text. It also has all default padding values set to 5.

Go to AdvAlertSkin.as and add 2 new variables - buttonbarHeight and buttonbarPadding:

public var buttonbarHeight:Number;
public var buttonbarPadding:TextPadding;

Set their default values in the constructor:

buttonbarHeight = 30;
buttonbarPadding = new TextPadding(5, 5, 5, 5);

Full class code:

package com.kircode.AdvAlert 
{
import flash.filters.DropShadowFilter;
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 var bgStroke:*;
public var headerStroke:*;
public var filters:Array;
public var blurColor:uint;
public var blurAlpha:Number;
public var buttonbarHeight:Number;
public var buttonbarPadding:TextPadding;

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], 1);
headerRect = new SolidColorRect(0x9999ff, [10, 10, 0, 0], 1);
bgStroke = new SolidColorStroke(2, 0x4444aa, 1);
headerStroke = new SolidColorStroke(0, 0x000000, 0);
filters = [new DropShadowFilter(0, 0, 0, 1, 20, 20, 1, 3)];
blurAlpha = 0.5;
blurColor = 0x888888;
buttonbarHeight = 30;
buttonbarPadding = new TextPadding(5, 5, 5, 5);
}

}

}

Now go to AdvAlertWindow.as class. Declare 3 new variables - buttons array, buttonbarPadding and buttonbarHeight:

private var buttons:Array;

private var buttonbarPadding:TextPadding;
private var buttonbarHeight:Number;

In the constructor we receive the buttons array and apply its value to the buttons variable:

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

setSkin(sk);

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

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

updateDraw();
}

Find the setSkin() function and add 2 lines that apply the buttonbarHeight and buttonbarPadding values from the skin object to the variables in this class:

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;
bgStroke = skin.bgStroke;
headerStroke = skin.headerStroke;
skinFilters = skin.filters;
buttonbarHeight = skin.buttonbarHeight;
buttonbarPadding = skin.buttonbarPadding;
}

Now find the piece of code that positions the textField object in updateDraw() function.

Modify the line that sets the height of it to substract the button bar height, top and bottom borders. Add temporary lines that set the background color of the textField:

// text
textField.width = w - (textPadding.right + textPadding.left);
textField.height = h - (textPadding.top + textPadding.bottom + headerPadding.top + headerPadding.bottom + headerHeight + buttonbarHeight + buttonbarPadding.top + buttonbarPadding.bottom);
// temporary, to see the edges of the text field
textField.background = true;
textField.backgroundColor = 0xff0000;
textField.text = t;
textField.x = pos.x + textPadding.right;
textField.y = pos.y + textPadding.top + headerHeight + headerPadding.bottom + headerPadding.top;

You should see the text field doesn't reach all the way down to fill all the available space in the alert window - it reserves space for the button bar.

Full updateDraw() code (I simplified some lines in bg fill and header fill parts of the code):

public function updateDraw():void {
this.graphics.clear();
// filters
this.filters = skinFilters;

// bg stroke
if (bgStroke is SolidColorStroke) {
this.graphics.lineStyle(bgStroke._lineThickness, bgStroke._lineColor, bgStroke._lineAlpha);
}
if (bgStroke is GradientColorStroke) {
this.graphics.lineStyle(bgStroke._lineThickness);
this.graphics.lineGradientStyle(bgStroke._gradientType, bgStroke._colors, bgStroke._alphas, bgStroke._ratios, bgStroke._matrix, bgStroke._spreadMethod, bgStroke._interpolationMethod, bgStroke._focalPointRatio);
}
if (bgStroke is BitmapStroke) {
this.graphics.lineStyle(bgStroke._lineThickness);
this.graphics.lineBitmapStyle(bgStroke._bitmap, bgStroke._matrix, bgStroke._repeat, bgStroke._smooth);
}

// bg fill
if (bgRect is SolidColorRect) this.graphics.beginFill(bgRect._backgroundColor, bgRect._alpha);
if (bgRect is GradientColorRect) this.graphics.beginGradientFill(bgRect._gradientType, bgRect._colors, bgRect._alphas, bgRect._ratios, bgRect._matrix, bgRect._spreadMethod, bgRect._interpolationMethod, bgRect._focalPointRatio);
if (bgRect is BitmapRect) this.graphics.beginBitmapFill(bgRect._bitmap, bgRect._matrix, bgRect._repeat, bgRect._smooth);

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 stroke
if (headerStroke is SolidColorStroke) {
this.graphics.lineStyle(headerStroke._lineThickness, headerStroke._lineColor, headerStroke._lineAlpha);
}
if (headerStroke is GradientColorStroke) {
this.graphics.lineStyle(headerStroke._lineThickness);
this.graphics.lineGradientStyle(headerStroke._gradientType, headerStroke._colors, headerStroke._alphas, headerStroke._ratios, headerStroke._matrix, headerStroke._spreadMethod, headerStroke._interpolationMethod, headerStroke._focalPointRatio);
}
if (headerStroke is BitmapStroke) {
this.graphics.lineStyle(headerStroke._lineThickness);
this.graphics.lineBitmapStyle(headerStroke._bitmap, headerStroke._matrix, headerStroke._repeat, headerStroke._smooth);
}

// header fill
if (headerRect is SolidColorRect) this.graphics.beginFill(headerRect._backgroundColor, headerRect._alpha);
if (headerRect is GradientColorRect) this.graphics.beginGradientFill(headerRect._gradientType, headerRect._colors, headerRect._alphas, headerRect._ratios, headerRect._matrix, headerRect._spreadMethod, headerRect._interpolationMethod, headerRect._focalPointRatio);
if (headerRect is BitmapRect) this.graphics.beginBitmapFill(headerRect._bitmap, headerRect._matrix, headerRect._repeat, headerRect._smooth);

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 + buttonbarHeight + buttonbarPadding.top + buttonbarPadding.bottom);
// temporary, to see the edges of the text field
textField.background = true;
textField.backgroundColor = 0xff0000;
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;
}

And full AdvAlertWindow.as 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 buttons:Array;

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

private var textPadding:TextPadding;
private var headerPadding:TextPadding;
private var titlePadding:TextPadding;
private var headerHeight:Number;
private var buttonbarPadding:TextPadding;
private var buttonbarHeight:Number;
private var titleFormat:TextFormat;
private var textFormat:TextFormat;
private var selectable:Boolean;
private var headerRect:*;
private var bgRect:*;
private var headerStroke:*;
private var bgStroke:*;
private var skinFilters:Array;

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

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;
bgStroke = skin.bgStroke;
headerStroke = skin.headerStroke;
skinFilters = skin.filters;
buttonbarHeight = skin.buttonbarHeight;
buttonbarPadding = skin.buttonbarPadding;
}

public function updateDraw():void {
this.graphics.clear();
// filters
this.filters = skinFilters;

// bg stroke
if (bgStroke is SolidColorStroke) {
this.graphics.lineStyle(bgStroke._lineThickness, bgStroke._lineColor, bgStroke._lineAlpha);
}
if (bgStroke is GradientColorStroke) {
this.graphics.lineStyle(bgStroke._lineThickness);
this.graphics.lineGradientStyle(bgStroke._gradientType, bgStroke._colors, bgStroke._alphas, bgStroke._ratios, bgStroke._matrix, bgStroke._spreadMethod, bgStroke._interpolationMethod, bgStroke._focalPointRatio);
}
if (bgStroke is BitmapStroke) {
this.graphics.lineStyle(bgStroke._lineThickness);
this.graphics.lineBitmapStyle(bgStroke._bitmap, bgStroke._matrix, bgStroke._repeat, bgStroke._smooth);
}

// bg fill
if (bgRect is SolidColorRect) this.graphics.beginFill(bgRect._backgroundColor, bgRect._alpha);
if (bgRect is GradientColorRect) this.graphics.beginGradientFill(bgRect._gradientType, bgRect._colors, bgRect._alphas, bgRect._ratios, bgRect._matrix, bgRect._spreadMethod, bgRect._interpolationMethod, bgRect._focalPointRatio);
if (bgRect is BitmapRect) this.graphics.beginBitmapFill(bgRect._bitmap, bgRect._matrix, bgRect._repeat, bgRect._smooth);

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 stroke
if (headerStroke is SolidColorStroke) {
this.graphics.lineStyle(headerStroke._lineThickness, headerStroke._lineColor, headerStroke._lineAlpha);
}
if (headerStroke is GradientColorStroke) {
this.graphics.lineStyle(headerStroke._lineThickness);
this.graphics.lineGradientStyle(headerStroke._gradientType, headerStroke._colors, headerStroke._alphas, headerStroke._ratios, headerStroke._matrix, headerStroke._spreadMethod, headerStroke._interpolationMethod, headerStroke._focalPointRatio);
}
if (headerStroke is BitmapStroke) {
this.graphics.lineStyle(headerStroke._lineThickness);
this.graphics.lineBitmapStyle(headerStroke._bitmap, headerStroke._matrix, headerStroke._repeat, headerStroke._smooth);
}

// header fill
if (headerRect is SolidColorRect) this.graphics.beginFill(headerRect._backgroundColor, headerRect._alpha);
if (headerRect is GradientColorRect) this.graphics.beginGradientFill(headerRect._gradientType, headerRect._colors, headerRect._alphas, headerRect._ratios, headerRect._matrix, headerRect._spreadMethod, headerRect._interpolationMethod, headerRect._focalPointRatio);
if (headerRect is BitmapRect) this.graphics.beginBitmapFill(headerRect._bitmap, headerRect._matrix, headerRect._repeat, headerRect._smooth);

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 + buttonbarHeight + buttonbarPadding.top + buttonbarPadding.bottom);
// temporary, to see the edges of the text field
textField.background = true;
textField.backgroundColor = 0xff0000;
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;
}


}

}

Thanks for reading!

No comments:

Post a Comment