Showing posts with label event listener. Show all posts
Showing posts with label event listener. Show all posts

Wednesday, August 17, 2011

One image, three states of button.


When we want to create custom button, usually three states considered: mouse over (roll over), mouse out (roll out) and press (click, release). If it is advanced, with multiple animations, and differences between those free states, theres no other way to create each of them separately. But if You need quite simple button which changes its color, look at this example.

Firstly some declarations:

private var _loader:Loader;


private var _colorTransform:ColorTransform;
private var _rollOverColorTransform:ColorTransform;
private var _clickColorTransform:ColorTransform;
        
private var _color:uint;
private var _rollOverColor:uint;
private var _clickColor:uint;

We also have to define values:

_color = 0xFFFFFF;
_rollOverColor = 0xFF6600;

We load image:

_loader = new Loader();
_loader.load(new URLRequest(url));
addChild(_loader);
buttonMode = true;

Prepare transformations for switching states:

_colorTransform = _loader.transform.colorTransform;
_colorTransform.color = _color;
_loader.transform.colorTransform = _colorTransform;
            
_rollOverColorTransform = _loader.transform.colorTransform;
_rollOverColorTransform.color = _rollOverColor;


_clickColorTransform = _loader.transform.colorTransform;
_clickColorTransform.color = _clickColor;

Then we set listeners:

addEventListener(MouseEvent.ROLL_OVER, handleRollOver);
addEventListener(MouseEvent.ROLL_OUT, handleRollOut);
addEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);

And handlers for events:


private function handleRollOver(e:MouseEvent):void
{
    _loader.transform.colorTransform = _rollOverColorTransform;
}
    
private function handleRollOut(e:MouseEvent):void
{
    _loader.transform.colorTransform = _colorTransform;
}
        
private function handleMouseDown(e:MouseEvent):void
{
    _loader.transform.colorTransform = _clickColorTransform;
}

And it's done!

Check it:




Monday, July 11, 2011

Dynamic Font Embedding

When You want to load some parts or modules later font is one of thing that is not most important. Sometimes there is some kind of configuration where you or user chooses which font should be used. In those situations font should be embedded dynamically. So here simple instruction step by step:

Firstly we need font packed separately in swf. I made sepataed project to easily maintain it but it can also be module. My code looks like this:


package Arial
{
import flash.display.Sprite;

public class Font_Arial extends Sprite
{
[Embed(source='ARIAL.ttf', fontName="Font_Arial", unicodeRange='U+0020-U+002F,U+0030-U+0039,U+003A-U+0040,U+0041-U+005A,U+005B-U+0060,U+0061-U+007A,U+007B-U+007E, U+00A0-U+00FF, U+0100-U+017E, U+20AC')]
public static var Font_Arial:Class;


[Embed(source='ARIALBD.ttf', fontWeight= "bold", fontName="Font_Arial", unicodeRange='U+0020-U+002F,U+0030-U+0039,U+003A-U+0040,U+0041-U+005A,U+005B-U+0060,U+0061-U+007A,U+007B-U+007E, U+00A0-U+00FF, U+0100-U+017E, U+20AC')]
public static var Font_ArialBold:Class;

[Embed(source='ARIALI.ttf', fontStyle='italic', fontName="Font_Arial", unicodeRange='U+0020-U+002F,U+0030-U+0039,U+003A-U+0040,U+0041-U+005A,U+005B-U+0060,U+0061-U+007A,U+007B-U+007E, U+00A0-U+00FF, U+0100-U+017E, U+20AC')]
public static var Font_ArialItalic:Class;

[Embed(source='ARIALBI.ttf', fontStyle='italic', fontWeight= "bold",fontName="Font_Arial", unicodeRange='U+0020-U+002F,U+0030-U+0039,U+003A-U+0040,U+0041-U+005A,U+005B-U+0060,U+0061-U+007A,U+007B-U+007E, U+00A0-U+00FF, U+0100-U+017E, U+20AC')]
public static var Font_ArialBoldItalic:Class;


}
}

Maybe small description of code. I have  got package name. This will be important later.
Class name is something you can sat as you wish. The only thing is that it cannot be named as Font name in system, so if you name it Arial there will be conflict.
As You can see I'm embedding similar files - each one consist different style - there is normal, bold, italic and bold&italic (last one is separated style!). For each one there are describing parameters fontWeight and fontStyle.
FontName for all font styles must be the same and must be same as class name.
Last parameter is unicodeRange. it describes which signs are embedded. You can leave it but then all signs will added which usually is unnecessary and your file will be heavy. For example all glyphs from Arial normal (without bold and italic) weights about 300kB when my file with four styles and only glyphs that are used by my application (latin symbols, numbers, special chars) weights 90kB.

Now let's load it

public function FontLoader():void {
loadFont(_serverPath+"fonts/Arial/Font_Arial.swf");
}


