Archive for the 'Tips & Tricks' Category



16
Feb

Declaration tag in Flex Gumbo

Flex Gumbo have added a new tag called declaration. The new tag has to be used in cases where you want to reference a component that is not part of the mx.core or classes that are not display objects.

For instance, when creating Cairngorm projects you need to set references in the entry point to your controller, services and view such as the following code:


	<view:MainApp />
	<control:Controller />
	<business:Services />

However, in Flex Gumbo classes that are not display objects needs to be placed in a a declarations tag. Change your code easily by placing your classes to the declaration tag as follow;


	<view:MainApp />
	<Declarations>
		<control:Controller />
		<business:Services />
	</Declarations>

Otherwise you will get the following runtime error message.


TypeError: Error #1034: Type Coercion failed: cannot convert com.domain.project.control::Controller@21cf9d61 to flash.display.DisplayObject.
	at mx.components::Group/itemAdded()[E:\dev\gumbo_alpha\frameworks\projects\flex4\src\mx\components\Group.as:752]
	at mx.components::Group/initializeChildrenArray()[E:\dev\gumbo_alpha\frameworks\projects\flex4\src\mx\components\Group.as:251]
	at mx.components::Group/commitProperties()[E:\dev\gumbo_alpha\frameworks\projects\flex4\src\mx\components\Group.as:267]
	at mx.core::UIComponent/validateProperties()[E:\dev\gumbo_alpha\frameworks\projects\framework\src\mx\core\UIComponent.as:6130]
	at mx.managers::LayoutManager/validateProperties()[E:\dev\gumbo_alpha\frameworks\projects\framework\src\mx\managers\LayoutManager.as:539]
	at mx.managers::LayoutManager/doPhasedInstantiation()[E:\dev\gumbo_alpha\frameworks\projects\framework\src\mx\managers\LayoutManager.as:659]
	at Function/http://adobe.com/AS3/2006/builtin::apply()
	at mx.core::UIComponent/callLaterDispatcher2()[E:\dev\gumbo_alpha\frameworks\projects\framework\src\mx\core\UIComponent.as:8849]
	at mx.core::UIComponent/callLaterDispatcher()[E:\dev\gumbo_alpha\frameworks\projects\framework\src\mx\core\UIComponent.as:8789]

Notice that I haven’t placed my view in the declaration tag, since my view is a Canvas component, which extends Container. So what?

Component that doesn’t implements the mx.core namespace has to go into the declaration tag, including all the Fx components, however Canvas extends Container which is part of mx.core so no need to place it in the declaration tag.

By the way, you may have the same issue with PureMVC projects. The view reference in your entry point may need to be placed in the declaration tag, as explained above.

27
Jan

Tips - Debugging Flex applications with flashlog.txt on a Mac

Debugging Flex applications with mm.cfg and flashlog.txt let us track trace statements and error messages for projects running in the browser using the debug mode. Since I haven’t done it since 2001 I completely forget what to do and came across couple of issues, so I figured I’ll throw a post for other people that may have the same issue.

You first need to create the txt file and directories here:
/Users/YourUserName/Library/Preferences/Macromedia/Flash\ Player/Logs/flashlog.txt

Then you need to create the mm.cfg file in both location:
/Library/Application Support/Macromedia/mm.cfg
/Users/YourUserName/mm.cfg

Then paste the follwing code in the mm.cfg:
ErrorReportingEnable=1
TraceOutputFileEnable=1
MaxWarnings=0

Initially, I pasted the code only in the first directory and couldn’t get it to work, not sure why, so place the file in both directories to play it safe.
I am running the Flash Debug Player 10, on Mac OS X.

To see the messages as they come on Terminal, navigate to the flashlog directory and type in:
tail -f flashlog.txt

I Hope you find this tip handy.

03
Dec

Use ThunderBolt in Cairngorm application to log messages and debug

Here’s a tip regarding logging messages in Cairngorm application. I would recommend using ThunderBolt with Mozilla firebug. ThunderBolt is a light weight logging mechanism and very simple to implement; on every user gesture add a logger message during the following methods: execute, result and fault.

To use ThunderBolt just place the ThunderBolt swc in your lib folder and log a message, for instance:
Logger.error (”Logging two objects: A number typed as int and a string”, myNumber, myString);

ThunderBolt screenshot

Once you compile and run the application you can keep track of all the methods that got executed and save time debugging the application. Additionally, using this method can help you figure out if there are unnecessary double calls to the same commands.
Thunderbolt is available to AS2/3 code as well as AIR and Flex Gumbo: http://code.google.com/p/flash-thunderbolt/

There are two ways to implement, one directly through ThunderBolt such as here:

