Sunday, September 30, 2012

Creating Advanced Alert Window class: Part 28

In this tutorial we will add the ability to add dynamic content to our alert windows.

By dynamic content I mean any class that extends DisplayObject. This includes MovieClips, Sprites, etc. By enabling the developers to add these objects to the window, we allow them to add things like images, animations, even interactive elements to the alert, making the possibilities limitless.

Go to AdvAlertSkin class and declare an array dynamicContent:

public var dynamicContent:Array;

Set it to an empty array in the constructor:

dynamicContent = [];

Add a function addContent(), which will make the process of adding content elements to the window easier - receive 2 parameters: object and position. Push an object to dynamicContent with attributes obj and pos, containing the received data:

/**
 * Add dynamic content to the alert window.
 * @paramobject The object to add to the window.
 * @parampoint Position of the object inside the window.
 */

public function addContent(object:DisplayObject, position:Point):void {
dynamicContent.push({obj:object, pos:position});
}

Full AdvAlertSkin class:

package com.kircode.AdvAlert 
{
import flash.display.DisplayObject;
import flash.filters.DropShadowFilter;
import flash.geom.Point;
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 var buttonInterval:Number;
public var buttonbarAlign:String; // values: right, left, center
public var dynamicContent:Array;

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(0, 5, 5, 5);
buttonInterval = 5;
buttonbarAlign = "right";
dynamicContent = [];
}

/**
 * Add dynamic content to the alert window.
 * @paramobject The object to add to the window.
 * @parampoint Position of the object inside the window.
 */

public function addContent(object:DisplayObject, position:Point):void {
dynamicContent.push({obj:object, pos:position});
}

}

}

Now we need to go to AdvAlertWindow and receive the dynamicContent array from the skin.

First, declare the variable here:

private var dynamicContent:Array;

In the setSkin() function, receive the value from skin and apply it to local dynamicContent:

dynamicContent = skin.dynamicContent;

In the end of updateDraw() function, call a function called addContent():

// add dynamic content
addContent();

The function just loops through all elements of dynamicContent and adds it to the window:

private function addContent():void {
for (var i:int = 0; i < dynamicContent.length; i++) {
addChild(dynamicContent[i].obj);
dynamicContent[i].obj.x = dynamicContent[i].pos.x + pos.x;
dynamicContent[i].obj.y = dynamicContent[i].pos.y + pos.y;
}
}

Full AdvAlertWindow class:

package com.kircode.AdvAlert 
{
import flash.display.MovieClip;
import flash.events.Event;
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 parw:int;
private var parh:int;
public 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;
private var buttonInterval:Number;
private var defaultButtonSkin:AdvAlertButtonSkin;
private var buttonbarAlign:String;
private var dynamicContent:Array;

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

setSkin(sk);

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

titleField = new TextField();
addChild(titleField);
for (var i:int = 0; i < buttons.length; i++) {
if (buttons[i].currentSkin == null) {
buttons[i].setSkin(defaultButtonSkin);
buttons[i].updateDraw();
}
addChild(buttons[i]);
}

updateDraw();

if (ph == 0) autoSize();
}

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;
buttonInterval = skin.buttonInterval;
buttonbarAlign = skin.buttonbarAlign;
dynamicContent = skin.dynamicContent;
}

private function autoSize():void {
var textHeight:int = textField.textHeight;
h = headerHeight + headerPadding.top + headerPadding.bottom + buttonbarHeight + buttonbarPadding.top + buttonbarPadding.bottom + textPadding.top + textPadding.bottom + textHeight + 10;
pos.y = parh / 2 - h / 2;
updateDraw();
}

private function addContent():void {
for (var i:int = 0; i < dynamicContent.length; i++) {
addChild(dynamicContent[i].obj);
dynamicContent[i].obj.x = dynamicContent[i].pos.x + pos.x;
dynamicContent[i].obj.y = dynamicContent[i].pos.y + pos.y;
}
}

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);
textField.text = t;
textField.x = pos.x + textPadding.left;
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;

// buttons
var xCoord:Number;
var i:int

// right align
if(buttonbarAlign=="right"){
if (buttons.length > 0) xCoord = pos.x + w - buttons[buttons.length-1].w - buttonbarPadding.right;
for (i = buttons.length-1; i >= 0; i--) {
if (i != buttons.length-1) xCoord -= buttons[i].w + buttonInterval;
buttons[i].x = xCoord;
buttons[i].y = pos.y + h - buttons[i].h - buttonbarPadding.bottom;
}
}

// left align
if(buttonbarAlign=="left"){
if (buttons.length > 0) xCoord = pos.x + buttonbarPadding.left;
for (i = 0; i < buttons.length; i++) {
if (i > 0) xCoord += buttons[i].w + buttonInterval;
buttons[i].x = xCoord;
buttons[i].y = pos.y + h - buttons[i].h - buttonbarPadding.bottom;
}
}

// center align
if(buttonbarAlign=="center"){
if (buttons.length > 0) {
var buttonbarWidth:Number = 0;
for (i = 0; i < buttons.length; i++) {
buttonbarWidth += buttons[i].w + buttonInterval;
}
buttonbarWidth -= buttonInterval;
xCoord = pos.x + (w/2) - buttonbarWidth/2;
}
for (i = 0; i < buttons.length; i++) {
if (i > 0) xCoord += buttons[i].w + buttonInterval;
buttons[i].x = xCoord;
buttons[i].y = pos.y + h - buttons[i].h - buttonbarPadding.bottom;
}
}

// add dynamic content
addContent();
}


}

}

Now, let's create an example window that contains an image.

Open the testing flash source file and add a new item to the library there - a MovieClip with an image inside of it. Make sure the coordinates of the image's top left corner are (0;0). My image's sizes are 120x112.

Now go to main.as (the document class of the flash file) and create a custom skin with an image embedded using addContent(). Set text's padding to a greater value to not overlap with the window:

var myIcon:MovieClip = new warning_icon();

var mySkin:AdvAlertSkin = new AdvAlertSkin();
mySkin.addContent(myIcon, new Point(5, 40));
mySkin.textPadding.left = 140;

AlertManager = new AdvAlertManager(this, stage, mySkin);
AlertManager.alert("This is an alert window with a custom skin and a dynamic content element.", "Example alert!", null, null, 500, 160);

And the results are:



Thanks for reading!

No comments:

Post a Comment