private function loadFont(url:String):void {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, fontLoaded);
loader.load(new URLRequest(url));
}

I hope this part is easy and don't need comment


private function fontLoaded(event:Event):void 
{
var FontLibrary:Class = event.target.applicationDomain.getDefinition("Arial.Font_Arial") as Class;


Font.registerFont(FontLibrary['Font_Arial']);
Font.registerFont(FontLibrary['Font_ArialBold']);
Font.registerFont(FontLibrary['Font_ArialItalic']);
Font.registerFont(FontLibrary['Font_ArialBoldItalic']);


drawText();
}

We're extracting data from externall module. Remember my package name Arial? Full class name with package has to be put to getDefinition() method. Remember about package name. I lost some time to figure it out.
When you register font you can use it globally in your app.  Instead of calling similar command four time you can use foreach loop here.
Now we can use our font.

public function drawText():void
{
var tf:TextFormat = hintText.getTextFormat();

tf.font = "Font_Arial";
hintText.embedFonts = true;
hintText.setTextFormat(tf);
hintText.defaultTextFormat = tf;

}

I hope it's clear enough.

Friday, March 11, 2011

ADDED vs. ADDED_TO_STAGE

ADDED and ADDED_TO_STAGE are two events that are dispatched on object when this is added as child to displayed parent. But there is a reason why they both exist. Here is small study on differences.

Case #1 - adding object to stage.
in this case we're adding class (named A) to main class which is stage. both listeners are added as in presented code:

public class A extends Sprite
{
    public function A()
    {
        trace('A A()');
        super();

        addEventListener(Event.ADDED, _handleAdded);
        addEventListener(Event.ADDED_TO_STAGE, _handleAddedtoStage);
    }

    private function _handleAdded(event:Event):void
    {
        trace('A added');
    }

    private function _handleAddedtoStage(event:Event):void
    {
        trace('A AddedtoStage');
    }
}


And here is main class code:

public function Blog()
{
    trace('Blog Blog()');
    var a:A = new A();

    trace('adding A to stage');
    addChild(a);
}


Here is result of experiment:

Blog Blog()
A A()
adding A to stage
A added
A AddedtoStage


Conclusion: both events works works similar. What is more, everytime ADDED is before ADDED_TO_STAGE. Flash is not working parallely so there must be some reason of this constant order. If You switch adding listeners result is the same. This shows that ADDED is always dispatched before ADDED_TO_STAGE.

Case #2 - cascade adding objects to stage
Now we add one more object, so structure will look like this:

Stage(Blog) -> A -> B

Main class of Blog stays same as in previous example. Class A is modified to create instance and load into itself object of type B. Here is code of class A:

public class A extends Sprite
{
    public function A()
    {
        trace('A A()');
        super();

        addEventListener(Event.ADDED_TO_STAGE, _handleAddedtoStage);
        addEventListener(Event.ADDED, _handleAdded);

        var b:B = new B();
        addChild(b);
    }

    private function _handleAdded(event:Event):void
    {
        trace('A added');
    }

    private function _handleAddedtoStage(event:Event):void
    {
        trace('A AddedtoStage');
    }
}


And here we have source of class B. It looks like class A in previous case:

public class B extends Sprite
{
    public function B()
    {
        trace('B B()');
        super();

        addEventListener(Event.ADDED_TO_STAGE, _handleAddedtoStage);
        addEventListener(Event.ADDED, _handleAdded);
    }

    private function _handleAdded(event:Event):void
    {
        trace('B added');
    }

    private function _handleAddedtoStage(event:Event):void
    {
        trace('B AddedtoStage');
    }
}


And let's see what now happens:

Blog Blog()
A A()
B B()
B added
A added
adding A to stage
A added
A AddedtoStage
B AddedtoStage


Conclusion: First thing is that an event ADDED is captured in class A twice. Once when object is added to this class as child and once when the object itself is added to parent. Second and most important part delay between capturing those event. This shows that event ADDED is dispatched each time when method addChild (or AddChildAt) are called. And this event is dispatched first. ADDED_TO_STAGE is dispatched when object or it's parent or a structure of objects of many levels are added to displayed class on stage. And this event goes as second. Last thing - ADDED_TO_STAGE event is propagated from stage to it's children and to further levels of descendants


Wednesday, February 2, 2011

buttonMode & TextFields

We have some kind of like Sprite/MovieClip. We're creating our own button or item that should be click-able. So we set buttonMode, add event listener, and everything is ok till we add some text. And here comes problem. Hand cursor disappears when we roll over on the text.

best solution is to use mouseChildren property.

this.buttonMode = true;
this.mouseChildren = false;
this.addEventListener(MouseEvent.MOUSE_UP, _handleMouseRelease);

All objects added as child won't be mouse enabled