Example:


/*
 Copyright (c) 2008 Elrom LLC, All Rights Reserved 

 @author   Elad Elrom
 @contact  elad.ny at gmail.com
 @project  Example project

 @internal 

 */

package com.elad.Project.commands.services
{
	import com.adobe.cairngorm.commands.ICommand;
	import com.adobe.cairngorm.control.CairngormEvent;
	import com.elad.Project.business.SequenceDelegate;
	import com.elad.Project.events.SequenceEvent;
	import com.elad.Project.model.ModelLocator;

	import mx.rpc.IResponder;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;

	import org.osflash.thunderbolt.Logger;

    /**
     *
     * Defines the associated <code>ICommand</code> implementation for
     * an "Sequence" use-case.
     *
     * <p>
     * The <code>SequenceCommand</code> is utilized to abstract the
     * handling of a <code>SequenceEvent</code>.
     * </p>
     *
     * @see com.elad.Project.events.SequenceEvent
     * @see com.adobe.cairngorm.commands.ICommand
     *
     */
	public final class SequenceCommand implements ICommand, IResponder
	{

		/**
		 *
		 * Defines a local convenience reference to the application
		 * <code>ModelLocator</code> implementations
		 *
		 */
		private var modelLocator:ModelLocator = ModelLocator.getInstance();

	    /**
	     *
	     * Concrete <code>ICommand</code> implementation which handles
	     * an <code>SequenceEvent</code>.
	     *
	     */
		public function execute(event:CairngormEvent) : void
		{
			Logger.info( "SequenceCommand"+" execute" );
			var evt:SequenceEvent = event as SequenceEvent;
			var delegate:SequenceDelegate = new SequenceDelegate( this );

			delegate.callSomeMethod();
		}

	    /**
	     *
	     * Handles the service result of the <code>SequenceDelegate</code>
	     * service invocation.
	     *
	     * @see mx.rpc.events.ResultEvent
	     *
	     */
		public function result(data:Object) : void
		{
			Logger.info( "SequenceCommand"+" result" );
			var result:ResultEvent = data as ResultEvent;
		}

	    /**
	     *
	     * Handles the service fault of the <code>SequenceDelegate</code>
	     * service invocation.
	     *
	     * @see mx.rpc.events.ResultEvent
	     *
	     */
		public function fault(info:Object) : void
		{
			var fault:FaultEvent = info as FaultEvent;
			Logger.error( "SequenceCommand", fault );
		}
	}
}

A better way to implements, as suggested by Stefan Bistram which is more recommended since your classes don’t really need to know anything about ThunderBolt and you will be able to make changes without changing your entire code is using ThunderBoltTarget. The way it works is that you inject ThunderBolt to the Logging API built into Flex. You just set the target object in your entry class in MXML;


/**
 *
 * Define an instance of <code>ThunderBoltTarget</code>
 *
 * @see org.osflash.thunderbolt.ThunderBoltTarget
 * @see mx.logging.Log
 *
 */
private var _target: ThunderBoltTarget = new ThunderBoltTarget();

Than on set the filter to point to your command package;


_target.filters = ["com.elad.project.commands.*"];
Log.addTarget(_target);	

And now you can use the Flex Log API to inject your messages;


/*
 Copyright (c) 2008 Elrom LLC, All Rights Reserved 

 @author   Elad Elrom
 @contact  elad.ny at gmail.com
 @project  Example project

 @internal 

 */

package com.elad.Project.commands.services
{
	import com.adobe.cairngorm.commands.ICommand;
	import com.adobe.cairngorm.control.CairngormEvent;
	import com.elad.Project.business.SequenceDelegate;
	import com.elad.Project.events.SequenceEvent;
	import com.elad.Project.model.ModelLocator;

	import mx.rpc.IResponder;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;

    /**
     *
     * Defines the associated <code>ICommand</code> implementation for
     * an "Sequence" use-case.
     *
     * <p>
     * The <code>SequenceCommand</code> is utilized to abstract the
     * handling of a <code>SequenceEvent</code>.
     * </p>
     *
     * @see com.elad.Project.events.SequenceEvent
     * @see com.adobe.cairngorm.commands.ICommand
     *
     */
	public final class SequenceCommand implements ICommand, IResponder
	{

		/**
		 *
		 * Defines a local convenience reference to the application
		 * <code>ModelLocator</code> implementations
		 *
		 */
		private var modelLocator:ModelLocator = ModelLocator.getInstance();

	    /**
	     *
	     * Concrete <code>ICommand</code> implementation which handles
	     * an <code>SequenceEvent</code>.
	     *
	     */
		public function execute(event:CairngormEvent) : void
		{
                  			Log.getLogger("com.elad.project.commands.services.SequenceCommand").info("execute");

			var evt:SequenceEvent = event as SequenceEvent;
			var delegate:SequenceDelegate = new SequenceDelegate( this );

			delegate.callSomeMethod();
		}

	    /**
	     *
	     * Handles the service result of the <code>SequenceDelegate</code>
	     * service invocation.
	     *
	     * @see mx.rpc.events.ResultEvent
	     *
	     */
		public function result(data:Object) : void
		{
			Log.getLogger("com.elad.project.commands.services.SequenceCommand").info("result");

			var result:ResultEvent = data as ResultEvent;
		}

	    /**
	     *
	     * Handles the service fault of the <code>SequenceDelegate</code>
	     * service invocation.
	     *
	     * @see mx.rpc.events.ResultEvent
	     *
	     */
		public function fault(info:Object) : void
		{
			var fault:FaultEvent = info as FaultEvent;
			Log.getLogger("com.elad.project.commands.services.SequenceCommand").error("fault", fault);

		}
	}
}

