From the monthly archives:

December 2009

Šťastný a úspěšný nový rok 2010!

by Viktor Bezděk on December 31, 2009

Přeji všem čtenářům i obchodním partnerům úspěšný vstup do nového roku. Nechť nám přinese silné zdraví, nové a lepší technologie (a jejich hladké zvládnutí), méně zmrdů a více úspěchů.

Do nového roku slibuji více článků a workshopy s AUG (MVC, 3D, AS3 komponenty).

How to get FDT to ignore some “erroneous” code

by Slavomír Durej on December 19, 2009

Have been using FDT for about 3 and a half years now, on many occasions I came across a code that , although perfectly compilable (both by mxmlc and flash IDE), FDT thought it contained errors.

For example when code contained some “clever” trinary operator arguments, or a javascript code segments wrapped in CDATA …

Anyway, I came across a simple way to make FDT to ignore such code.

If you place the problematic code inside a /*FDT_IGNORE*/ …. /*FDT_IGNORE*/ comments, FDT will not parse such code and therefore will not mark it as code containing syntactic error. Goodbye red marks !

However .. on the other side, if such code contains a functions or variables that other classes refer to, FDT will not be able to find those references in the “ignored” sections.

So use it with caution !

RayMath class

by Jozef Chúťka on December 16, 2009

raymath

While working on newest project I created a simple util class that simulates rays of spot light. It uses DisplayObject hitTestPoint() method to test for ray stream collisions so it does not go beyond the obstacles (corners etc.). Feel free to use RayMath class as you wish

RayMath application

RayMath class

package sk.yoz.math
{
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.geom.Point;

    public class RayMath extends Object
    {
        public function RayMath()
        {
            super();
        }

        public static function getRayPoints(lamp:DisplayObject,
            boundary:DisplayObject, rayCount:uint = 50, rayRange:uint = 50)
            :Array
        {
            var lp:Point, gp:Point, fp:Point;
            var points:Array = [];
            var angle:Number;
            for(var i:uint = 0; i < rayCount; i++)
            {
                fp = null;
                for(var j:uint = 0; j < rayRange; j++)
                {
                    angle = Math.PI / rayCount * i * 2;
                    lp = new Point(Math.cos(angle) * j, Math.sin(angle) * j);
                    gp = lamp.localToGlobal(lp);
                    if(!boundary.hitTestPoint(gp.x, gp.y, true))
                        break;
                    fp = lp;
                }
                if(fp)
                    points.push(fp);
            }
            return points;
        }

        public static function boundaryDistance(points:Array):Number
        {
            var shortest:Number = Number.MAX_VALUE;
            var zeroPoint:Point = new Point(0, 0);
            var distance:Number;
            for each(var point:Point in points)
            {
                distance = Point.distance(point, zeroPoint);
                if(distance < shortest)
                    shortest = distance;
            }
            return shortest;
        }

        public static function drawRays(lamp:Sprite, points:Array):void
        {
            if(!points.length)
                return;
            lamp.graphics.moveTo(points[0].x, points[0].y);
            for each(var point:Point in points)
                lamp.graphics.lineTo(point.x, point.y);
            lamp.graphics.lineTo(points[0].x, points[0].y);
        }
    }
}

Demo application

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    applicationComplete="init()" width="500" height="500"
    backgroundGradientAlphas="1,1" backgroundColor="0xffffff">
