<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Russ Back &#187; Adobe Flex</title>
	<atom:link href="http://www.russback.com/articles/adobe-flex/feed" rel="self" type="application/rss+xml" />
	<link>http://www.russback.com</link>
	<description>Professional Web Development</description>
	<lastBuildDate>Mon, 02 Nov 2009 08:16:33 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Creating an image asset library</title>
		<link>http://www.russback.com/adobe-flex/creating-an-image-asset-library.html</link>
		<comments>http://www.russback.com/adobe-flex/creating-an-image-asset-library.html#comments</comments>
		<pubDate>Thu, 27 Aug 2009 16:38:10 +0000</pubDate>
		<dc:creator>Russ</dc:creator>
				<category><![CDATA[Adobe Flex]]></category>

		<guid isPermaLink="false">http://www.russback.com/?p=564</guid>
		<description><![CDATA[Ever had those perplexing errors where Flex Builder refuses to compile image assets into your project even though you've instantiated them? Create an asset library and you'll never have that problem again...]]></description>
			<content:encoded><![CDATA[<h2>The problem</h2>
<p>When you compile your Flex projects there will come a time when you realise that some classes just aren&#8217;t getting compiled into the bin-release folder, perhaps because you have some conditional ActionScript code that instantiates a class according to some logic and the Flex compiler assumes that your class isn&#8217;t required.</p>
<p>This is an annoying quirk of the compiler and there are a common workaround is to instantiate a &#8216;dummy&#8217; instance of one of these uncompiled classes to ensure that it gets included. I prefer to avoid this by creating an external asset library that compiles into its own SWC library file as follows&#8230;</p>
<h2>Creating a Library project</h2>
<p>A Flex Library project can be created in the same way as any other project: just choose Flex Library Project in the New menu instead of Flex Project.</p>
<p><img src="/wp-content/uploads/asset-library-create-library-project.gif" width="553" height="182" alt="Creating a new Flex Library project" /></p>
<p> At first glance nothing has changed other than the icon in the Flex Navigator view (shown below) but the benefit of this approach will become apparent very shortly.</p>
<p><img src="/wp-content/uploads/asset-library-flex-navigator-view.gif" width="553" height="292" alt="Creating a new Flex Library project" /></p>
<h2>Create a Class</h2>
<p>First we need to create at least one class. For this example I&#8217;ve chosen to use the excellent <a href="http://www.famfamfam.com/lab/icons/silk/">FamFamFam Silk Icon library</a> &#8211; a collection of 700+ 16px x 16px images that are used for many online interfaces. For this article we&#8217;ll add all the icons from this library to our Flex Library Project and then expose two of them for use in an external application.</p>
<h3>Import the assets</h3>
<p>This is easy &#8211; just download the icon library, extract it and drag all of the images into the Library Project. For my example these live at /assets/images/famfamfam/silkicons/. They can live anywhere but this structure makes it easy it easy to add assets from other sources to our library.</p>
<h3>Exposing the assets</h3>
<p>For this example we just need two of the icons and to expose these we create a new class called IconLibrary (mine&#8217;s in the package com.russback). This is a straight-forward bindable class that has a public static constant of type Class for each of the assets we want to expose:</p>
<pre>package com.russback
{
	/**
	 * Class containing constants for each icon image available for use in the application
	 */
	[Bindable]
	public final class IconLibrary
	{

		/**
		 * Displays the <b>accept</b> icon from the FamFamFam Silk Icons library
		 */
		[Embed(source="assets/images/famfamfam/silkicons/accept.png")]
		public static const ACCEPT:Class;

		/**
		 * Displays the <b>bomb</b> icon from the FamFamFam Silk Icons library
		 */
		[Embed(source="assets/images/famfamfam/silkicons/bomb.png")]
		public static const BOMB:Class;

		/**
		 * Constructor
		 */
		public function IconLibrary()
		{
		}

	}
}</pre>
<h3>Compiling the Library</h3>
<p>Now all we need to do is compile the Library and this is where the benefit of using this approach kicks in. If you right-click on the Flex Library Project in the Flex Navigator view and choose Properties, you&#8217;ll get your compiler options. Click on Flex Library Build Path and you&#8217;ll see a view with a button bar (Classes, Assets, Source path, Library path). In the Classes view you can select which classes you want the compiler to compile into the library. The beauty of this is that you take control &#8211; the compiler will compile whatever you choose regardless of whether you&#8217;ve used the class anywhere so we go ahead and make sure our IconLibrary class gets included.</p>
<p><img src="/wp-content/uploads/asset-library-include-classes.gif" width="553" height="257" alt="Choosing classes to compile" /></p>
<p>Next, click on the Assets button and make sure that <strong>all</strong> the images in the library are included. We could just include the two assets we&#8217;re exposing and that would create a very small SWC file but the great thing about SWC files is that only the classes and assets it references will get included in any release build (which paradoxically caused the initial problem we&#8217;re solving&#8230;). So as we only have two references to these assets (in our IconLibrary class) we know don&#8217;t need to worry about our SWC footprint.</p>
<p><img src="/wp-content/uploads/asset-library-include-assets.gif" width="553" height="267" alt="Choosing assets to compile" /></p>
<p>I should at this point credit <a href="http://www.ronaldferguson.net/">Ronald Ferguson</a> for this as he has already walked this path and his <a href="http://www.ronaldferguson.net/freestuff/37-projects/67-silkflex.html?showall=1">free library</a> works great. It has constants for every icon in the library; however this creates a large SWC file and with 700+ icons in the library, it&#8217;s hard to justify this footprint. The trade off is that every time you want to use an icon that&#8217;s not referenced in the IconLibrary class we need to go back to it and add a new constant.</p>
<p>I&#8217;ve used the Silk Icon library as an example here but you could easily extend this Library to include other image sets as required; the approach is exactly the same, just make sure that any new class you add to the Library project gets compiled by following the steps above.</p>
<h2>Linking to  the library in an external application</h2>
<p>So we now have a library that by default will be compiled to a SWC file in the bin directory of our Library Project. To use that SWC library file in any other Flex Project we just need to reference it in each project as follows</p>
<ol>
<li>Right-click on the project in the Flex Navigator view and choose <strong>Properties</strong></li>
<li>Click on <strong>Flex Build Path</strong> and then hit the <strong>Library path</strong> button</li>
<li>Click the <strong>Add SWC&#8230;</strong> button and navigate to the SWC file your in your Library Project&#8217;s bin directory and hit <strong>Open</strong></li>
<li>You should now have your SWC referenced as the screenshot below shows</li>
</ol>
<p><img src="/wp-content/uploads/asset-library-swc-reference.gif" width="553" height="292" alt="External SWC lib file referenced" /></p>
<h2>Using the Library</h2>
<p>Using the Library couldn&#8217;t be any easier: We simply bind the source property of an Image class to the constant in the Library that we want to use:</p>
<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;mx:Application
	xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
	layout=&quot;vertical&quot;
	width=&quot;553&quot;
	height=&quot;200&quot;
	viewSourceURL=&quot;srcview/index.html&quot;
	&gt;
	&lt;mx:Script&gt;
		&lt;![CDATA[
			import com.russback.IconLibrary;
		]]&gt;
	&lt;/mx:Script&gt;

	&lt;mx:HBox&gt;
		&lt;mx:Image source=&quot;{IconLibrary.BOMB}&quot; /&gt;
		&lt;mx:Text text=&quot;Add images inline?&quot; /&gt;
	&lt;/mx:HBox&gt;

	&lt;mx:HBox&gt;
		&lt;mx:Image source=&quot;{IconLibrary.ACCEPT}&quot; /&gt;
		&lt;mx:Text text=&quot;Use an external image library?&quot; /&gt;
	&lt;/mx:HBox&gt;

&lt;/mx:Application&gt;</pre>
<p>You can download and edit the source code for the <a href="/wp-content/examples/creating-an-image-asset-library/srcview/creating-an-image-asset-library.zip">example application</a> and also the <a href="/wp-content/examples/creating-an-image-asset-library/ImageAssetLibrary.zip">example Library</a>, You can also right-click on the demo below and choose View Source to see how it all fits together.</p>
<p><script type="text/javascript">
		var vars = {};    
		var params = {
			base: "."
			};
		swfobject.embedSWF("http://www.russback.com/wp-content/examples/creating-an-image-asset-library/main.swf", "example", "553", "200", "10.0.0", "expressInstall.swf", vars, params);
	    </script></p>
<div class="flash_content" id="example">
<p>You need Flash Player 10 to view this content. You can <a href="http://get.adobe.com/flashplayer/" title="Visit adobe.com">download this for free</a> from the Adobe website. If you&#8217;re using a feed reader you could <a href="http://www.russback.com/adobe-flex/creating-an-image-asset-library.html">try loading this post in your web browser</a>.</p>
</p></div>
<p> Using this method might seem like a pain at first but it keeps your code clean, your assets in one manageable location<br />
, and you can say goodbye to those compiler problems. </p>
<h2>One last note on compiler errors</h2>
<p>Using this method you may find you get a compiler warning for each constant when you compile the Library, particularly if you <a href="/adobe-flex/compiling-documentation-with-ant-and-asdoc.html">compile documentation using Ant and asdoc</a>. </p>
<p><img src="/wp-content/uploads/ant-build-warning.gif" alt="Ant build warning" /></p>
<p>There is nothing to worry about here; the compiler is simply telling you that you haven&#8217;t created an instance of the constant. If you want to get rid of these completely, you can add an additional line to the build.xml file used by Ant and your compiler will run happily silent:</p>
<pre>&lt;arg line=&quot;-warn-const-not-initialized=false&quot; /&gt;</pre>
<p><img src="/wp-content/uploads/ant-build-successful.gif" alt="Ant build successful" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.russback.com/adobe-flex/creating-an-image-asset-library.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Compiling documentation with Ant and asdoc</title>
		<link>http://www.russback.com/adobe-flex/compiling-documentation-with-ant-and-asdoc.html</link>
		<comments>http://www.russback.com/adobe-flex/compiling-documentation-with-ant-and-asdoc.html#comments</comments>
		<pubDate>Fri, 21 Aug 2009 07:46:03 +0000</pubDate>
		<dc:creator>Russ</dc:creator>
				<category><![CDATA[Adobe Flex]]></category>
		<category><![CDATA[Ant]]></category>
		<category><![CDATA[asdoc]]></category>

		<guid isPermaLink="false">http://www.russback.com/?p=548</guid>
		<description><![CDATA[The documention tool in Flex - asdoc - is a great tool for documenting your code but getting it running isn't the easiest task. I had a few problems with this on Mac OSX Leopard 10.5.8 so hopefully this will help you if you're struggling.]]></description>
			<content:encoded><![CDATA[<h2>Documenting code for asdoc</h2>
<p>Documenting your code for asdoc is easy and there&#8217;s plenty of help available on this and I&#8217;d suggest starting with the <a href="http://livedocs.adobe.com/flex/3/html/help.html?content=asdoc_2.html">Flex help</a>.</p>
<h2>Installing Ant</h2>
<p>You can run asdoc from the command line but I found it much easier to install Ant in Flex Builder, which is as simple as this:</p>
<ol>
<li>In Flex Builder  go to Help &gt; Software Updates &gt; Find and Install</li>
<li>Click on the option to <strong>Search for new features to install</strong></li>
<li>Make sure <strong>The Eclipse Project Updates</strong> is selected and then hit Finish</li>
<li>Expand the tree <strong>Eclipse 3.3.2 or newer,</strong> select <strong>Eclipse Java Development Tools</strong> and install</li>
<li>Restart Flex Builder and then go to Window &gt; Other Views</li>
<li>Expand the <strong>Ant</strong> directory, click on the <strong>Ant</strong> icon and hit OK</li>
<li>You should now have an Ant panel, though the position of it may vary according to your perspective settings (mine is alongside Console at the bottom)</li>
</ol>
<p><img src="/wp-content/uploads/ant-installed.jpg" width="553" height="173" alt="Ant installed" /></p>
<h2>Create a symbolic link to asdoc</h2>
<p>A copy of asdoc lives in each SDK directory so if you&#8217;re using 3.3.0, you&#8217;ll find it at  /Applications/Adobe Flex Builder 3/sdks/3.3.0/bin/asdoc. We&#8217;ll be using Ant to build our documentation and giving it the path to the asdocs progrm but asdoc has a problem with spaces in pathnames, which although not a problem on Windows, is a pain on Mac as the path above has spaces in it and attempting to use this in Ant throws an error. I first tried <a href="http://thanksmister.com/?p=87">the approach in this excellent article</a> but still had the same problem so instead I created a symbolic link (shortcut) to asdoc in my hard disc root.</p>
<p>You can do this in a number of ways, the easiest of which is perhaps using this <a href="http://www.macupdate.com/info.php/id/10433">little plugin</a>. </p>
<p><img src="/wp-content/uploads/symbolic-linker.jpg" width="553" height="299" alt="Symbolic Linker" /></p>
<p>Once you&#8217;ve created your symobolic link, name it something obvious with no funny characters. Mine is flex-sdk-330. When you click on this symbolic link in the Finder you&#8217;ll see the contents of the 3.3.0 directory and inside that, the bin directory and asdoc program. So far so good.</p>
<p><img src="/wp-content/uploads/symbolic-link.jpg" width="553" height="229" alt="Symbolic Linker" /></p>
<h2>Create the Ant  files</h2>
<p>To compile our documentation we need an XML file called build.xml and a properties file called build.properties so we create these in the root of our Flex Project. If Ant has installed properly you&#8217;ll probably see a little Ant icon on your file. </p>
<p><img src="/wp-content/uploads/ant-files.jpg" width="553" height="262" alt="Ant files" /></p>
<h3>The build.properties file</h3>
<p>The properties file contains a set of values that the XML file will use. </p>
<p>We start with a reference to the symbolic link we created earlier.</p>
<pre># Path to SDK
SDK_PATH = /flex-sdk-330</pre>
<p> Then we add something very important: the path to the Flash player we are using for this project. Setting the target player in Flex Builder will only tell the Flex compiler to target a specific player but Ant won&#8217;t know about that so if you&#8217;re targetting version 10, make sure you reference the version 10 player here.</p>
<p>One problem you may find if you don&#8217;t do this is you end up with compile errors. One that I got tripped up by was an error to do with the FileReference class. This was changed in Flash player 10 to include the ability to load files from the user&#8217;s environment without the need to load them to a server first. If you get errors to do with FileReference, make sure you have this set correctly.</p>
<pre># Path to target Flash Player library (relative to the SDK_PATH
PLAYER_PATH = /frameworks/libs/player/10/playerglobal.swc</pre>
<p>The next property is where you reference any SWC library files your project uses. In the example I&#8217;m providing for download below I&#8217;m not including any so this is just blank:
</p>
<pre># Paths to libraries to include
# LIBRARIES = ./libs/SomeLibrary.swc ./libs/SomeOtherLibrary.swc
LIBRARIES = </pre>
<p>Next comes the path the the source files for the project, which are typically in the src directory:
</p>
<pre># Source files
SOURCE = ./src</pre>
<p>The next two settings are used for the documentation output &#8211; the TITLE appears in the title of the documents and the FOOTER text appears at the bottom of each page.</p>
<pre>
# Title for the documentation
TITLE = Compiling Documentation with Ant and asdoc</pre>
<pre># Text to add to the footer of each page
FOOTER = Compiled using Ant and asdoc (build.xml and build.properties)</pre>
<p>Finally we have a location to output our documentation to, in this case a directory called docs in the Flex Project:
</p>
<pre># Output location
OUTPUT_PATH = ./docs</pre>
<h2>The build.xml file</h2>
<p>Now we have our properties file we can go ahead and use them in our XML file. The properties file is referenced right at the outset and then we include a path to the flexTasks.jar file (note the properties throughout this file are called in as follows ${PROPERTY}).</p>
<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;project name=&quot;Compiling Documentation with Ant and asdoc&quot; default=&quot;Clean and Build&quot; basedir=&quot;.&quot;&gt;

	&lt;property file=&quot;./build.properties&quot; /&gt;

	&lt;!-- Path to Flex Ant Tasks (info at http://labs.adobe.com/wiki/index.php/Flex_Ant_Tasks) --&gt;
	&lt;taskdef resource=&quot;flexTasks.tasks&quot; classpath=&quot;${SDK_PATH}/ant/lib/flexTasks.jar&quot; /&gt;</pre>
<p>Next we have our default Ant task which simply calls the two other tasks in the file Clean, and Build.
</p>
<pre>	&lt;target name=&quot;Clean and Build&quot; description=&quot;Calls the Clean and Build tasks&quot;&gt;
		&lt;antcall target=&quot;Clean&quot; description=&quot;Calls the Clean task&quot; /&gt;
		&lt;antcall target=&quot;Build&quot; description=&quot;Calls the Build task&quot; /&gt;
	&lt;/target&gt;</pre>
<p>This is followed by a simple task that deletes the existing documentation if there is any:</p>
<pre>	&lt;target name=&quot;Clean&quot; description=&quot;Deletes the existing documentation and recreates the directory&quot;&gt;
		&lt;delete dir=&quot;${OUTPUT_PATH}&quot; failOnError=&quot;true&quot; includeEmptyDirs=&quot;true&quot; /&gt;
		&lt;mkdir dir=&quot;${OUTPUT_PATH}&quot;/&gt;
		&lt;echo&gt;Clean task completed successfully&lt;/echo&gt;
	&lt;/target&gt;
</pre>
<p>And finally the task that will build our documentation:</p>
<pre>	&lt;target name=&quot;Build&quot; description=&quot;Builds the documentation&quot;&gt;
		&lt;exec executable=&quot;${SDK_PATH}/bin/asdoc&quot; failonerror=&quot;true&quot;&gt;
			&lt;arg line=&quot;-load-config ${SDK_PATH}/frameworks/flex-config.xml&quot; /&gt;
			&lt;arg line=&quot;-doc-sources ${SOURCE}&quot; /&gt;
			&lt;arg line=&quot;-source-path ${SOURCE}&quot; /&gt;
			&lt;arg line=&quot;-external-library-path ${SDK_PATH}/${PLAYER_PATH}&quot; /&gt;
			&lt;arg line=&quot;-include-libraries ${LIBRARIES}&quot; /&gt;
			&lt;arg line=&quot;-window-title '${TITLE}'&quot; /&gt;
			&lt;arg line=&quot;-footer '${FOOTER}'&quot; /&gt;
			&lt;arg line=&quot;-output ${OUTPUT_PATH}&quot;/&gt;
		&lt;/exec&gt;
		&lt;echo&gt;Build taks completed successfully&lt;/echo&gt;
	&lt;/target&gt;

&lt;/project&gt;</pre>
<h2>Compile the documentation </h2>
<p>Now everything is set up we simply need to drag the build.xml file onto the Ant panel and double-click on it or hit the Play button in the Ant panel.</p>
<p><img src="/wp-content/uploads/ant-ready.jpg" width="553" height="131" alt="Ant ready to run" /></p>
<p> If everything is set up correctly we should get a couple of confirmation messages in the Console panel and the documentation will be created in a /docs directory in the root of our Flex Project.</p>
<p><img src="/wp-content/uploads/ant-done.jpg" width="553" height="239" alt="Ant done" /></p>
<h2>Download an example project</h2>
<p>To see an example in action you can  <a href="/wp-content/examples/compiling-documentation-with-ant-and-asdoc/compiling-documentation-with-ant-and-asdoc.zip">download and edit the source code</a> here. This should work if you follow the steps above but obviously can be modified as required.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.russback.com/adobe-flex/compiling-documentation-with-ant-and-asdoc.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Disabling drag on an AdvancedDataGrid row</title>
		<link>http://www.russback.com/adobe-flex/disabling-drag-on-an-advanceddatagrid-row.html</link>
		<comments>http://www.russback.com/adobe-flex/disabling-drag-on-an-advanceddatagrid-row.html#comments</comments>
		<pubDate>Tue, 18 Aug 2009 20:30:09 +0000</pubDate>
		<dc:creator>Russ</dc:creator>
				<category><![CDATA[Adobe Flex]]></category>
		<category><![CDATA[AdvancedDataGrid]]></category>
		<category><![CDATA[Drag/Drop]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://www.russback.com/?p=539</guid>
		<description><![CDATA[Basic drag and drop in Flex is a breeze but creating custom behaviour and data management can sometimes be tricky. This article explains how to enable or disable drag on each individual row of an AdvancedDataGrid.]]></description>
			<content:encoded><![CDATA[<p>Drag and drop using an AdvancedDataGrid is just a case of setting a few properties (dragEnabled, dropEnabled are two of these) but this makes every row of your datagrid draggable, but what if you only want to enable the copy or move of particular items in the list?</p>
<p>In this article we&#8217;ll make this happen using a shop as an example. We&#8217;ll have a list of products that in the warehouse, and a list of products that are available to buy on the shop floor. To transfer stock from the warehouse to the store we&#8217;ll drag them and drop them from one list to the other but not everything in the warehouse is saleable &#8211; some of it has been recalled for safety reasons so we don&#8217;t want to be able to drag those.</p>
<p>So to start, we&#8217;ll set up a value object class for each of our products.</p>
<h2>The Product value object</h2>
<p>Nothing fancy here, just a name and availability properties and a couple of constants we use for the availability of each Product:</p>
<pre>package com.russback.valueobjects
{
  /**
   * Value Object for a Product, containing a few basic properties
   */
  [Bindable]
  public class Product
  {

    /**
     * Used for Products currently available for sale
     */
    public static const AVAILABLE:String = "productAvailable";

    /**
     * Used for Products that have been recalled due to a fault
     */
    public static const RECALLED:String = "productRecalled";

    /**
     * Name of the Product
     * @default null
     */
    public var name:String;

    /**
     * Current availability status of this Product
     * @default AVAILABLE
     */
    public var availability:String = AVAILABLE;  

    /**
     * Constructor
     */
    public function Product()
    {
    }

  }
}</pre>
<h2>Extending the AdvancedDataGrid</h2>
<p>Next we need somewhere to display each of Products and for this example I&#8217;m using the AdvancedDataGrid. This approach could equally apply to a List but the AdvancedDataGrid is something I tend to use time and again so I&#8217;m using this one here.</p>
<p>Our extended object is called ExtendedAdvancedDataGrid (pretty unimaginative to be fair) and it begins with the usual imports and a constructor that simply invokes the constructor of the super class:</p>
<pre>package com.russback.extensions
{
  import com.russback.valueobjects.Product;

  import mx.controls.AdvancedDataGrid;
  import mx.core.DragSource;
  import mx.core.IUIComponent;
  import mx.events.DragEvent;
  import mx.managers.DragManager;

  /**
   * Extends the AdvancedDataGrid to allow for dragging of grid rows depending on data properties
   */
  public class ExtendedAdvancedDataGrid extends AdvancedDataGrid
  {

    /**
     * Constructor adds creation complete event listener
     */
    public function ExtendedAdvancedDataGrid()
    {
      super();
    }</pre>
<p>Next we override the default dragStart() method of the super class. First we create a new Array object and then for each item the user has selected and dragged, we check if it&#8217;s availability property is AVAILABLE and if so, add it to our array.</p>
<p>Then if we have any data in our Array, we create a new DragSource object containing our array data and create a drag proxy that will indicate to the user which items are being dragged (we&#8217;ll look at this shortly). Finally we call the DragManager&#8217;s doDrag() method, passing it this as the drag initiator, our DragSource, event and drag proxy.</p>
<p>This approach allows you to select any row in the list but only those Products that are available will actually be added to the DragManager to move or copy.</p>
<pre>    /**
     * Only adds product to the drag if they are available
     * Uses an instance of the CustomDragProxy class as it's drag proxy image
     */
    override protected function dragStartHandler(event:DragEvent):void
    {
      var dragData:Array = new Array();

      for each (var product:Product in this.selectedItems)
      {
        if (product.availability == Product.AVAILABLE)
        {
          dragData.push(product);
        }
      }

      if (dragData.length)
      {

        var dragSource:DragSource = new DragSource();
            dragSource.addData( dragData, "items" );

        var customDragProxy:ExtendedAdvancedDataGridDragProxy = new ExtendedAdvancedDataGridDragProxy();
            customDragProxy.owner = this;

        DragManager.doDrag(this as IUIComponent, dragSource, event, customDragProxy);

      }
    }</pre>
<p>Our final two methods in this class override the dragDrop() and dragComplete() methods. The AdvancedDataGrid moves data from source and target objects out of the box but we typically don&#8217;t want to do this in a large application where a framework such as Cairngorm is in place, so all I&#8217;m doing here is effectively preventing that behaviour. In a real world application I&#8217;d fire events in this methods and then handle the data transfer in the controller but for this example we just have a couple of comments.</p>
<pre>    /**
     * Custom drop behaviour. Prevents superclass' default behaviour
     */
    override protected function dragDropHandler(event:DragEvent):void
    {
      // custom code here to respond to a drop - firing an event to handle in an
      // MVC framework could be one example

      hideDropFeedback(event);
    }

    /**
     * Custom drag complete behaviour. Prevents superclass' default behaviour
     */
    override protected function dragCompleteHandler(event:DragEvent):void
    {
      // custom code here to respond to a completed drag - firing an event to handle in an
      // MVC framework could be one example
    }

  }
}</pre>
<h2>Creating a custom drag proxy</h2>
<p>When you create your own dragStart() method and don&#8217;t define a drag proxy, Flex will visualise the drag by creating a box that matches the size of the drag source (ie the AdvancedDataGrid). This works fine but it doesn&#8217;t indicate which items are being dragged and this is important for us as although we can select all the items in our list, we can only drag the Products that are available and therefore we only want to see these in the drag proxy while we&#8217;re dragging.</p>
<p>So for this we have another class that extends the AdvancedDataGridDragProxy class. This starts with a few constants that will be used to configure the proxy. I&#8217;ve set these up as constants just to separate these display properties from the core logic so you could just as easily replace these with public variables that you set when you create a new instance of this class.</p>
<p>The proxy will be a VBox object containing an HBox for each Product in the dragged data. The constants we have are for the width and height of each row and also the X and Y offset which we&#8217;ll use to position the proxy in relation to the mouse cursor during the drag. The last part of this initial section of code is a private variable that we&#8217;ll use to hold the VBox and the constructor.</p>
<pre>package com.russback.extensions
{
  import com.russback.valueobjects.Product;

  import mx.containers.HBox;
  import mx.containers.VBox;
  import mx.controls.AdvancedDataGrid;
  import mx.controls.Image;
  import mx.controls.Text;
  import mx.controls.advancedDataGridClasses.AdvancedDataGridDragProxy;
  import mx.core.ScrollPolicy;

  /**
   * Extends AdvancedDataGridDragProxy to display a proxy of the items that
   * the ExtendedAdvancedDataGrid has allowed to be dragged
   */
  public class ExtendedAdvancedDataGridDragProxy extends AdvancedDataGridDragProxy
  {

    /**
     * Width of each item in the proxy
     * @default 200
     */
    private static const ITEM_WIDTH:int = 200;

    /**
     * Height of each item in the proxy
     * @default 25
     */
    private static const ITEM_HEIGHT:int = 25;

    /**
     * Number of pixels to offset the proxy (against the mouse position) in the horizontal direction
     * @default -10
     */
    private static const MOUSE_X_OFFSET:int = -10;

    /**
     * Number of pixels to offset the proxy (against the mouse position) in the vertical direction
     * @default -10
     */
    private static const MOUSE_Y_OFFSET:int = -10;

    /**
     * VBox used as a wrapper for the items in the proxy
     * @default new VBox()
     */
    private var _vbox:VBox = new VBox();

    /**
     * Constructor
     */
    public function ExtendedAdvancedDataGridDragProxy()
    {
      super();
    }</pre>
<p>Next we ovveride the createChildren() method of the super class to prevent the creation of that box object that the AdvanvedDataGridProxy class creates. First we create a reference to this proxy&#8217;s owner which will be an instance of our ExtendedAdvancedDataGrid class, and then we create a sorted array containing each selected item the user has selected.</p>
<p>Now we have this we can loop through each item and provided the Product is available, we call a method called createRowProxy which we&#8217;ll look at next. This method returns an HBox which we add to our VBox.</p>
<p>Finally we set the width and height of the VBox according to the number of rows we&#8217;ve created, add the VBox to the proxy and then position the proxy in relation to the mouse cursor. -10 for both X and Y constant values works nicely in this example but this is down to your design.</p>
<pre>    /**
     * Grabs the selected items from the ExtendedAdvancedDataGrid, calls the createRowProxy()
     * method for each item that can be dragged and sets the proxy's position in line with
     * the current mouse position
     */
    override protected function createChildren():void
    {

      var grid:AdvancedDataGrid = this.owner as ExtendedAdvancedDataGrid;

      var products:Array = grid.selectedIndices;
          products.sort();

      for (var i:int = 0; i < products.length; i++)
      {
        var product:Product = grid.dataProvider[products[i]] as Product;

        if (product.availability == Product.AVAILABLE)
        {
          _vbox.addChild(createRowProxy(product));
        }
      }

      _vbox.width = ITEM_WIDTH;
      _vbox.height = _vbox.numChildren * ITEM_HEIGHT;
      _vbox.horizontalScrollPolicy = ScrollPolicy.OFF;
      _vbox.verticalScrollPolicy = ScrollPolicy.OFF;

      this.addChild(_vbox);

      this.x = grid.contentMouseX + MOUSE_X_OFFSET;
      this.y = grid.contentMouseY + MOUSE_Y_OFFSET;

    }</pre>
<p>The final method in here is the createRowProxy() method which I mentioned above. Given a Product object, this creates an HBox containing an icon image and the name of the Product and returns the HBox. It's these HBoxes you will see when you drag data from our list.</p>
<pre>    /**
     * Creates an HBox with an Image and text to act as a proxy for each row of
     * dragged data in the proxy object
     * @return An HBox
     */
    private function createRowProxy(product:Product):HBox
    {
      var hBox:HBox = new HBox();
          hBox.horizontalScrollPolicy = ScrollPolicy.OFF;
          hBox.verticalScrollPolicy = ScrollPolicy.OFF;

      var image:Image = new Image();
          image.source = "assets/images/package.png";

      var name:Text = new Text();
          name.text = product.name;

      hBox.addChild(image);
      hBox.addChild(name);

      return hBox;
    }

  }
}</pre>
<h2>An item renderer just for show</h2>
<p>Before we go ahead and use our new classes, I've created an item renderer just to make the example clear. This is a straight-forward MXML component that extends HBox and shows an icon image and the name of the Product (very similar to our drag proxy we created, for obvious reasons). The only thing to note in here is that we use a move  icon for the mouse cursor if you mouseover this object and the Product is draggable. This will indicate to the user that this item can be dragged.</p>
<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;mx:HBox
  xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
  xmlns:valueobjects=&quot;com.russback.valueobjects.*&quot;
  creationComplete=&quot;creationCompleteHandler(event)&quot;
  &gt;

  &lt;mx:Script&gt;
    &lt;![CDATA[
      import com.russback.valueobjects.Product;
      import mx.events.FlexEvent;

      /**
       * ID of the current cursor
       * @default 0
       */
      private var _cursorID:int = 0;

      /**
       * Image to display as cursor to indicate item is draggable
       */
          [Embed(source=&quot;assets/images/arrow-move.png&quot;)]
          private var _cursorClass:Class;

      /**
       * Adds event listeners for MOUSE_OVER and MOUSE_OUT MouseEvents
       */
      private function creationCompleteHandler(event:FlexEvent):void
      {
        this.addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
        this.addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
      }

      /**
       * Sets the cursor to indicate item is draggable
       */
      private function mouseOverHandler(event:MouseEvent):void
      {
        if (data.availability == Product.AVAILABLE)
        {
          _cursorID = cursorManager.setCursor(_cursorClass);
        }
      }

      /**
       * Resets the cursor
       */
      private function mouseOutHandler(event:MouseEvent):void
      {
        cursorManager.removeCursor(_cursorID);
      }

    ]]&gt;
  &lt;/mx:Script&gt;

  &lt;valueobjects:Product id=&quot;data&quot; /&gt;

  &lt;mx:Image
    source=&quot;assets/images/package.png&quot;
    toolTip=&quot;Product available&quot;
    visible=&quot;{data.availability == Product.AVAILABLE}&quot;
    includeInLayout=&quot;{data.availability == Product.AVAILABLE}&quot;
    /&gt;

  &lt;mx:Image
    source=&quot;assets/images/bug.png&quot;
    toolTip=&quot;Product recalled&quot;
    visible=&quot;{data.availability == Product.RECALLED}&quot;
    includeInLayout=&quot;{data.availability == Product.RECALLED}&quot;
    /&gt;

  &lt;mx:Text text=&quot;{data.name}&quot; /&gt;

&lt;/mx:HBox&gt;</pre>
<h2>Putting it all together</h2>
<p>We now have all of our building blocks for the example so we dive into the MXML application. This a very simple application that  has an ArrayCollection containing a set of Product objects, an instance of our ExtendedAdvancedDataGrid class, and then an out-of-the-box AdvancedDataGrid. I've included the latter just to demonstrate that you don't need a custom class as your target.</p>
<p>The first grid (our extended class) lists everything in our warehouse and uses our ProductRenderer component as the itemRenderer for it's only column. The second grid lists everything available in the shop (nothing initially) and has drop enabled. </p>
<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;mx:Application
  xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
  xmlns:valueobjects=&quot;com.russback.valueobjects.*&quot;
  xmlns:extensions=&quot;com.russback.extensions.*&quot;
  layout=&quot;horizontal&quot;
  width=&quot;553&quot;
  height=&quot;300&quot;
  viewSourceURL=&quot;srcview/index.html&quot;
  &gt;

  &lt;mx:Script&gt;
    &lt;![CDATA[
      import com.russback.valueobjects.Product;
    ]]&gt;
  &lt;/mx:Script&gt;

  &lt;mx:ArrayCollection id=&quot;products&quot;&gt;
    &lt;valueobjects:Product name=&quot;Widgets&quot; /&gt;
    &lt;valueobjects:Product name=&quot;Gadgets&quot; /&gt;
    &lt;valueobjects:Product name=&quot;Gizmos&quot; availability=&quot;{Product.RECALLED}&quot; /&gt;
    &lt;valueobjects:Product name=&quot;Buttons&quot; /&gt;
    &lt;valueobjects:Product name=&quot;Wizards&quot; availability=&quot;{Product.RECALLED}&quot; /&gt;
  &lt;/mx:ArrayCollection&gt;

  &lt;extensions:ExtendedAdvancedDataGrid
    width=&quot;100%&quot;
    height=&quot;100%&quot;
    dataProvider=&quot;{products}&quot;
    dragEnabled=&quot;true&quot;
    allowMultipleSelection=&quot;true&quot;
    dropEnabled=&quot;true&quot;
    &gt;
    &lt;extensions:columns&gt;
      &lt;mx:AdvancedDataGridColumn headerText=&quot;Products in Warehouse&quot; itemRenderer=&quot;com.russback.itemrenderers.ProductRenderer&quot; /&gt;
    &lt;/extensions:columns&gt;
  &lt;/extensions:ExtendedAdvancedDataGrid&gt;

  &lt;mx:AdvancedDataGrid
    width=&quot;100%&quot;
    height=&quot;100%&quot;
    dropEnabled=&quot;true&quot;
    &gt;
    &lt;mx:columns&gt;
      &lt;mx:AdvancedDataGridColumn headerText=&quot;Products on Shop Floor&quot; itemRenderer=&quot;com.russback.itemrenderers.ProductRenderer&quot; /&gt;
    &lt;/mx:columns&gt;
  &lt;/mx:AdvancedDataGrid&gt;

&lt;/mx:Application&gt;</pre>
<p><script type="text/javascript">
    var vars = {};    
    var params = {
      base: "."
      };
    swfobject.embedSWF("http://www.russback.com/wp-content/examples/disabling-drag-on-an-advanceddatagrid-row/main.swf", "example", "553", "300", "10.0.0", "expressInstall.swf", vars, params);
      </script></p>
<h2>Example in action</h2>
<p>In the example below you can select multiple items in the warehouse list and drop them in the shop list and they'll be added to the shop list. The drag proxy for the drag should only show those items that are being dragged, which is not necessarily every item you selected before you started the drag.</p>
<p>You can <a href="/wp-content/examples/disabling-drag-on-an-advanceddatagrid-row/srcview/disabling-drag-on-an-advanceddatagrid-row.zip">download and edit the source code</a>, or right-click on the demo below and choose View Source to see how it all fits together.</p>
<div class="flash_content" id="example">
<p>You need Flash Player 10 to view this content. You can <a href="http://get.adobe.com/flashplayer/" title="Visit adobe.com">download this for free</a> from the Adobe website. If you&#8217;re using a feed reader you could <a href="http://www.russback.com/adobe-flex/disabling-drag-on-an-advanceddatagrid-row.html">try loading this post in your web browser</a>.</p>
</div>
<p>In this example we've prevented the dragDrop() and dragComplete() methods so the data doesn't get removed from the warehouse. We'd need to do some more work in our ExtendedAdvancedDataGrid class to do this as already discussed but I've not included that here in order to keep things simple. It's also possible to drag duplicate Products into the shop list, which is the default behaviour for the AdvancedDataGrid so again, we'd need to do some more work in this area to prevent dupes being added but hopefully this article provides enough information to start you on your road to customising your own drag and drop interfaces.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.russback.com/adobe-flex/disabling-drag-on-an-advanceddatagrid-row.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Hiding a Tab in a TabNavigator</title>
		<link>http://www.russback.com/adobe-flex/hiding-a-tab-in-a-tabnavigator.html</link>
		<comments>http://www.russback.com/adobe-flex/hiding-a-tab-in-a-tabnavigator.html#comments</comments>
		<pubDate>Thu, 06 Aug 2009 12:56:50 +0000</pubDate>
		<dc:creator>Russ</dc:creator>
				<category><![CDATA[Adobe Flex]]></category>
		<category><![CDATA[TabNavigator]]></category>
		<category><![CDATA[ViewStack]]></category>

		<guid isPermaLink="false">http://www.russback.com/?p=513</guid>
		<description><![CDATA[This one seems to crop up regularly: how to hide a tab in the TabNavigator's TabBar. The simple option is to create a quick binding...]]></description>
			<content:encoded><![CDATA[<p>You can easily disable a tab by disabling the associated child object in the TabNavigator, which is fair enough. So you might think that altering the child&#8217;s visibile and includeInLayout properties would impact the tab too, but it doesn&#8217;t and that&#8217;s because only the child that&#8217;s currently in view has its visible.	The solution is simply to bind the visibility and includeInLayout properties to another property of the child. The enabled property is a good start but then you&#8217;re saying that all disabled elements are invisible, which you might not want. So we go with a custom property.</p>
<h2>Create a custom property on the child</h2>
<p>This is dead easy. The class below is simply a Box that has a public var added to it that defaults to true, and it&#8217;s this we&#8217;ll use for binding.</p>
<pre>package com.russback
{
	import mx.containers.Box;

	public class ExtendedBox extends Box
	{

		/**
		 * Used for binding the visible and includeInLayout properties
		 * of the TabNavigator
		 */
		[Bindable]
		public var tabVisible:Boolean = true;

		/**
		 * Constructor
		 */
		public function ExtendedBox()
		{
			super();
		}

	}
}</pre>
<h2>Creating the Tab binding </h2>
<p>All we need here is one method that creates the binding. We fire this method once the CREATION_COMPLETE FlexEvent has fird and it&#8217;s job is simply to bind the visibility and includeInLayout properties to the tabVisible variable we created in our custom Box:</p>
<pre>package com.russback
{
	import flash.display.DisplayObject;

	import mx.binding.utils.BindingUtils;
	import mx.containers.TabNavigator;
	import mx.controls.Button;
	import mx.events.FlexEvent;

	public class ExtendedTabNavigator extends TabNavigator

	{

		/**
		 * Constructor adds event listener
		 */
		public function ExtendedTabNavigator()
		{
			super();
			addEventListener(FlexEvent.CREATION_COMPLETE, createTabBindings);
		}

		/**
		 * event handler binds each tab's visible and inludeInLayout properties to the
		 * custom "tabVisible" property of the related child
		 */
		private function createTabBindings(event:FlexEvent):void
		{
			for (var i:uint; i < childDescriptors.length; i++)
			{
				var tab:Button = getTabAt(i);
				var child:DisplayObject = getChildAt(i);

				BindingUtils.bindProperty(tab, "visible", child, "tabVisible");
				BindingUtils.bindProperty(tab, "includeInLayout", child, "tabVisible");
			}
		}

	}
}</pre>
<h2>Putting it all together</h2>
<p>The MXML for this is simple. We simply create an instance of our ExtendedTabNavigator and populate it with some child objects, which are ExtendedBox objects. We can then set the visibility of each associated Tab by setting the tabVisible property on each.</p>
<p>The example below shows the four states you could have:</p>
<ol>
<li>Enabled and tab visible</li>
<li>Enabled and tab hidden</li>
<li>Disabled and tab hidden</li>
<li>Disabled and tab visible</li>
</ol>
<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;mx:Application
	xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
	xmlns:russback=&quot;com.russback.*&quot;
	layout=&quot;absolute&quot;
	width=&quot;553&quot;
	height=&quot;320&quot;
	viewSourceURL=&quot;srcview/index.html&quot;
	&gt;

	&lt;russback:ExtendedTabNavigator width=&quot;100%&quot; height=&quot;100%&quot;&gt;
		&lt;russback:ExtendedBox label=&quot;1: Enabled and tab visible&quot; /&gt;
		&lt;russback:ExtendedBox label=&quot;2: Enabled and tab hidden&quot; tabVisible=&quot;false&quot; /&gt;
		&lt;russback:ExtendedBox label=&quot;3: Disabled and tab hidden&quot; enabled=&quot;false&quot; tabVisible=&quot;false&quot; /&gt;
		&lt;russback:ExtendedBox label=&quot;4: Disabled and tab visible&quot; enabled=&quot;false&quot; /&gt;
	&lt;/russback:ExtendedTabNavigator&gt;

&lt;/mx:Application&gt;</pre>
<p><script type="text/javascript">
		var vars = {};    
		var params = {
			base: "."
			};
		swfobject.embedSWF("http://www.russback.com/wp-content/examples/hiding-a-tab-in-a-tabnavigator/main.swf", "example", "553", "320", "9.0.0", "expressInstall.swf", vars, params);
	    </script></p>
<p>You can <a href="/wp-content/examples/hiding-a-tab-in-a-tabnavigator/srcview/hiding-a-tab-in-a-tabnavigator.zip">download and edit the source code</a>, or right-click on the demo below and choose View Source to see how it all fits together.</p>
<div class="flash_content" id="example">
<p>You need Flash Player 10 to view this content. You can <a href="http://get.adobe.com/flashplayer/" title="Visit adobe.com">download this for free</a> from the Adobe website. If you&#8217;re using a feed reader you could <a href="http://www.russback.com/adobe-flex/hiding-a-tab-in-a-tabnavigator.html">try loading this post in your web browser</a>.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.russback.com/adobe-flex/hiding-a-tab-in-a-tabnavigator.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Preventing click events on a Flex Accordion header</title>
		<link>http://www.russback.com/adobe-flex/preventing-click-events-on-a-flex-accordion-header.html</link>
		<comments>http://www.russback.com/adobe-flex/preventing-click-events-on-a-flex-accordion-header.html#comments</comments>
		<pubDate>Fri, 31 Jul 2009 10:07:43 +0000</pubDate>
		<dc:creator>Russ</dc:creator>
				<category><![CDATA[Adobe Flex]]></category>
		<category><![CDATA[accordion]]></category>
		<category><![CDATA[events]]></category>

		<guid isPermaLink="false">http://www.russback.com/?p=496</guid>
		<description><![CDATA[Intercepting Flex's Accordion navigation isn't something that the Accordion provides out of the box, but with a few simple classes it's easy to prevent clicks, prompt for confirmation, or whatever else you need to do...]]></description>
			<content:encoded><![CDATA[<p>Flex takes care of switching the views in an Accordion when you click on the bars of the Accordion, but what if you want to detect that user activity and do something else? Maybe you want to disable the navigation if a form inside one of the accordion children has failed validation, or you want a user to confirm they don&#8217;t want to save the changes they&#8217;ve made in that form. </p>
<p>Below are two examples to achieve this. For both examples, we&#8217;ll simply enable and disable each item in the Accordion, which will enable or disable the navigation of the Accordion as appropiate.</p>
<h2>Understanding the Accordion</h2>
<p>Both of these examples make use of the Accordion&#8217;s headerRenderer class to achieve what we&#8217;re looking for. The default for an Accordion is a Button class and as Button is a subclass of Container, we know that it has a property called data which is a reference to the related object. In the case of the Accordion that related object is the child object you add to the Accordion. In other words if you add one VBox to an Accordion, that VBox is referenced in the data property of the header bar that appears in the Accordion.</p>
<p>A common way to disable a view is to set the enabled property to false, so what we&#8217;ll doing in both examples is setting the enabled property of each child object of the Accordion and our headerRenderer will follow suit. To test this I&#8217;ve created a little class just to toggle the enabled property of an object on click:</p>
<pre>package com.russback.examples
{
	import flash.events.MouseEvent;

	import mx.controls.Button;
	import mx.core.Container;

	public class ExampleButtonControl extends Button
	{

		/**
		 * Target container linked to this ExampleButtonControl
		 */
		public var target:Container;

		/**
		 * Constructor
		 */
		public function ExampleButtonControl()
		{
			super();
		}

		/**
		 * Toggles the enabled property of the target Container
		 */
		override protected function clickHandler(event:MouseEvent):void
		{
			super.clickHandler(event);

			target.enabled = ! target.enabled;
		}

	}
}</pre>
<h2>Example 1: using BindingUtils</h2>
<p>The first example is simple: we just need to bind the enabled property of each header to the related Accordion child so we have a class that extends the Button control. This overrides the default createChildren() method to bind the enabled property of the Button to the enabled property of it&#8217;s data object:</p>
<pre>package com.russback
{
	import flash.events.MouseEvent;

	import mx.binding.utils.BindingUtils;
	import mx.controls.Button;

	public class BoundAccordionHeader extends Button
	{
		/**
		 * Constructor
		 */
		public function BoundAccordionHeader()
		{
			super();
		}

		/**
		 * Overrides default createChild() method
		 * Binds the enabled property to the data's enabled property
		 */
		override protected function createChildren():void
		{
			super.createChildren();

			BindingUtils.bindProperty(this, "enabled", data, "enabled");
		}

	}
}</pre>
<h3>Example 1 in action</h3>
<p>The MXML for this couldn&#8217;t be simpler. We simply create an Accordion and set it&#8217;s headerRenderer property to be our BoundAccordionHeader class. The only other objects in this example are three of our ExampleButtonControl objects that simply toggle the enabled state of each child in the Accordion. Job done.</p>
<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;mx:Application
	xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
	xmlns:russback=&quot;com.russback.*&quot;
	layout=&quot;vertical&quot;
	viewSourceURL=&quot;srcview/index.html&quot;
	&gt;

	&lt;mx:HBox width=&quot;100%&quot;&gt;
		&lt;russback:ExampleButtonControl label=&quot;Toggle Child 1&quot; target=&quot;{child1}&quot; /&gt;
		&lt;russback:ExampleButtonControl label=&quot;Toggle Child 2&quot; target=&quot;{child2}&quot; /&gt;
		&lt;russback:ExampleButtonControl label=&quot;Toggle Child 3&quot; target=&quot;{child3}&quot; /&gt;
	&lt;/mx:HBox&gt;

	&lt;mx:Accordion height=&quot;100%&quot; width=&quot;100%&quot; headerRenderer=&quot;com.russback.BoundAccordionHeader&quot; &gt;
		&lt;mx:VBox id=&quot;child1&quot; label=&quot;Child 1&quot; /&gt;
		&lt;mx:VBox id=&quot;child2&quot; label=&quot;Child 2&quot; /&gt;
		&lt;mx:VBox id=&quot;child3&quot; label=&quot;Child 3&quot; /&gt;
	&lt;/mx:Accordion&gt;

&lt;/mx:Application&gt;</pre>
<p><script type="text/javascript">
		var vars = {};    
		var params = {
			base: "."
			};
		swfobject.embedSWF("http://www.russback.com/wp-content/examples/preventing-click-on-an-accordion-header-1/main.swf", "example", "553", "320", "9.0.0", "expressInstall.swf", vars, params);
	    </script></p>
<p>You can <a href="/wp-content/examples/preventing-click-events-on-an-accordion-header/srcview/preventing-click-on-an-accordion-header-1.zip">download and edit the source code</a>, or right-click on the demo below and choose View Source to see how it all fits together.</p>
<div class="flash_content" id="example">
<p>You need Flash Player 10 to view this content. You can <a href="http://get.adobe.com/flashplayer/" title="Visit adobe.com">download this for free</a> from the Adobe website. If you&#8217;re using a feed reader you could <a href="http://www.russback.com/adobe-flex/preventing-click-events-on-an-accordion-header.html">try loading this post in your web browser</a>.</p>
</div>
<h2>Example 2: Events</h2>
<p>Example 1 is great if you just need a simple binding but what if you need to handle those changes to the enabled property? This next example uses a custom event class to enable you to handle events at the Accordion level. A use for this might be to have the Accordion enabled but only to allow navigation in certain circumstances, such as if a form in one of the child objects has been validated successfully.</p>
<h3>A custom event</h3>
<p>For this example I&#8217;ve created a custom event, called AccordionHeaderEvent. This is a simple extension of the Event class that has a static constant for the event type and a container property. We&#8217;ll fire one of these events each time an Accordion child changes it&#8217;s enabled property and use the event&#8217;s container property to hold a reference to the child object involved.</p>
<pre>package com.russback.events
{
	import flash.events.Event;

	import mx.core.Container;

	public class AccordionHeaderEvent extends Event
	{

		/**
		 * Event types
		 */
		public static const UPDATE_HEADER:String = "accordionHeaderEventUpdateHeader";

		/**
		 * Container object associated with this event
		 * NB event bubbles and can be cancelled
		 */
		public var container:Container;

		/**
		 * Constructor sets this event's container property
		 */
		public function AccordionHeaderEvent(type:String, container:Container, bubbles:Boolean=true, cancelable:Boolean=true)
		{
			super(type, bubbles, cancelable);
			this.container = container;
		}

	}
}</pre>
<h3>Custom headerRenderer component</h3>
<p>This is a simple class that only has three methods. The first is the obligatory constructor that just invokes the super class, the next is an override of the createChildren() method that sets the enabled property of the button according to the enabled property of the button&#8217;s data property. This data property is assigned by the Accordion class and is a reference to the child object in the Accordion (a VBox for example).</p>
<pre>package com.russback.extensions
{
	import com.russback.events.AccordionHeaderEvent;

	import flash.events.MouseEvent;

	import mx.controls.Button;

	public class StateEnabledAccordionHeader extends Button
	{
		/**
		 * Constructor
		 */
		public function StateEnabledAccordionHeader()
		{
			super();
		}

		/**
		 * Sets the enabled property according to the data's enabled property
		 */
		override protected function createChildren():void
		{
			super.createChildren();

			if (data.enabled is Boolean)
			{
				enabled = data.enabled;
			}
		}</pre>
<p>Next we override the clickHandler() method. All we do here is stop the event from bubbling if the button has been disabled. And that&#8217;s it for this example.</p>
<pre>		/**
		 * Prevents the CLICK MouseEvent propogating if this object is disabled
		 */
		override protected function clickHandler(event:MouseEvent):void
		{
			if (! enabled)
			{
				event.stopImmediatePropagation();
			}
		}

	}
}</pre>
<p>This is enough to disable an Accordion item when it creates, but we should really extend this further so that we can enable and disable each item according to user behaviour or data values. For this we need to look at the child objects we&#8217;re going to add to the Accordion.</p>
<h3>Child objects of the Accordion</h3>
<p>For this example I&#8217;m just using three VBox objects but this approach applies to any class that extends the Container class. For now I&#8217;ve just created a custom class that extends VBox, called ExampleAccordionChild and it just has one override function.</p>
<pre>package com.russback.examples
{
	import com.russback.events.AccordionHeaderEvent;

	import mx.containers.VBox;
	import mx.core.Container;

	public class ExampleAccordionChild extends VBox
	{
		/**
		 * Constructor
		 */
		public function ExampleAccordionChild()
		{
			super();
		}

		/**
		 * Fires an UPDATE_HEADER AccordionHeaderEvent after setting the enabled property,
		 * passing this class as the event's container property
		 */
		override public function set enabled(value:Boolean):void
		{
			super.enabled = value;

			var accordionHeaderEvent:AccordionHeaderEvent = new AccordionHeaderEvent(AccordionHeaderEvent.UPDATE_HEADER, this as Container);
			dispatchEvent(accordionHeaderEvent);
		}

	}
}</pre>
<p>After the constructor we override the enabled() setter function to fire a new AccordionHeaderEvent with itself as the container argument. This will fire an event every time the enabled property of this object is changed and as our event is set to bubble, we&#8217;ll be able to capture this in the Accordion, which we can look at now.</p>
<h2>The custom Accordion component</h2>
<p>I&#8217;ve created an extension of the Accordion classs called StateEnabledAccordion. The constructor sets the headerRenderer property for the Accordion by setting up a new ClassFactory object which has the StateEnabledAccordionHeader class as it&#8217;s argument, and adds an event listener for the custom event we&#8217;ve created.</p>
<pre>package com.russback.extensions
{
	import com.russback.events.AccordionHeaderEvent;

	import flash.display.DisplayObject;

	import mx.containers.Accordion;
	import mx.controls.Alert;
	import mx.core.ClassFactory;

	public class StateEnabledAccordion extends Accordion
	{

		/**
		 * Constructor adds headerRenderer and event listener
		 */
		public function StateEnabledAccordion()
		{
			super();

			headerRenderer = new ClassFactory(StateEnabledAccordionHeader);
			addEventListener(AccordionHeaderEvent.UPDATE_HEADER, accordionHeaderEventHandler);
		}</pre>
<p>Then we have our event handler function that handles an UPDATE_HEADER AccordionHeaderEvent by using the container reference in the event to locate the child object that fired the event. We then get the Accordion&#8217;s header object for that child, set its enabled property, and cancel the event as we don&#8217;t need it to bubble any further. I&#8217;ve also added an Alert here just to demonstrate the fact that you can work with this here to do whatever you want.</p>
<pre>		/**
		 * Event handler sets the enabled property of the header element associated
		 * with the event container object, and stops the event from bubbling further
		 */
		private function accordionHeaderEventHandler(event:AccordionHeaderEvent):void
		{
			var childIndex:int = getChildIndex(event.container);

			var child:DisplayObject = getChildAt(childIndex);
			Alert.show("Received from " + child, "AccordionHeaderEvent.UPDATE_HEADER received");

			getHeaderAt(childIndex).enabled = event.container.enabled;
			event.stopImmediatePropagation();

		}

	}
}</pre>
<h3>Example 2 in action</h3>
<p>Creating the custom Accordion for this excample isn&#8217;t much more complex that exampl 1. We just create a new StateEnabledAccordion which contains as many ExampleAccordionChild child objects as we need. This method relies on having the child objects fire an event whenever their enabled property changes so you&#8217;d need to make sure you add that override to any child object you use.</p>
<pre><?xml version="1.0" encoding="utf-8"?>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;mx:Application
	xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
	xmlns:examples=&quot;com.russback.examples.*&quot;
	xmlns:extensions=&quot;com.russback.extensions.*&quot;
	layout=&quot;vertical&quot;
	viewSourceURL=&quot;srcview/index.html&quot;
	&gt;

	&lt;mx:HBox width=&quot;100%&quot;&gt;
		&lt;examples:ExampleButtonControl label=&quot;Toggle Child 1&quot; target=&quot;{child1}&quot; /&gt;
		&lt;examples:ExampleButtonControl label=&quot;Toggle Child 2&quot; target=&quot;{child2}&quot; /&gt;
		&lt;examples:ExampleButtonControl label=&quot;Toggle Child 3&quot; target=&quot;{child3}&quot; /&gt;
	&lt;/mx:HBox&gt;

	&lt;extensions:StateEnabledAccordion height=&quot;100%&quot; width=&quot;100%&quot; &gt;
		&lt;examples:ExampleAccordionChild id=&quot;child1&quot; label=&quot;Child 1&quot; /&gt;
		&lt;examples:ExampleAccordionChild id=&quot;child2&quot; label=&quot;Child 2&quot; /&gt;
		&lt;examples:ExampleAccordionChild id=&quot;child3&quot; label=&quot;Child 3&quot; /&gt;
	&lt;/extensions:StateEnabledAccordion&gt;

&lt;/mx:Application&gt;</pre>
<p><script type="text/javascript">
		var vars = {};    
		var params = {
			base: "."
			};
		swfobject.embedSWF("http://www.russback.com/wp-content/examples/preventing-click-on-an-accordion-header-2/main.swf", "example2", "553", "320", "9.0.0", "expressInstall.swf", vars, params);
	    </script></p>
<p>You can <a href="/wp-content/examples/preventing-click-events-on-an-accordion-header/srcview/preventing-click-on-an-accordion-header-2.zip">download and edit the source code</a>, or right-click on the demo below and choose View Source to see how it all fits together.</p>
<div class="flash_content" id="example2">
<p>You need Flash Player 10 to view this content. You can <a href="http://get.adobe.com/flashplayer/" title="Visit adobe.com">download this for free</a> from the Adobe website. If you&#8217;re using a feed reader you could <a href="http://www.russback.com/adobe-flex/preventing-click-events-on-an-accordion-header.html">try loading this post in your web browser</a>.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.russback.com/adobe-flex/preventing-click-events-on-a-flex-accordion-header.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Creating a strongly typed ArrayCollection</title>
		<link>http://www.russback.com/adobe-flex/creating-a-strongly-typed-arraycollection.html</link>
		<comments>http://www.russback.com/adobe-flex/creating-a-strongly-typed-arraycollection.html#comments</comments>
		<pubDate>Fri, 24 Jul 2009 08:04:16 +0000</pubDate>
		<dc:creator>Russ</dc:creator>
				<category><![CDATA[Adobe Flex]]></category>
		<category><![CDATA[ArrayCollection]]></category>

		<guid isPermaLink="false">http://www.russback.com/?p=489</guid>
		<description><![CDATA[I often find myself adding getting Objects from an ArrayCollection and then having to cast them as the correct Object type before I can work with them. So here's a simple way to create a strongly-typed ArrayCollection.]]></description>
			<content:encoded><![CDATA[<h2>The scenario</h2>
<p>The ArrayCollection class&#8217; addItem(), addItemAt(), getItem() and getItemAt() methods accept/return a generic Object which is great because we can use if for storing pretty much anything. But there is no way to ensure that the ArrayCollection only contains a specific class of Object, or to return an Object cast as a specific class.</p>
<p>Typically you just get your Object out of the ArrayCollection, cast it as the class you know it belongs to, and then carry on. But when you&#8217;re doing this over and over again it makes sense to override the get and add methods to work with specific Object classes.</p>
<h2>Example data</h2>
<p>To start with we need some data and for this example we have a number of &#8216;products&#8217; to work with. So for this we have a simple Product Value Object with name and price properties:</p>
<pre>package valueobjects
{
  public class Product
  {
    public var name:String;
    public var price:Number;

    /**
    * Constructor function sets up this Product object
     */
    public function Product(name:String, price:Number):void
    {
      this.name = name;
      this.price = price;
    }

  }

}</pre>
<h2>The strongly-typed ArrayCollection (ProductArrayCollection.as)</h2>
<p>Next we need our new ArrayCollection class &#8211; which I&#8217;ve called ProductArrayCollection for this example &#8211; that extends the base ArrayCollection class:</p>
<pre>package extensions
{
  import mx.collections.ArrayCollection;
  import valueobjects.Product; 

  public final class ProductArrayCollection extends ArrayCollection
  {

    /**
     * Private property used to prevent direct use of addItem and addItemAt methods
     */
    private var _itemOk:Boolean = false;

    /**
     * Constructor function simply calls the constructor function of the ArrayCollection super class
     */
    public function ProductArrayCollection(source:Array=null)
    {
      super(source);
    }</pre>
<p>The only thing to note here is a private Boolean variable called _itemOk, which is defaulted to false. We&#8217;ll use this to protect our ArrayCollection from rogue addItem() and addItemAt() method calls, as we&#8217;ll see next, starting with overrides of the addItem() and addItemAt() methods&#8230;</p>
<p>These overrides both check to see if the _itemOK property is set to true. If it&#8217;s true then we call the super class&#8217; addItem() (or addItemAt()) method which adds the supplied Object to the ArrayCollection. If it&#8217;s false, we throw an error. Doing this prevents us from calling the addItem() and addItemAt() methods directly as we can&#8217;t set the _itemOK value to false from outside the ProductArrayCollection class, we need to do that with an internal method.</p>
<pre>    /**
     * Overrides the ArrayCollection's addItem() method
     * Adds an item only if the _itemOK property has been set by the addProduct() method
     * Resets the _itemOK property if the add is successful, or throws an error
     */
    override public function addItem(item:Object):void
    {
      if (this._itemOk)
      {
        super.addItem(item);
        this._itemOk = false;
      }
      else
      {
        throw new Error(&quot;Use addProduct() to add a Product to the ProductArrayCollection&quot;);
      }
    }

    /**
     * Overrides the ArrayCollection's addItemAt() method
     * Adds an item at the specified index only if the _itemOK property has been set by the addProductAt() method
     * Resets the _itemOk property if the add is successful, or throws an error
     */
    override public function addItemAt(item:Object, index:int):void
    {
      if (this._itemOk)
      {
        super.addItemAt(item, index);
        this._itemOk = false;
      }
      else
      {
        throw new Error(&quot;Use addProductAt() to add a Product to a specific location in the ProductArrayCollection&quot;);
      }
    }</pre>
<p>To enable us to do that then, we need two new methods: addProduct() and addProductAt(). These simply set the value of _itemOK to true before calling the addItem() and addItemAt() methods:</p>
<pre>    /**
     * Sets the _itemOK property and calls the addItem() method
     */
    public function addProduct(product:Product):void
    {
      this._itemOk = true;
      this.addItem(product);
    }

    /**
     * Sets the _itemOK property and calls the addItemAt() method
     */
    public function addProductAt(product:Product, index:int):void
    {
      this._itemOk = true;
      this.addItemAt(product, index);
    }</pre>
<p>So now we can only add Product Objects to our ProductArrayCollection, the last thing we need to do is add a getProductAt() method that will return a Product rather than a generic Object:</p>
<pre>    /**
     * Uses the ArrayCollection's getItemAt() method and returns the result as a Product
     */
    public function getProductAt(index:int, prefetch:int=0):Product
    {
      return this.getItemAt(index) as Product;
    }

  }
}</pre>
<p>And that&#8217;s it &#8211; we now have a strongly-typed ArrayCollection that we can use for Products and can be extended for any other Object class.</p>
<h2>The ProductArrayCollection in action</h2>
<p>The example below is a simple one. Clicking on the each button calls the method on the button&#8217;s label. The addItem() and addItemAt() methods should should do nothing while the addProduct() and addProductAt() methods update the list. The core methods fail silently as this example is in release mode and the errors don&#8217;t display. <a href="/wp-content/examples/creating-a-strongly-typed-arraycollection/srcview/creating-a-strongly-typed-arraycollection.zip">However you can download and run the source code to generate these errors for yourself</a>.</p>
<p>Clicking on the getProductAt(0) button should display name of the name of the item at position 0 in the list.  An explanation of the source code is below and you can <a href="/wp-content/examples/creating-a-strongly-typed-arraycollection/srcview/creating-a-strongly-typed-arraycollection.zip">download and edit the source code</a>, or right-click on the demo below and choose View Source to see how it all fits together.</p>
<h3>Example</h3>
<p>
		<script type="text/javascript">
		var vars = {};    
		var params = {
			base: "."
			};
		swfobject.embedSWF("http://www.russback.com/wp-content/examples/creating-a-strongly-typed-arraycollection/main.swf", "example", "553", "450", "9.0.0", "expressInstall.swf", vars, params);
	</script>
</p>
<div class="flash_content" id="example">
<p>You need Flash Player 10 to view this content. You can <a href="http://get.adobe.com/flashplayer/" title="Visit adobe.com">download this for free</a> from the Adobe website. If you&#8217;re using a feed reader you could <a href="http://www.russback.com/adobe-flex/creating-a-strongly-typed-arraycollection.html">try loading this post in your web browser</a>.</p>
</div>
<h3>The application (main.mxml)</h3>
<p>In our application we begin with some basic layout properties, a call to a creationCompleteHandler() method, and a Script block with a private variable containing an instance of the ProductArrayCollection class:</p>
<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;mx:Application
  xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
  layout=&quot;horizontal&quot;
  width=&quot;553&quot;
  height=&quot;450&quot;
  creationComplete=&quot;creationCompleteHandler(event);&quot;
  &gt;

  &lt;mx:Script&gt;
    &lt;![CDATA[
      import mx.messaging.Producer;
      import valueobjects.Product;
      import extensions.ProductArrayCollection;
      import mx.events.FlexEvent;

      /**
       * A strongly typed ArrayCollection that can only hold Product objects
       */
      [Bindable]
      private var _products:ProductArrayCollection = new ProductArrayCollection();</pre>
<p>Next we have our creationCompleteHandler() function that is called when the application is created. In this example, it simply adds event listeners to each of the buttons in the example. Each event listnener triggers the clickHandler() method and it&#8217;s this method that calls each of the ProductArrayCollection methods we&#8217;re concerned with: addItem(), addProduct(), addItemAt(), addProductAt(), and getProductAt().</p>
<p>The line that calls getProductAt() also grabs the returned Product and updates the view with the name of that Product. As the getProductAt() method returns a Product instead of a generic Object class, we don&#8217;t need to cast it as a Product and can therefore reference the properties of it directly.</p>
<pre>      /**
       * Adds event listeners to each of the buttons in the example
       */
      private function creationCompleteHandler(event:FlexEvent):void
      {
        this.btnAddItemJeans.addEventListener(MouseEvent.CLICK, clickHandler);
        this.btnAddProductJeans.addEventListener(MouseEvent.CLICK, clickHandler);
        this.btnAddItemAtTeeShirt.addEventListener(MouseEvent.CLICK, clickHandler);
        this.btnAddProductAtTeeShirt.addEventListener(MouseEvent.CLICK, clickHandler);
        this.btnGetProductAt.addEventListener(MouseEvent.CLICK, clickHandler);
      }			

      /**
       * Creates two example products and handles click events on
       * each of the buttons in the example
       */
      private function clickHandler(event:MouseEvent):void
      {

        var jeans:Product = new Product(&quot;Jeans&quot;, 19.99);
        var teeShirt:Product = new Product(&quot;Tee Shirt&quot;, 54.99);

        switch (event.target.id)
        {
          case &quot;btnAddItemJeans&quot;:
            this._products.addItem(jeans);
            break;
          case &quot;btnAddProductJeans&quot;:
            this._products.addProduct(jeans);
            break;
          case &quot;btnAddItemAtTeeShirt&quot;:
            this._products.addItemAt(teeShirt, 0);
            break;
          case &quot;btnAddProductAtTeeShirt&quot;:
            this._products.addProductAt(teeShirt, 0);
            break;
          case &quot;btnGetProductAt&quot;:
            this.txtLog.text = &quot;Product at 0 = &quot; + this._products.getProductAt(0).name;
            break;
        }
      }</pre>
<p>The final part of our Script block is a simple label function that the list uses to display the properties of each Product in the list:</p>
<pre>      /**
        * Returns a string containing the Product name and price
        */
      private function labelFunction(item:Object):String
      {
        var text:String = &quot;&quot;;
        if (item is Product)
        {
          var product:Product = item as Product;
          text = product.name + &quot;, £&quot; + product.price;
        }
        return text;
      }

    ]]&gt;
  &lt;/mx:Script&gt;</pre>
<p>Our MXML view components are simple: A Vbox with some text and each of the buttons that will test our class, and a list to display the Products in our _products ProductArrayCollection variable.</p>
<pre>  &lt;mx:VBox width=&quot;100%&quot;&gt;

    &lt;mx:Text
      text=&quot;Add Jeans using...&quot;
      /&gt;

    &lt;mx:Button
      label=&quot;addItem()&quot;
      id=&quot;btnAddItemJeans&quot;
      /&gt;

    &lt;mx:Button
      label=&quot;addProduct()&quot;
      id=&quot;btnAddProductJeans&quot;
      /&gt;

    &lt;mx:Text
      text=&quot;Add Tee Shirt using...&quot;
      /&gt;

    &lt;mx:Button
      label=&quot;addItemAt(0)&quot;
      id=&quot;btnAddItemAtTeeShirt&quot;
      /&gt;

    &lt;mx:Button
      label=&quot;addProductAt(0)&quot;
      id=&quot;btnAddProductAtTeeShirt&quot;
      /&gt;

    &lt;mx:VBox
      visible=&quot;{this._products.length &gt; 0}&quot;
      includeInLayout=&quot;{this._products.length &gt; 0}&quot;
      &gt;

    &lt;mx:Text
      text=&quot;Get first product using...&quot;
      /&gt;

    &lt;mx:Button
      label=&quot;getProductAt(0)&quot;
      id=&quot;btnGetProductAt&quot;
      /&gt;

    &lt;mx:Text
      id=&quot;txtLog&quot;
      /&gt;

    &lt;/mx:VBox&gt;

  &lt;/mx:VBox&gt;

  &lt;mx:List
    dataProvider=&quot;{this._products}&quot;
    width=&quot;100%&quot;
    height=&quot;100%&quot;
    labelFunction=&quot;this.labelFunction&quot;
    /&gt;

&lt;/mx:Application&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.russback.com/adobe-flex/creating-a-strongly-typed-arraycollection.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Intercepting tab events in a Flex TabNavigator</title>
		<link>http://www.russback.com/adobe-flex/intercepting-tab-events-in-a-flex-tabnavigator.html</link>
		<comments>http://www.russback.com/adobe-flex/intercepting-tab-events-in-a-flex-tabnavigator.html#comments</comments>
		<pubDate>Fri, 08 May 2009 07:03:43 +0000</pubDate>
		<dc:creator>Russ</dc:creator>
				<category><![CDATA[Adobe Flex]]></category>
		<category><![CDATA[events]]></category>
		<category><![CDATA[TabNavigator]]></category>

		<guid isPermaLink="false">http://www.russback.com/?p=475</guid>
		<description><![CDATA[Flex 3's TabNavigator component has no simple way for us to listen for an event on the tabs, such as a mouseover or a click. So a custom component is required and it's a nice simple one...]]></description>
			<content:encoded><![CDATA[<p>Flex takes care of switching the views in a TabNavigator when you click on the tabs, but what if you want to detect that user activity and do something else? Maybe you want to update something else in your application. For this you need to extend the TabNavigator class and this example explains how to do that.</p>
<p>For this example, we&#8217;ll detect clicks on each tab, and also the mouseover, mouseout, mousedown and mouseup events. When any of these events occur, our example will update a TextArea element to indicate that the event has been captured and you can see this in the example below by mousing over and clicking on any of the tabs in the TabNavigator.<script type="text/javascript">
		var vars = {};    
		var params = {
			base: "."
			};
		swfobject.embedSWF("http://www.russback.com/wp-content/examples/intercepting-tab-events-in-a-flex-tabnavigator/main.swf", "example", "553", "320", "9.0.0", "expressInstall.swf", vars, params);
	</script><br />
You can <a href="/wp-content/examples/intercepting-tab-events-in-a-flex-tabnavigator/srcview/intercepting-tab-events-in-a-flex-tabnavigator.zip">download and edit the source code</a>, or right-click on the demo below and choose View Source to see how it all fits together.</p>
<div class="flash_content" id="example">
<p>You need Flash Player 10 to view this content. You can <a href="http://get.adobe.com/flashplayer/" title="Visit adobe.com">download this for free</a> from the Adobe website. If you&#8217;re using a feed reader you could <a href="http://www.russback.com/adobe-flex/intercepting-tab-events-in-a-flex-tabnavigator.html">try loading this post in your web browser</a>.</p>
</div>
<h2>A custom event</h2>
<p>For this example I&#8217;ve created a custom event, called TabEvent. This is a simple extension of the Event class that has a couple of static constants and an event property. We&#8217;ll fire a TabEvent each time a tab is interacted with and use the event property to record which event actually took place.</p>
<p>The constants are there for us to use when we create a new TabEvent, which we&#8217;ll see when we look at our application <acronym title="Magic eXtensible Markup Language">MXML</acronym>. For this example there are two constants that match the two types of event we want to capture: a mousevent (TAB_MOUSE_ACTIVITY) and a click event (TAB_ITEMCLICK_ACTIVITY):</p>
<pre>package events
{
  import flash.events.Event;

  public class TabEvent extends Event
  {

    /**
    * Constants for each type of TabEvent
    */
    public static const TAB_MOUSE_ACTIVITY:String = &quot;tabEventTabMouseActivity&quot;;
    public static const TAB_ITEMCLICK_ACTIVITY:String = &quot;tabEventTabITemClickActivity&quot;;
</pre>
<p>Next	we have public variable called event, which takes an Event object. We use this to record what type of event has occurred (a MouseEvent for example) and the constructor function assigns this property when a new TabEvent is created. We want the event to bubble up to the root of the application so we set the bubbles property to true.</p>
<pre>
    /**
    * event property to hold the event that occurred on the Tab
    */
    public var event:Event;

    /**
    * Calls the constructor class of the super class and assigns the received event to the event property
    */
    public function TabEvent(type:String, event:Event, bubbles:Boolean=true, cancelable:Boolean=false)
    {
      super(type, bubbles, cancelable);
      this.event = event;
    }

  }
}</pre>
<h2>The custom TabNavigator component</h2>
<p>Next we have our custom component, which extends the TabNavigator class and is therefore called ExtendedTabNavigator. The first thing we have is the constructor function that simply calls the constructor of the super class (ie the TabNavigator class) and adds an event listener for the FlexEvent.CREATION_COMPLETE event).</p>
<pre>package components
{
  import events.TabEvent;
  import flash.events.MouseEvent;
  import mx.containers.TabNavigator;
  import mx.controls.Button;
  import mx.events.FlexEvent;
  import mx.events.ItemClickEvent;

  public class ExtendedTabNavigator extends TabNavigator
  {
    public function ExtendedTabNavigator()
    {
      super();

      // add creation complete handler
      addEventListener(FlexEvent.CREATION_COMPLETE, creationCompleteHandler);
    }</pre>
<p>That event listener triggers the creationCompleteHandler() function which itself adds two event listners to the tabBar property of the TabNavigator. We can&#8217;t do this in the constructor as it fires before the tabBar property is populated with an instance of the TabBar class, but deferring the event listener setup to this function gets around this nicely. In this example we&#8217;re going to listen for any click events (ItemClickEvent.ITEM_CLICK) and we then also add a listener for the the FlexEvent.UPDATE_COMPLETE event on the TabBar itself. We do this for the same reason we did with the creationCompleteHandler() function &#8211; we want to monitor each tab in the TabBar but until the TabBar has been updated with its dataProvider, we&#8217;re unable to do so.</p>
<pre>    /**
    * Adds an event listener to monitor the ItemClickEvent.ITEM_CLICK on the tabBar
    * plus a listener to monitor the FlexEvent.UPDATE_COMPLETE event
    */
    private function creationCompleteHandler(ev:FlexEvent):void
    {
      tabBar.addEventListener(ItemClickEvent.ITEM_CLICK, itemClickEventHandler);
      tabBar.addEventListener(FlexEvent.UPDATE_COMPLETE, updateCompleteHandler);
    }</pre>
<p>So when the creation of the TabBar is updated, we can add our event listeners for each mouse event we want to monitor. We could monitor as many different events as we wanted to here but for this example, we&#8217;ll just look at four common ones.</p>
<pre>    /**
    * Adds event listeners for a selection of MouseEvents to each button in the tabBar
    */
    private function updateCompleteHandler(ev:FlexEvent):void
    {
      for each (var button:Button in tabBar.getChildren())
      {
        button.addEventListener(MouseEvent.MOUSE_OVER, mouseEventHandler);
        button.addEventListener(MouseEvent.MOUSE_OUT, mouseEventHandler);
        button.addEventListener(MouseEvent.MOUSE_DOWN, mouseEventHandler);
        button.addEventListener(MouseEvent.MOUSE_UP, mouseEventHandler);
      }
    }</pre>
<p>We then have two event handler functions that are called by our event listeners. The first expects an ItemClickEvent and the second expects a MouseEvent but they both do exactly the same thing: create a new TabEvent, passing it the the received ItemClickEvent or MouseEvent as the event property, and then dispatching the TabEvent to be captured by the application. We could just as easily have one handler function that expected an Event and therefore could be used for any event but this example shows how to handle different types of event differently.</p>
<pre>    /**
    * Dispatches a TabEvent.TAB_ITEMCLICK_ACTIVITY event containing the received MouseEvent
    */
    private function itemClickEventHandler(ev:ItemClickEvent):void
    {
      var tabEvent:TabEvent = new TabEvent(TabEvent.TAB_ITEMCLICK_ACTIVITY, ev);
      dispatchEvent(tabEvent);
    }

    /**
    * Dispatches a TabEvent.TAB_MOUSE_ACTIVITY event containing the received MouseEvent
    */
    private function mouseEventHandler(ev:MouseEvent):void
    {
      var tabEvent:TabEvent = new TabEvent(TabEvent.TAB_MOUSE_ACTIVITY, ev);
      dispatchEvent(tabEvent);
    }</pre>
<h2>Putting it all together &#8211; main.mxml</h2>
<p>Now we have our extended class, we need to put it into action. Our application begins first by setting up some basic data to act as the dataProvider for our ExtendedTabNavigator. This is simply an ArrayCollection of generic Objects that each have a pageName property.</p>
<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;mx:Application
  xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
  layout=&quot;vertical&quot;
  xmlns:components=&quot;components.*&quot;
  width=&quot;553&quot;
  height=&quot;320&quot;
  creationComplete=&quot;creationCompleteHandler();&quot;
  viewSourceURL=&quot;srcview/index.html&quot;
  &gt;

  &lt;mx:Style source=&quot;/assets/styles/styles.css&quot; /&gt;

  &lt;mx:Script&gt;
    &lt;![CDATA[

    import mx.controls.Button;
    import mx.events.ItemClickEvent;
    import events.TabEvent;
    import mx.controls.Text;
    import mx.containers.VBox;
    import mx.collections.ArrayCollection;

    /**
    * An array of some basic data: objects with a pageName property
    */
    [Bindable]
    private var pages:ArrayCollection = new ArrayCollection([
      {pageName:&quot;Page 1&quot;},
      {pageName:&quot;Page 2&quot;},
      {pageName:&quot;Page 3&quot;},
      {pageName:&quot;Page 4&quot;},
      {pageName:&quot;Page 5&quot;}
    ]);</pre>
<p>Next we have our creationCompleteHandler() function which is called when the application build has completed. This simply loops through our pages ArrayCollection, creates a new VBox using the createPage() function and adds that VBox to our ExtendedTabNavigator. It then adds event listeners for the two different types of TabEvent:</p>
<pre>    /**
    * Sets up the example by calling the createPage() function for every
    * object in the pages Array, and adds event listeners
    */
    private function creationCompleteHandler():void
    {
      for each (var page:Object in pages)
      {
        var vBox:VBox = createPage(page.pageName);
        tabs.addChild(vBox);
      }

    addEventListener(TabEvent.TAB_ITEMCLICK_ACTIVITY, tabEventItemClickHandler);
    addEventListener(TabEvent.TAB_MOUSE_ACTIVITY, tabEventMouseHandler);

    }</pre>
<p>Below this we have a createPage() function, whose job is to create a VBox with a Text object inside it. This is called by our creationCompleteHandler() function.</p>
<pre>    /**
    * Creates a VBox with a Text object
    */
    private function createPage(pageName:String):VBox
    {
      var vBox:VBox = new VBox();
      vBox.label = pageName;

      var text:Text = new Text();
      text.text = pageName;

      vBox.addChild(text);
      return vBox;
    }</pre>
<p>The last functions in our Script block are the event handler functions that are called by the event listeners. Both accept a TabEvent and then update the text property of one of the TextAreas in our example so we can see that an event has been received:</p>
<pre>    /**
    * Responds to a TabEvent by sending the event details to the mouseEventDetails TextArea
    */
    private function tabEventMouseHandler(ev:TabEvent):void
    {
      var mouseEvent:MouseEvent = ev.event as MouseEvent;
      mouseEventDetails.text = mouseEvent.type + &quot; on &quot; + Button(mouseEvent.target).label;
    }

    /**
    * Responds to a TabEvent by sending the event details to the itemClickEventDetails TextArea
    */
    private function tabEventItemClickHandler(ev:TabEvent):void
    {
      var itemClickEvent:ItemClickEvent = ev.event as ItemClickEvent;
      itemClickEventDetails.text = &quot;Clicked on &quot; + itemClickEvent.label.toString();
    }

    &gt;
  &lt;/mx:Script&gt;</pre>
<p>All that&#8217;s left is to add our MXML components to the view and these are simply a couple of Text elements to label up what we&#8217;re looking at, an instance of our ExtendedTabNavigator class, and two TextArea components that display the events being received. Now when you perform a mouseover, mouseout, mouseup, mousedown or click event on any of the tabs, our TextAreas show us exactly what&#8217;s happening.</p>
<pre>&lt;mx:Text
  text=&quot;Intercepting MouseEvents in a Flex TabNavigator&quot;
  /&gt;

&lt;components:ExtendedTabNavigator
  id=&quot;tabs&quot;
  width=&quot;100%&quot;
  height=&quot;75&quot;
  /&gt;

 &lt;mx:Text text=&quot;ItemClickEvent Details&quot; /&gt;

 &lt;mx:TextArea
 id=&quot;itemClickEventDetails&quot;
 width=&quot;100%&quot;
 /&gt;

&lt;mx:Text text=&quot;MouseEvent Details&quot; /&gt;

&lt;mx:TextArea
  id=&quot;mouseEventDetails&quot;
  width=&quot;100%&quot;
  /&gt;

&lt;/mx:Application&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.russback.com/adobe-flex/intercepting-tab-events-in-a-flex-tabnavigator.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Binding the selectedChild of a ViewStack in a Flex MVC structure</title>
		<link>http://www.russback.com/adobe-flex/binding-selectedchild-of-a-viewstack-in-mvc.html</link>
		<comments>http://www.russback.com/adobe-flex/binding-selectedchild-of-a-viewstack-in-mvc.html#comments</comments>
		<pubDate>Sun, 03 May 2009 07:25:25 +0000</pubDate>
		<dc:creator>Russ</dc:creator>
				<category><![CDATA[Adobe Flex]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[TabNavigator]]></category>
		<category><![CDATA[ViewStack]]></category>

		<guid isPermaLink="false">http://local.wp-clearpixel.co.uk/?p=18</guid>
		<description><![CDATA[When coding in Adobe Flex 3 within an <acronym title="Model View Controller">MVC</acronym> framework, at some point you might discover you need to update a ViewStack or TabNavigator as the Model changes. Here's a simple way to do it.]]></description>
			<content:encoded><![CDATA[<h2>The scenario</h2>
<p>In any Flex application you&#8217;re likely to have a number of views (which I&#8217;ll call pages for this example), and some form of navigation that enables you to switch from one page to another.</p>
<p>Even if you application is tiny you&#8217;re still going to be splitting your application into components and the more you do this, the more valuable bindings become. If you have all your code in the application file for example, you can get away with writing ActionScript that directly references objects in the View and update them. But once you have split your code into components it becomes much more difficult to target component objects in lower down in your package structure (think &quot;child.child.child.child&quot; &#8211; not a good idea).</p>
<p>Of course, that&#8217;s not how <a href="http://en.wikipedia.org/wiki/MVC">MVC</a> works and it&#8217;s exactly what we use data bindings for in Flex. In an MVC pattern, the Model stores the data of the application, the View contains the presentation interface, and the Controller takes care of communication between the two.</p>
<p>For this example, we have a simple application with a navigation bar (a ToggleButtonBar), a stack (ViewStack) of five pages and a set of five tab (TabNavigator)s, each containing a page.</p>
<p>When we click on the navigation bar, our example will update both the stack of pages and the tabs so that the page associated with the current navigation item is displayed. This is shown here and the code is explained in step-by-step detail below. You can <a href="/wp-content/examples/binding-selectedchild-of-a-viewstack-in-mvc/srcview/binding-selectedchild-of-a-viewstack-in-mvc.zip">download and edit the source code</a>, or right-click on the demo below and choose View Source to see how it all fits together.</p>
<p>
	<script type="text/javascript">
		var vars = {};    
		var params = {
			base: "."
			};
		swfobject.embedSWF("http://www.russback.com/wp-content/examples/binding-selectedchild-of-a-viewstack-in-mvc/main.swf", "example", "553", "300", "9.0.0", "expressInstall.swf", vars, params);
	</script>
</p>
<div class="flash_content" id="example">
<p>You need Flash Player 10 to view this content. You can <a href="http://get.adobe.com/flashplayer/" title="Visit adobe.com">download this for free</a> from the Adobe website. If you&#8217;re using a feed reader you could <a href="http://www.russback.com/adobe-flex/binding-selectedchild-of-a-viewstack-in-mvc.html">try loading this post in your web browser</a>.</p>
</div>
<h2>The problem</h2>
<p>The TabNavigator and ViewStack components have selectedChild and selectedIndex properties so at first glance, it would seem reasonable to bind the selectedChild property to the Model so that as you update you click on your app&#8217;s navigation, the selectedChild changes. </p>
<p>However the selectedChild expects a Container as its value and you&#8217;re more likely to have a string value recorded in the Model (examples might be something like &quot;sectionHome&quot;, &quot;sectionProducts&quot;, sectionUsers&quot;). The task therefore is to respond to changes to this string value in the Model and select the relevant child Container in the TabNavigator or ViewStack, so we need to be able to match the current value of that string with the relevant view (perhaps matching the string &quot;checkout&quot; to the view that displays the application checkout). </p>
<p>In a more complex application your View elements are going to be fairly complex, with numerous children objects that themselves have children, and so on. Although the structure in this example is very simple, the principle is the same as a very large project in that at the component level, the ViewStack and TabNavigator objects have no knowledge of the ToggleButtonBar and so communicating directly between the two isn&#8217;t going to work. </p>
<p>In Flex we use events to communicate throughout the application but these events only travel in one direction: they bubble upwards from the component to the application. But as the TabNavigator and ViewStack components may not be instantiated at the root of the application, we can&#8217;t simply work from the top down and communicate changes from the application down to each component. So for this, we&#8217;ll need to use data bindings on the ViewStack and TabNavigator. </p>
<h3>A note before we start</h3>
<p>This article isn&#8217;t intended to be an example of MVC as such &#8211; I&#8217;m simply building a simple MVC structure here as the theory could apply to any MVC framework, such as <a href="http://opensource.adobe.com/wiki/display/cairngorm/">Cairngorm</a>, <a href="http://mate.asfusion.com/">Mate</a> or <a href="http://puremvc.org/">pureMVC</a>. However to plug in one of those frameworks in this example is perhaps a little overkill.</p>
<p>Jump straight to <a href="#thesolution">the solution</a> if you want to skip the MVC section. </p>
<h2>Example data</h2>
<p>To start with we need some data and for this example we have a number of &#8216;pages&#8217; in the application. So for this we have a simple Page Value Object with name and title properties:</p>
<pre>package valueObjects
{
 /**
 * Basic Value Object for an example Page object
 */
 [Bindable]
 public class Page
 {
    /**
    * name and title properties
    */
    public var name:String;
    public var title:String;

    /**
    * Constructor function
    */
    public function Page()
    {
    }
  }
} </pre>
<h2>Events</h2>
<p>To communicate the fact that a user has clicked on an item in the navigation bar, we need an event. And for this we have a custom event that bubbles up to the application root, taking with it an instance of the item that was clicked on. The object expected is Page Value Objects:</p>
<pre>package events
  {
  import flash.events.Event;
  import valueObjects.Page;

  public class NavigationEvent extends Event
  {

    /**
    * A single event type that can be triggered
    */
    public static const DISPLAY_PAGE:String = &quot;navigationEventDisplayPage&quot;;

    /**
    * The Page object associated with this event
    */
    public var selectedPage:Page;

    /**
    * Constructor function calls the super class constructor and assigns the ExampleItem to the event
    * NB &gt; sets the bubbles property to true so that this event can be captured at the root
    * of the Application
    */
    public function NavigationEvent(type:String, selectedPage:Page, bubbles:Boolean=true, cancelable:Boolean=false)
    {
    super(type, bubbles, cancelable);
    this.selectedPage = selectedPage;
    }

  }
}</pre>
<h2>The Model</h2>
<p>The place to store our data is the Model and for this example I&#8217;ve created a simple class called Model:</p>
<p>In the Model we have a constructor function and then a property which will contain an instance of the Model class, an ArrayCollection property that will hold our example data, and a String property that will contain a string value that represents the page that&#8217;s in view at any time:</p>
<pre>package components
  {
  import mx.collections.ArrayCollection;
  import valueObjects.Page;

  [Bindable]
  public class Model
  {

    /**
    * Constructor function
    */
    public function Model()
    {
    }

    /**
    * Instance of the Model
    */
    public static var _instance:Model = null;

    /**
    * ArrayCollection to hold the list of pages in this example
    */
    public var data:ArrayCollection = new ArrayCollection();

    /**
    * Property to record the current selected view in the navigation
    */
    public var selectedPageName:String;</pre>
<p>The only other code we have in this example is the getInstance() function. When this function is first invoked, a new instance of the Model is created and stored in the _instance property. If getInstance() is then called again, the existing instance is returned, which should mean that we only ever have one instance of our data. </p>
<pre>    /**
    * Creates an instance of the Model class or
    * returns the existing instance
    */
    public static function getInstance():Model
    {
      if (_instance == null)
      {
        _instance = new Model();
      }
      return _instance;
    }</pre>
<h2>The Controller</h2>
<p>Now we have our Model, we need a way to communicate with it and this is where the Controller comes in. In this class we have a constructor method, an instance property and a getInstance() function  &#8211; to ensure that we only invoke one Controller in our application &#8211; and a reference to the Model. The Model reference is called in by using the Model&#8217;s getInstance function to ensure we use the one Model referenced throughout the application. </p>
<pre>package components
  {
  import events.NavigationEvent;
  import components.Model;
  import valueObjects.Page;

  public class Controller
  {
    /**
    * Constructor function
    */
    public function Controller()
    {
    }

    /**
    * Instance of the Controller
    */
    private static var _instance:Controller = null;

    /**
    * A singleton instance of the Model
    */
    private var _model:Model = Model.getInstance();

    /**
    * Creates an instance of the Controller or returns the existing instance
    */
    public static function getInstance():Controller
    {
      if (_instance == null)
      {
        _instance = new Controller();
      }
      return _instance;
    }</pre>
<p>We then have a function to add some data to the Model. In this example, this will create a new Page object and add it to the Model&#8217;s data property.</p>
<pre>    /**
    * Creates a Page object and adds it to the model
    */
    public function createPage(name:String, title:String):void
    {
      var page:Page = new Page();
      page.name = name;
      page.title = title;
      _model.data.addItem(page);
    }</pre>
<p>The final function is used to update the selectedPage property of the Model, which it does by receiving a NavigationEvent containing a Page object.</p>
<pre>    /**
    * Updates the model when the navigation changes
    */
    public function updateModel(ev:NavigationEvent):void
    {
      var selectedPage:Page = ev.selectedPage;
      _model.selectedPageName = selectedPage.name;
    }</pre>
<h2><a name="thesolution" id="thesolution"></a>The View and the solution to our problem</h2>
<p>The View is made up of a set of components shown in the diagram at the top of this page and in Flex that breaks down like this&#8230;</p>
<h3>The application (main.mxml)</h3>
<p>In our application we begin with a Script block which starts by intantiating singleton instances of our Model and Controller classes:</p>
<pre>    /**
    * A singleton instance of the Model
    */
    [Bindable]
    private var _model:Model = Model.getInstance();

    /**
    * A singleton instance of the Controller
    */
    private var _controller:Controller = Controller.getInstance();</pre>
<p>Next we have our creationCompleteHandler() function that is called when the application is created. In this example, this function calls the Controller&#8217;s createPage function a number of times to create five pages for our example. It then calls the addViews() function (see below) and finally adds an event listener to monitor any NavigationEvent.DISPLAY_PAGE events. This listener passes the event to the updateModel() function in the Controller. </p>
<pre>    /**
    * Sets up the Application on load
    * For this example this involves adding some example pages to the model
    * and setting up the required event listeners
    */
    private function creationCompleteHandler():void
    {
    // add some example data to the model
    _controller.createPage(&quot;page1&quot;, &quot;Page 1&quot;);
    _controller.createPage(&quot;page2&quot;, &quot;Page 2&quot;);
    _controller.createPage(&quot;page3&quot;, &quot;Page 3&quot;);
    _controller.createPage(&quot;page4&quot;, &quot;Page 4&quot;);
    _controller.createPage(&quot;page5&quot;, &quot;Page 5&quot;);

    // create some example views for each page in the model
    addViews(); 

    // add event listener for a NavigationEvent
    addEventListener(NavigationEvent.DISPLAY_PAGE, _controller.updateModel);
    }</pre>
<p>Next we have two functions that create some views for us. addViews() recursively calls createView() and between them, they create a VBox with some text that is then assigned to our ViewStack and Tabnavigator objects so we have something to see in our example. </p>
<pre>    /**
    * Adds a VBox object based on the Page data to the TabNavigator and
    * ViewStack used in this example
    */
    private function addViews():void
    {
      for each (var page:Page in _model.data)
      {
        createView(page, viewStack as ViewStack);
        createView(page, tabNavigator as ViewStack);
      }
    }

    /**
    * Creates a new VBox and child Text object based on a Page object
    * and appends it to the target ViewStack
    */
    private function createView(page:Page, target:ViewStack):void
    {
      var vBox:VBox = new VBox();
      vBox.name = page.name;
      vBox.label = page.title;

      var text:Text = new Text();
      text.text = page.title;
      vBox.addChild(text);

      target.addChild(vBox);
    }</pre>
<p>Now we&#8217;re onto our <acronym title="Magic eXtensible Markup Language">MXML</acronym> that begins with our application&#8217;s navigation: a simple ToggleButtonBar that&#8217;s been created as a component called NavigationBar. This gets its data from the data property of our Model class and uses the title property of the each Page object stored in the data property. </p>
<pre>    &lt;components:NavigationBar
      id=&quot;navigationBar&quot;
      dataProvider=&quot;{_model.data}&quot;
      labelField=&quot;title&quot;
      /&gt;
</pre>
<p>We then have a simple Text object and then our ViewStack, followed by another Text object and then our TabNavigator. However instead of instantiating the basic ViewStack and TabNavigator objects, here we&#8217;re using a custom component called BoundViewStack. The only thing we need to do for the second instantiation here is tell it to display as a TabNavigator, which we do by setting the isTabNavigator property to true. </p>
<pre>
    &lt;mx:Text
      text=&quot;ViewStack example:&quot;
      /&gt;

    &lt;components:BoundViewStack
      id=&quot;viewStack&quot;
      width=&quot;100%&quot;
      height=&quot;75&quot;

      /&gt;

    &lt;mx:Text
      text=&quot;TabNavigator example:&quot;
      /&gt;

    &lt;components:BoundViewStack
      isTabNavigator=&quot;true&quot;
      id=&quot;tabNavigator&quot;
      width=&quot;100%&quot;
      height=&quot;75&quot;
      /&gt;
</pre>
<h3>NavigationBar.mxml</h3>
<p>Our NavigationBar component simply extends the ToggleButtonBar class by adding an event listener that will monitor clicks on the navigation items, and an event handler to handle those click events.</p>
<p>The dataProvider of this component is set in main.mxml to be the data property of the Model class. That data property is an ArrayCollection of Page objects, so when the user clicks on an item in the navigation bar, they&#8217;re effectively clicking on a Page.</p>
<p>We take advantage of that in our event handler by creating a new NavigationEvent and passing it the selected Page object as its selectedPage argument and the event is then dispatched and caught in the event listener we set up in main.mxml. </p>
<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
  &lt;mx:ToggleButtonBar
    xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;

    creationComplete=&quot;creationCompleteHandler();&quot;
    &gt;

    &lt;mx:Script&gt;
    &lt;![CDATA[
      import events.NavigationEvent;
      import valueObjects.Page;
      import mx.events.ItemClickEvent;

      /**
      * Sets up the component on creation complete
      * For this example it just adds the required event listeners
      */
      private function creationCompleteHandler():void
      {
        addEventListener(ItemClickEvent.ITEM_CLICK, buttonClickHandler);
      }

      /**
      * Passes the clicked ButtonBar item to a new NavigationEvent
      * and dispatches that event
      */
      private function buttonClickHandler(ev:ItemClickEvent):void
      {
        var selectedPage:Page = ev.item as Page;
        var navigationEvent:NavigationEvent = new NavigationEvent(NavigationEvent.DISPLAY_PAGE, selectedPage);
        dispatchEvent(navigationEvent);
      }

    ]]&gt;
    &lt;/mx:Script&gt;

&lt;/mx:ToggleButtonBar&gt;</pre>
<p>So we now have our navigation bar communicating with the Model (via the Controller) each time the user clicks on the navigation bar. Now we need to tie our ViewStack and TabNavigator to the Model.</p>
<h3>BoundViewStack.as</h3>
<p>The TabNavigator is an extension of the ViewStack class so for our needs, we only need one component for both. We could create distinct TabNavigator and ViewStack components but we&#8217;d have to duplicate the code we&#8217;re about to write so it makes sense to create a new component that extends TabNavigator called BoundViewStack.</p>
<p>The first few lines of the this simple component takes care of our imports and the constructor function invokes the constructor class of the super class before adding an event listener that will detect when our component has been created. We do this by my monitoring the FlexEvent.CREATION_COMPLETE event:</p>
<pre>package components
  {
  import flash.display.DisplayObject;
  import components.Model;
  import mx.binding.utils.ChangeWatcher;
  import mx.containers.TabNavigator;
  import mx.core.Container;
  import mx.events.FlexEvent;
  import mx.events.PropertyChangeEvent;

  public class BoundViewStack extends TabNavigator
  {
    /**
    * Class constructor function invokes the contructor of the TabNavigator class and adds
    * an event listener for the FlexEvent.CREATION_COMPLETE event
    */
    public function BoundViewStack()
    {
      super();
      addEventListener(FlexEvent.CREATION_COMPLETE, creationCompleteHandler);
    }</pre>
<p>We then continue with a public property to determine if this component should display as a TabNavigator, and then singleton instances of our Model class:</p>
<pre>    /**
    * Property to determine if this should be used as a TabNavigator
    */
    public var isTabNavigator:Boolean = false;

    /**
    * A singleton instance of the model object
    */
    private var _model:Model = Model.getInstance();</pre>
<p>Then comes our creationCompleteHandler() function that does a couple of things. If the component is not to be displayed as a TabNavigator it hides the TabNavigator&#8217;s tab bar by setting its visibility and includeInLayout properties to false, and its height to 0.</p>
<p>Next is where we solve our problem with the ChangeWatcher class. The ChangeWatcher watches a property of an object and then calls a handler function when the property changes. We know that we have a property in our Model called currentPageName that holds the name of the Page the user clicked on in the navigation bar, so we set up a watch on that property. </p>
<pre>    /**
    * Sets up the Class on creation complete
    * A ChangeWatcher is used to monitor the model and if this component is not to display
    * as a TabNavigator, the tabBar is hidden from view
    */
    private function creationCompleteHandler(ev:FlexEvent):void
    {
      if (! isTabNavigator)
      {
        tabBar.visible = false;
        tabBar.includeInLayout = false;
        tabBar.height = 0;
      } 

    // add a ChangeWatcher to monitor the model
    ChangeWatcher.watch(_model, &quot;selectedPageName&quot;, modelChangeHandler);
    }
</pre>
<p>		The final piece in the jigsaw is the handler function that the ChangeWatcher calls: modelChangeHandler(). This expects a PropertyChangeEvent in which both the old and new values of the _model.selectedPageName property is available.</p>
<p>As each page in our View has its name property set to match the name property of a Page object (we know this as we created our page views progromatically in the addViews() function of main.mxml), we need to get the child oject that corresponds to the Page the user has selected, which we do with the getChildByName function.</p>
<p>If this returns an object we then want to display it, which we do by updating the TabNavigator&#8217;s selectedChild property. This expects a Container so we need cast the DisplayObject we received in the previous step in order for it to work. </p>
<pre>    /**
    * Responds to changes in the model by updating the selectedChild
    */
    private function modelChangeHandler(ev:PropertyChangeEvent):void
    {
      var itemToSelect:DisplayObject = getChildByName(ev.newValue as String);

      if (itemToSelect)
      {
        selectedChild = itemToSelect as Container;
      }
    }</pre>
<p>And then bang, we&#8217;re done. We now have a very basic MVC application structure where everything is tied together with events and bindings, leaving us free to structure our component packages in any way our application demands.</p>
<p>The solution to our problem is very simple so this article is more in-depth than it needs to be, but I hope it explains a little about the advantages of an MVC pattern and that it will lead you on to looking at frameworks like Cairngorm that take care of a lot of the MVC side of things.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.russback.com/adobe-flex/binding-selectedchild-of-a-viewstack-in-mvc.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Displaying an image in a Flex tooltip</title>
		<link>http://www.russback.com/adobe-flex/displaying-an-image-in-a-tooltip.html</link>
		<comments>http://www.russback.com/adobe-flex/displaying-an-image-in-a-tooltip.html#comments</comments>
		<pubDate>Thu, 02 Apr 2009 14:35:55 +0000</pubDate>
		<dc:creator>Russ</dc:creator>
				<category><![CDATA[Adobe Flex]]></category>

		<guid isPermaLink="false">http://www.russback.com/?p=371</guid>
		<description><![CDATA[Adding a simple text tooltip in Adobe Flex is simple - the ToolTip Manager displays the tooltip text property of an object as default behaviour. More complex tooltips need a little extra work.]]></description>
			<content:encoded><![CDATA[<h2>Demo and source code</h2>
<p>This is a simple example that will display a panel with the details of an image as a tooltip, including a preview of the image itself.</p>
<p>This is shown here and the code is explained in step-by-step detail below. You can <a href="/wp-content/examples/displaying-an-image-in-a-tooltip/srcview/displaying-an-image-in-a-tooltip.zip">download and edit the source code</a>, or right-click on the demo below and choose View Source to see how it all fits together.</p>
<p><script type="text/javascript">
var vars = {};    
var params = {
  base: "."
};
    swfobject.embedSWF("http://www.russback.com/wp-content/examples/displaying-an-image-in-a-tooltip/main.swf", "example", "553", "420", "9.0.0", "expressInstall.swf", vars, params);
</script></p>
<div class="flash_content" id="example">
<p>You need Flash Player 10 to view this content. You can <a href="http://get.adobe.com/flashplayer/" title="Visit adobe.com">download this for free</a> from the Adobe website. If you&#8217;re using a feed reader you could <a href="http://www.russback.com/adobe-flex/displaying-an-image-in-a-tooltip.html">try loading this post in your web browser</a>.</p>
</div>
<h2><a name="data" id="data"></a>Data and assets</h2>
<p>The first thing we need is some data, so for this we set up a <a href="http://en.wikipedia.org/wiki/Value_object" title="Visit wikipedia.org">Value Object</a> that describes our photo object. For this we simpy need a few basic properties including the title, the photographer details and the filename of the preview image we&#8217;re going to display on our tooltip. In our example this is saved as <span class="code">Photo.as</span> in the <span class="code">valueObjects</span> directory.</p>
<pre>package valueObjects
{
 /**
  * Basic Value Object for a photo
  */
 [Bindable]
 public class Photo
 {
   public var title:String;
   public var filename:String;
   public var photographer:String;
   public var website:String;

   public function Photo()
   {
   }
 }
}
</pre>
<p>We also need some assets for our demo, a simple stylesheet and the preview images we&#8217;ll be displaying for each photo. These are all stored in the <span class="code">assets</span> directory of our demo.</p>
<p>To keep things nice and simple we&#8217;ll break our demo down into separate simple components, of which there are two: <a href="#photoview"><span class="code">PhotoView.mxml</span></a> and <a href="#phototooltip"><span class="code">PhotoToolTip.mxml</span></a>. But before we look at those, let&#8217;s dive into our <span class="code">Application</span> file <span class="code">Main.xml</span>.</p>
<h2>The Application</h2>
<p>As this is a very simple demo Main.mxml contains very little <abbr title="Magic eXtensible Markup Language">MXML</abbr> as it&#8217;s simpler just to build the app with ActionScript when the application loads. The only MXML code in here is a call to load the stylesheet for the demo, and then a <span class="code">Script</span> block which handles our application build, which we&#8217;ll go through step-by-step&#8230;</p>
<p>The first few lines take care of the imports for our <span class="code">PhotoView</span> component and the <span class="code">Photo</span> Value Object:</p>
<pre>import components.PhotoView;
import valueObjects.Photo;</pre>
<p>Next we have our two application methods. The first of these &#8211; <span class="code">createPhoto()</span> &#8211; creates a new <span class="code">Photo</span> Value Object and a new <span class="code">PhotoView</span> component. The component is then added to the <span class="code">Application</span> view.</p>
<pre>/**
 * Creates a new Photo object and adds it to the sample data collection
 */
 private function createPhoto(title:String, filename:String, photographer:String, website:String):void
 {
   var photo:Photo = new Photo();
   photo.title = title;
   photo.filename = filename;
   photo.photographer = photographer;
   photo.website = website;
   _photos.addItem(photo);
 }</pre>
<p>The <span class="code">createPhoto()</span> method is called a number of times when the <span class="code">Application</span> is first compiled, via our only other method in <span class="code">Main.mxml</span>: <span class="code">creationCompleteHandler()</span>. The job of this method is simply to create some demo objects by some data to the <span class="code">createPhoto()</span> method.</p>
<pre>/**
 * Sets up the demo when the application creation has been completed
 */
 private function creationCompleteHandler():void
 {
   // set up the sample data
   createPhoto(&quot;Tomatoes&quot;, &quot;1163182_tomatoes.jpg&quot;, &quot;Edmondo Dantes&quot;, &quot;http://www.sxc.hu/profile/edmondo&quot;);
   createPhoto(&quot;Oranges&quot;, &quot;1118482_oranges.jpg&quot;, &quot;chamanit&quot;, &quot;http://www.sxc.hu/profile/chamanit&quot;);
   createPhoto(&quot;Lemons&quot;, &quot;1126699_lemon.jpg&quot;, &quot;abcdz2000&quot;, &quot;http://www.sxc.hu/profile/abcdz2000&quot;);
   createPhoto(&quot;Peppers&quot;, &quot;1163181_peppers.jpg&quot;, &quot;Edmondo Dantes&quot;, &quot;http://www.sxc.hu/profile/edmondo&quot;);
   createPhoto(&quot;Courgettes&quot;, &quot;1163183_courgette.jpg&quot;, &quot;Edmondo Dantes&quot;, &quot;http://www.sxc.hu/profile/edmondo&quot;);
 }</pre>
<p>That takes care of our main <span class="code">Application</span>. Next is the <span class="code">PhotoView</span> component&#8230;</p>
<h2><a name="photoview" id="photoview"></a>PhotoView.mxml</h2>
<p>For each photo we want to show a simple red box with the title text in it. When you hover over this box, we want to show the rest of the information for the photo, along with the image, as a tooltip. So <span class="code">PhotoView.mxml</span> is a simple <span class="code">VBox</span> component with a <span class="code">Text</span> object inside it. It expects a <span class="code">Photo</span> Value Object for its data, so we bind the <span class="code">Photo.title</span> property to the value of the <span class="code">Text</span> object:</p>
<pre>&lt;mx:Text text=&quot;{photo.title}&quot; /&gt;</pre>
<p>The only MXML object in here is a <span class="code">Script</span> block, which takes care of our tooltip behaviour. The first few lines take care of our imports &#8211; the <span class="code">ToolTipEvent</span> Class and our <span class="code">Photo</span> Value Object.</p>
<pre>import mx.events.ToolTipEvent;
import valueObjects.Photo;</pre>
<p>We then create a public bindable variable to contain the <span class="code">Photo</span> data and it&#8217;s this variable that&#8217;s populated in the <span class="code">createPhoto()</span> mehod of <span class="code">Main.mxml</span> each time a photo is added.</p>
<pre>[Bindable]
public var photo:Photo;</pre>
<p>Next we have two methods, the first of which is our <span class="code">creationCompleteHandler()</span>. This is called when the <span class="code">PhotoView</span> component is compiled and simply assigns a new event listener that will detect the creation of a tooltip and fire our second method: <span class="code">toolTipCreateHandler()</span>.</p>
<pre>/**
 * Adds a TOOL_TIP_CREATE event on this component
 */
 private function creationCompleteHandler():void
 {
   addEventListener(ToolTipEvent.TOOL_TIP_CREATE, toolTipCreateHandler);
 }</pre>
<p>Our <span class="code">toolTipCreateHandler()</span> method follows and it&#8217;s purpose is to instantiate a new <span class="code">PhotoToolTip</span> component, pass it the <span class="code">Photo</span> Value Object for this particular photo, and then assign the component as to the tooltip event.</p>
<pre>/**
 * Event handler method to create a new tooltip object
 */
 private function toolTipCreateHandler(ev:ToolTipEvent):void
 {
   var tooltip:PhotoToolTip = new PhotoToolTip();
   tooltip.photo = photo;
   ev.toolTip = tooltip;
 }</pre>
<p>So what&#8217;s happening here? Basically when you hover your mouse over a instance of the <span class="code">PhotoView</span> component, a <span class="code">ToolTipEvent.TOOL_TIP_CREATE</span> event is fired and our <span class="code">toolTipCreateHandler()</span> method intercepts this and assigns a <span class="code">PhotoToolTip</span> component as the <span class="code">tooltip</span> property of the event, effectively overriding the default text tooltip that you get out of the box. There is only one thing left to do here to make the <span class="code">ToolTipEvent</span> fire: we need to set the <span class="code">tooltip</span> property of the <span class="code">PhotoView</span> component itself, which is done as follows in the properties of the <span class="code">PhotoView.mxml</span> file:</p>
<pre>&lt;mx:VBox
   xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
   creationComplete=&quot;creationCompleteHandler();&quot;
   toolTip=&quot;{photo.title}&quot;
   &gt;</pre>
<h2><a name="phototooltip" id="phototooltip"></a>PhotoToolTip.mxml</h2>
<p>Our final piece of the jigsaw is the component we want to display as the tooltip and this is where <span class="code">PhotoToolTip.mxml</span> comes in. This demo uses a simple <span class="code">Panel</span> component containing <span class="code">Image</span> and <span class="code">Text</span> objects that display the photo data but you could use any component that extends the <span class="code">UIComponent</span> Class. The important thing to note is that whatever component you choose, it must implement the <span class="code">IToolTip</span> Interface and contain <a href="http://livedocs.adobe.com/flex/3/html/basic_as_2.html" title="Visit adobe.com">getter and setter methods</a> for the text property, otherwise you&#8217;ll get errors when you compile your application.</p>
<p>The first line of our MXML file takes care of the implementation of the <span class="code">IToolTip</span> Interface and adds a title to the <span class="code">Panel</span> using the data from the <span class="code">Photo</span> Value Object for this photo.</p>
<pre>&lt;mx:Panel
   xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
   implements=&quot;mx.core.IToolTip&quot;
   title=&quot;{_photo.title} by {_photo.photographer}&quot;
   &gt;</pre>
<p>Next we have a <span class="code">Script</span> block, the first part of which imports the <span class="code">Photo</span> Value Object and declares a private bindable variable to hold the photo data.</p>
<pre>import valueObjects.Photo;

/**
 * Variable to contain the Photo Value Object
 */
[Bindable]
private var _photo:Photo;</pre>
<p>Then we have the text property and getter/setter methods that the <span class="code">IToolTip</span> Interface requires:</p>
<pre>/**
 * Required text property of the IToolTip interface
 */
private var _text:String;

/**
 * Getter method for text property, required for the IToolTip interface
 */
public function get text():String
{
  return _text;
}

/**
 * Setter method for text property, required for the IToolTip interface
 */
public function set text(value:String):void
{
  _text = value;
}</pre>
<p>The last part of our <span class="code">Script</span> consists of a setter method for the private variable <span class="code">_photo</span>. We could avoid this by making the variable public but in the interests of keeping the way in which we get and set properties consistent, we have a setter method for this (we don&#8217;t need a getter for this example so this is left out).</p>
<pre>/**
 * Setter method for photo property
 */
public function set photo(value:Photo):void
{
  _photo = value;
}</pre>
<p>Finally we have the <span class="code">Image</span> and <span class="code">Text</span> objects within the <span class="code">Panel</span> that will show the preview image and the photographer information stored in the photo&#8217;s <span class="code">Photo</span> Value Object.</p>
<pre>&lt;mx:Image source=&quot;assets/images/{_photo.filename}&quot; /&gt;
&lt;mx:Text text=&quot;Profile: {_photo.website}&quot; /&gt;</pre>
<p>This technique should provide a simple foundation for tooltip usage beyond simple text descriptions and is one that you can expand upon for your own, perhaps more complex requirements.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.russback.com/adobe-flex/displaying-an-image-in-a-tooltip.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