If you are using Cairngen 2.1.1 I have created template that you can just paste into your library for Cairngorm 2.2.1. Feel free to download and use them. Here’s the one for CommandExcludeDelegate.tpl:


@copy@

package @namespace@.commands
{
	import com.adobe.cairngorm.commands.ICommand;
	import com.adobe.cairngorm.control.CairngormEvent;
	import @namespace@.events.@sequence@Event;
	import @namespace@.model.ModelLocator;
	import mx.logging.Log;

    /**
     *
     * Defines the associated <code>ICommand</code> implementation for
     * the "@sequence@" use-case.
     *
     * <p>
     * The <code>@sequence@Command</code> is utilized to abstract the
     * handling of an <code>@sequence@Event</code>
     * </p>
     *
     * @see @namespace@.events.@sequence@Event
     * @see com.adobe.cairngorm.commands.ICommand
     *
     */
	public final class @sequence@Command implements ICommand
	{
		/**
		 *
		 * Defines a local convenience reference to the application
		 * <code>ModelLocator</code> implementations
		 *
		 */
		private var modelLocator:ModelLocator = ModelLocator.getInstance();

	    /**
	     *
	     * <code>ICommand</code> implementation which handles an
	     * <code>@sequence@Event</code>.
	     *
	     * <p>
         * The <code>@sequence@Command</code> does not require a specific
         * service invocation to be made, therefore the handling of an
         * <code>@sequence@Event</code> is completely managed by the
         * <code>@sequence@Command</code>.
	     * </p>
	     *
	     */
		public function execute(event:CairngormEvent) : void
		{
			Log.getLogger("@namespace@.commands.@sequence@Command").info("execute");
			var evt:@sequence@Event = event as @sequence@Event;
		}
	}
}

And here’s the one for CommandIncludeDelegate.tpl:


@copy@

package @namespace@.commands
{
	import com.adobe.cairngorm.commands.ICommand;
	import com.adobe.cairngorm.control.CairngormEvent;
	import @namespace@.business.@sequence@Delegate;
	import @namespace@.events.@sequence@Event;
	import @namespace@.model.ModelLocator;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.AsyncToken;
	import mx.rpc.IResponder;
	import mx.logging.Log;

    /**
     *
     * Defines the associated <code>ICommand</code> implementation for
     * an "@sequence@" use-case.
     *
     * <p>
     * The <code>@sequence@Command</code> is utilized to abstract the
     * handling of a <code>@sequence@Event</code>.
     * </p>
     *
     * @see @namespace@.events.@sequence@Event
     * @see com.adobe.cairngorm.commands.ICommand
     *
     */
	public final class @sequence@Command implements ICommand, IResponder
	{
		/**
		 *
		 * Defines a local convenience reference to the application
		 * <code>ModelLocator</code> implementations
		 *
		 */
		private var modelLocator:ModelLocator = ModelLocator.getInstance();

	    /**
	     *
	     * Concrete <code>ICommand</code> implementation which handles
	     * an <code>@sequence@Event</code>.
	     *
	     */
		public function execute(event:CairngormEvent) : void
		{
			Log.getLogger("@namespace@.commands.@sequence@Command").info("execute");

			var evt:@sequence@Event = event as @sequence@Event;
			var delegate:@sequence@Delegate = new @sequence@Delegate( this );
		}

	    /**
	     *
	     * Handles the service result of the <code>@sequence@Delegate</code>
	     * service invocation.
	     *
	     * @see mx.rpc.events.ResultEvent
	     *
	     */
		public function result(data:Object) : void
		{
			Log.getLogger("@namespace@.commands.@sequence@Command").info("result");
			var result:ResultEvent = data as ResultEvent;
		}

	    /**
	     *
	     * Handles the service fault of the <code>@sequence@Delegate</code>
	     * service invocation.
	     *
	     * @see mx.rpc.events.ResultEvent
	     *
	     */
		public function fault(info:Object) : void
		{
			var fault:FaultEvent = info as FaultEvent;
			Log.getLogger("@namespace@.commands.@sequence@Command")..error("fault", fault);
		}
	}
}
16
Sep