<mx:Script>
<![CDATA[
    import sk.yoz.math.RayMath;

    private function init():void
    {
        var bg:Graphics = boundary.graphics;
        bg.beginFill(0x000000, 1);

        bg.moveTo(50, 50);
        bg.lineTo(width - 50, 130);
        bg.lineTo(width - 150, height - 50);
        bg.lineTo(100, height - 100);
        bg.lineTo(50, 50);

        bg.moveTo(100, 200);
        bg.lineTo(300, 200);
        bg.lineTo(250, 300);
        bg.lineTo(100, 200);

        bg.moveTo(300, 250);
        bg.lineTo(350, 250);
        bg.lineTo(350, 300);
        bg.lineTo(300, 250);

        lamp.startDrag(true);
        addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
    }

    private function mouseMoveHandler(event:MouseEvent):void
    {
        var lg:Graphics = lamp.graphics;
        lg.clear();
        lg.beginFill(0xffff00, 0.5);
        lg.lineStyle(1, 0xffff00, 0.8);
        var points:Array = RayMath.getRayPoints(lamp, boundary, 80, 100);
        RayMath.drawRays(lamp, points);

        lg.endFill();
        for each(var point:Point in points)
        {
            lg.moveTo(0, 0);
            lg.lineTo(point.x, point.y);
        }
    }
]]>
</mx:Script>
<mx:UIComponent id="boundary" />
<mx:UIComponent id="lamp" />
</mx:Application>

FacebookLogger

by josefchutka on December 8, 2009

facebook-small-logo

In a last couple of weeks I have been working on a lot of facebook applications. It did not took long to realize that there is always the same logic behind logging/connecting to facebook. So I came to FacebookLogger abstraction class that handles these basic steps. It only contains login/connection logic, so its pretty much the core that is usable only after extending.

FacebookLogger class look like this:

package sk.yoz.net
{
    import com.facebook.events.FacebookEvent;
    import com.facebook.Facebook;
    import com.facebook.utils.FacebookSessionUtil;

    import flash.events.EventDispatcher;
    import flash.events.IEventDispatcher;
    import flash.display.LoaderInfo;

    import mx.events.CloseEvent;
    import mx.controls.Alert;

    import sk.yoz.events.FacebookLoggerEvent;

    public class FacebookLogger extends EventDispatcher
    {
        public static const NOT_LOGGED:String = "Seems like not logged, click when logged!";

        protected var facebook:Facebook;
        protected var session:FacebookSessionUtil;

        private var _connected:Boolean = false;

        public function FacebookLogger(target:IEventDispatcher=null)
        {
            super(target);
        }

        [Bindable(event="FacebookLoggerEventCONNECTED")]
        public function get connected():Boolean
        {
            return _connected;
        }

        protected function set connected(value:Boolean):void
        {
            _connected = value;
            dispatchEvent(new FacebookLoggerEvent(FacebookLoggerEvent.CONNECTED));
        }

        public function init(apiKey:String, appSecret:String,
            loaderInfo:LoaderInfo, parameters:Object):void
        {
            session = new FacebookSessionUtil(apiKey, appSecret, loaderInfo);
            session.addEventListener(FacebookEvent.CONNECT, connectHandler);
            facebook = session.facebook;

            if(parameters.fb_sig_session_key)
                 session.verifySession();
            else
                login();
        }

        protected function login():void
        {
            session.login();
            Alert.show(NOT_LOGGED, null, 4, null, loggedClose);
        }

        protected function connectHandler(event:FacebookEvent):void
        {
            if(!event.success)
                return login();

            protected::connected = true;
        }

        protected function loggedClose(event:CloseEvent):void
        {
            session.validateLogin();
        }
    }
}

… and you also gonna require FacebookLoggerEvent class …

package sk.yoz.events
{
    import flash.events.Event;

    public class FacebookLoggerEvent extends Event
    {
        public static const CONNECTED:String = "FacebookLoggerEventCONNECTED";

        public function FacebookLoggerEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
        {
            super(type, bubbles, cancelable);
        }

    }
}

Now, lets extend the core class. This class should hold all the required logic and communication with facebook, its fine to make it singleton:

package
{
    import mx.core.Application;

    import sk.yoz.events.FacebookLoggerEvent;
    import sk.yoz.net.FacebookLogger;

    public class FB extends FacebookLogger
    {
        private static const SINGLETON_LOCK:Object = {};
        private static const _instence:FB = new FB(SINGLETON_LOCK);

        protected var API_KEY:String = "***";
        protected var APP_SECRET:String = "***";

		private var initCallback:Function;

        public function FB(lock:Object)
        {
            super();

            if(lock != SINGLETON_LOCK)
                throw new Error("Use FB.instance!");

            addEventListener(FacebookLoggerEvent.CONNECTED, loggerConnectedHandler)
        }

        public static function get instance():FB
        {
            return _instence;
        }

        public function init2(application:Application):void
        {
			if(public::connected)
                return;
            init(API_KEY, APP_SECRET, application.loaderInfo, application.parameters);
        }

		public function initWithCallback(application:Application, callback:Function):void
        {
            initCallback = callback;
            init2(application);
        }

        private function loggerConnectedHandler(event:FacebookLoggerEvent):void
        {
			if(initCallback != null)
                initCallback();
			initCallback = null;
            // now we are connected, your code may go here
        }
    }
}

Update (Jan 6, 2009): Suggested initWithCallback() function where you can define callback function that is called after successful connect.

… so we can use in application as simple as possible:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    addedToStage="addedToStageHandler()">
<mx:Script>
<![CDATA[
    import FB;

    [Bindable]
    private var fb:FB = FB.instance;

    private function addedToStageHandler():void
    {
        fb.init2(this);
    }
]]>
</mx:Script>
<mx:Text text="{fb.connected ? 'connected' : 'connecting'}" />
</mx:Application>

Yeshi Silvano Norbu – Retreat

by Martin Boháč on December 6, 2009

Fotky jsou k dispozici zde, pokud nějakou z nich chcete použít, dejte mi vědět.

Flex Charts – interpolating values in Series

by Jozef Chúťka on December 4, 2009

interpolateValues

Recently, I felt into problem with chart when using interpolateValues parameter set to true. You expect it to work as described in Language Reference. And guess what, it works :) , but make sure you provide correct numeric values (not strings – those were problematic in my case). Parameter interpolateValues is able to draw a continuous line by interpolating the missing value. Missing values means null (v1 in example) or when key is omited (v2).

If you want to use Charts in Flex, download data visualization components for your flex builder and copy content into sdk directory.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
    backgroundColor="#ffffff">
<mx:Script>
<![CDATA[
    import mx.collections.ArrayCollection;

    [Bindable]
    private var dp:ArrayCollection = new ArrayCollection([
        {Month: "Jan", v1: 1000, v2: 900, v3: "800", v4: "700"},
        {Month: "Feb", v1: null, v3: null},
        {Month: "Mar", v1: 2000, v2: 1900, v3: "1800", v4: "1700"}
    ]);
]]>
</mx:Script>

<mx:Stroke id = "s1" color="blue" weight="2"/>
<mx:Stroke id = "s2" color="red" weight="2"/>
<mx:Stroke id = "s3" color="green" weight="2"/>
<mx:Stroke id = "s4" color="yellow" weight="2"/>

<mx:LineChart id="lineChart" height="100%" width="100%" dataProvider="{dp}">
    <mx:horizontalAxis>
        <mx:CategoryAxis categoryField="Month"/>
    </mx:horizontalAxis>
    <mx:series>
        <mx:LineSeries yField="v1" form="curve" displayName="v1"
            lineStroke="{s1}" interpolateValues="true"/>
        <mx:LineSeries yField="v2" form="curve" displayName="v2"
            lineStroke="{s2}" interpolateValues="true"/>
        <mx:LineSeries yField="v3" form="curve" displayName="v3"
            lineStroke="{s3}" interpolateValues="true"/>
        <mx:LineSeries yField="v4" form="curve" displayName="v4"
            lineStroke="{s4}" interpolateValues="true"/>
    </mx:series>
</mx:LineChart>
<mx:Legend dataProvider="{lineChart}" direction="horizontal"/>
</mx:Application>

Notice numeric vs. string values in dataProvider. Result:

interpolateValues