Add graphic to an existing Flex compoenent

Sometimes you need to add an arrow or other graphics elements into an existing Flex components. Here’s an example that shows you how to add an arrow to your component.

Add an arrow graphic to an existing Flex compoenent

Add an arrow graphic to an existing Flex compoenent


<mx:Script>
    <![CDATA[
        import mx.core.UIComponent;
       private static const ARROW_WIDTH:Number = 20;
       private static const ARROW_HEIGHT:Number = 20; 

       private function drawArrow(component:UIComponent):void
       {
            var arrow:UIComponent = new UIComponent();
            var arrowGraphics:Graphics = arrow.graphics;
            arrowGraphics.lineStyle(0,0,0);
            arrowGraphics.beginFill(component.getStyle("borderColor") , 1);              

            // draw arrow
            arrowGraphics.moveTo(component.x+((component.width - ARROW_WIDTH)/2), component.y + component.height);
            arrowGraphics.lineTo(component.x+(component.width /2), component.y + component.height + ARROW_HEIGHT);
            arrowGraphics.lineTo(component.x+((component.width + ARROW_WIDTH)/2), component.y + component.height);
            arrowGraphics.lineTo(component.x+((component.width - ARROW_WIDTH)/2), component.y + component.height);
            arrowGraphics.endFill();
           this.addChild(arrow);
       }
   ]]>
</mx:Script>

<mx:Canvas id="canvas" width="100" height="100"
    borderColor="#FFFFFF" x="100" y="100" initialize="drawArrow(canvas)"
    borderThickness="5" backgroundColor="white"> 

    <mx:Text
        color="black"
        fontWeight="bold"
        selectable="false"
        fontSize="15"
        paddingLeft="25" paddingTop="25">
        <mx:htmlText>
            <![CDATA[Hello<br/>World]]>
        </mx:htmlText>
    </mx:Text>
</mx:Canvas>
25
Jul

Create an FLV thumbnail image from VideoDisplay during runtime in Flex

Here’s a Little trick that shows you how to generate an image thumbnail during runtime from a VideoDisplay component, you can than create a server side proxy to save the image as a file or just use it as it is. Enjoy.


    <mx:Script>
        <![CDATA[
			import mx.events.VideoEvent;

			private function playheadUpdateHandler(event:VideoEvent):void {

			    var bmData:BitmapData = new BitmapData(100, 100);
			    bmData.draw(event.target as DisplayObject);

			    var bm:Bitmap = new Bitmap(bmData);
			    img.source = bm;
			}
        ]]>
    </mx:Script>

    <mx:Canvas>

		<mx:VideoDisplay id="videoDisplay"
			source="someFlvVideo.flv"
			playheadUpdate="playheadUpdateHandler(event); event.target.stop();"
			visible="false" width="100" height="100" />
		<mx:Image id="img" />
    </mx:Canvas>
12
Jun

Remove border from TextInput or DateField component

If you ever tried to remove the border from text input components such as TextInput or DateField you will find that whatever you do you cannot remove a line that look like a border from your top border. Anything you try such as:

dropShadowColor : “0xFFFFFF”;
dropShadowEnabled : “false”;
border-thickness-bottom : 0;
border-thickness-top : 0;
border-thickness-left : 0;
border-thickness-right : 0;

Or directly on the component such as;

borderColor=”white” borderThickness=”0″

You just can’t get the fu#$%$ borders off! The reason is that flex assign a border skin: borderSkin=”mx.skins.halo.HaloBorder” which will always going to leave a line on the top corner.

The solution is actually simple; either use
BorderSkin: Classrefernece(null); in CSS

Or create a skin and don’t draw anything leaving the skin borders empty, that will remove the borders, shadows etc;

package com.skins
{
import mx.skins.Border;

public class TextInputBorderlessSkin extends Border
{
override protected function updateDisplayList(w:Number, h:Number):void
{
super.updateDisplayList(w, h);
}
}
}

Now you can assign the skin in your CSS to your component text input;

.BorderlessTextInput {
    border-skin: ClassReference(”com.skins.TextInputBorderlessSkin”);
}

Play around with skins in Flex, you’ll have a lot of fun!