Logging Flash with Google Chrome Developer Tools console

Actionscript, Flex No Comments »

Google Chrome’s new Developer Tools panel is really great but now it’s even better now that I’ve managed to log directly into it from Actionscript.

And it’s all thanks to this blog post : http://aut0poietic.us/2008/10/22/using-the-flex-3-logging-framework

All I had to do was create the ExternalConsoleTarget class from his example and then grab the code for the Console Logging wrapper. Then in my project import the Console class and log like this …

Console.debug("Hello Chrome");

It worked for me straight out of the box. Wonderful.

And because I’m a bloody nice bloke here’s my test project which includes a SWC I made so you can use the two classes in your own projects: http://lyraspace.com/tools/ConsoleLogger/Main.html

Removing specific DisplayObjects from a container in Actionscript 3

Actionscript 2 Comments »

This is a common mistake when trying to remove certain DisplayObject objects from a container in Actionscript. I fell into it again today and kicked myself around the office for five minutes afterward.

If you want to remove specific DisplayObjects from a container you may be tempted to do something like this …

  1. for (i=0; i<container_mc.numChildren; i++)
  2.    {
  3.     if(container.getChildAt(i) == mySprite || container_mc.getChildAt(i) == anotherSprite) container_mc.removeChildAt(i);
  4.    }

This will work unless one of the Sprites is at the top of the stack in which case that object wont be removed. But WHY?!!!

Well because the numChildren property will reduce as the objects get removed so eventually it will stop before the last object. The solution is to compensate by adjusting the variable ‘i’ in the for loop. Like so …

  1. for (i=0; i<container_mc.numChildren; i++)
  2.    {
  3.     if(container.getChildAt(i) == mySprite || container_mc.getChildAt(i) == anotherSprite) { container_mc.removeChildAt(i); i–;}
  4.    }

Hope this helps someone and prevents any self-harm.

New touch/gesture events in Actionscript 3 for Flash Player 10.1

Actionscript, Flash, Flex 1 Comment »

This video from a MAX session has an informative demonstration of the new touch/gesture events in 10.1. Also loads of really cool new features in the AIR 2.0 runtime.

What’s coming in Adobe AIR 2.0

Here’s a great article outlining all of the new events, classes and information on how to manage the input.

I’ve scraped the code off this article for my own reference below. Please do read the article though.


flash.ui.Multitouch
[static] inputMode:String
[static] maxTouchPoints:int
[static] supportedGestures:Vector
[static] supportsGestureEvents:Boolean
[static] supportsTouchEvents:Boolean

Touch Input mode

flash.events.MultitouchInputMode
Multitouch.inputMode
MultitouchInputMode.TOUCH_POINT
MultitouchInputMode.NONE
MultitouchInputMode.GESTURE

Mouse

MouseEvent.CLICK
MouseEvent.DOUBLE_CLICK
MouseEvent.MOUSE_DOWN
MouseEvent.MOUSE_UP
MouseEvent.MOUSE_MOVE
MouseEvent.MOUSE_OUT
MouseEvent.MOUSE_OVER
MouseEvent.ROLL_OUT
MouseEvent.ROLL_OVER

Touch

TouchEvent.TOUCH_BEGIN
TouchEvent.TOUCH_MOVE
TouchEvent.TOUCH_END
TouchEvent.TOUCH_TAP
TouchEvent.TOUCH_OUT
TouchEvent.TOUCH_OVER
TouchEvent.TOUCH_ROLL_OUT
TouchEvent.TOUCH_ROLL_OVER
TouchEvent.TOUCH_TAP

Touch management

Many multi-touch developers like to use an Object or Array of points to keep track of touch inputs (aka blobs) as well as an ID, and X/Y coordinatees for each point. It looks like Flash Player 10.1 will help you conform to these conventions, ActionScript-style.


flash.utils.Dictionary /* Used to track Arrays of Points */
flash.geom.Point /* One contact point */
TouchEvent.touchPointID /* Unique ID for each touch contact point */
TouchEvent.stageX
TouchEvent.stageY
TouchEvent.isPrimaryTouchPoint

Gestures

flash.events.GestureEvent;
flash.events.GesturePhase;
flash.events.GesturePhaseEvent;
flash.events.TransformGestureEvent;

/* GestureEvent */
GestureEvent.GESTURE_TWO_FINGER_TAP
GestureEvent.phase: String
GestureEvent.localX:Number
GestureEvent.localY:Number
GestureEvent.stageX:Number
GestureEvent.stageY:Number

/* GesturePhase */
GesturePhase.BEGIN
GesturePhase.END
GesturePhase.UPDATE

/* GesturePhaseEvent */
GesturePhaseEvent.GESTURE_PAN
GesturePhaseEvent.GESTURE_PRESS_AND_TAP
GesturePhaseEvent.GESTURE_ROTATE
GesturePhaseEvent.GESTURE_ZOOM //Is the same thing as 'pinch'
GesturePhaseEvent.offsetX:Number
GesturePhaseEvent.offsetY:Number
GesturePhaseEvent.rotation:Number
GesturePhaseEvent.scaleX:Number
GesturePhaseEvent.scaleY:Number

Orientation recognition

flash.display.StageOrientation;
/* e.g. StageOrientation.DEFAULT */

flash.display.StageDisplayState;
/* e.g. stage.displayState = FULL_SCREEN_INTERACTIVE; */

Spark TextArea Skin bug update

Actionscript, Flex No Comments »

A quick update on the bug we posted here about the TextArea Skin focus bug. Here’s the original post but the news from Adobe is that it’s fixed and here’s the fix …

Forgot to mention in the checkin notes that the CustomTextAreaSkin must utilize the focusSkinExclusions property. You can see it used in the default TextAreaSkin. It looks like this:

/**
* @inheritDoc
*/
override public function get focusSkinExclusions():Array { return [ textDisplay ] };

Introducing Slider – the new Flex Mobile Framework

Actionscript, Apple, Flash, Flex, iPhone 2 Comments »

So the big news from the Adobe MAX conference yesterday was the announcement that Flash Player 10.1 will allow Flash Platform developers to create content for a range of other devices including Mobile, NetBooks and Set-top boxes. The new player will include some new multi-touch events to take advantage of this capability on Mobile, MacBook’s and Windows 7 touch-enabled devices. I’ll be looking at these events myself when they release the updated SDK and player and will be sure to post some examples and experiments.

Bigger news came in the form of a spoof ‘MythBusters’ video exploring the ‘myth’ that you can’t produce Flash content for the iPhone. Yes, Adobe will be compiling native iPhone content directly from Flash CS5. There’s no Flash plugin in the browser on the iPhone but the new FP10.1 touch events will work apparently. The compiler technology is way over my head but here’s the press release and some information on labs. It seems that Adobe have snuck a few iPhone apps onto the store in advance and the example I’ve played with, Chroma Circuit, performed very well (and is really addictive).

This got me thinking about the future for apps on the iPhone if Flash peeps all rush off trying to submit their content to the store. For a start Apple are going to be struggling to keep on top of their approval process. Apple is very strict when it comes to the Human Interface Guidelines (HIG) and the iPhone Dev kit that most devs use to generate UI elements on the iPhone ensure that developers ‘toe the line’ and by and large result in a design consistency that has been part of their success with the device. Now, I know there are already a lot of god awful apps on the iPhone that seem to deviate from the HIG exceedingly but it isn’t just the appearance of an app that is the issue here. Developing apps for the iPhone is a tricky, slippery business. Memory management and proper garbage collection is vital to the performance of the app and without thorough testing and a decent authoring/debugging environment like XCode it’s going to be very difficult indeed to create a decent iPhone app in Flash. So how will we develop decent apps for the iPhone or any of the other devices for that matter?

Well, while everyone was tweeting about the iPhone news I found myself reading through the Mobile dev FAQ’s and noticed this …

Can I use the Flex Framework to create content for the iPhone?

While it is possible to create iPhone content using the desktop Flex Framework, we do not recommend it. The Flex framework is currently optimized for execution in a desktop environment. The performance, UI, and interaction models have not been optimized for mobile devices.

Adobe is working on a mobile Flex Framework, which should be better suited for iPhone development.

What? That last line got me very excited. And then I saw the link.

And here’s a sneak preview!

Flex for mobile devices

Here’s the app they built running on an iPhone :
Flex Mobile Framework

Interesting bit of trivia is that the codename ‘Slider’ is a joke based on a conversation in which the original Flex framework was compared with a nice juicy burger for developers and so the mobile framework would be a smaller burger … a ’slider’. As a brit … I don’t get it.

So, there’ll be a new lightweight Flex framework that will allow us to produce UI elements and advanced layouts for mobile devices and this framework is currently codenamed ‘Slider’. Now, personally the iPhone thing could be painful but lets not forget about all of the other devices that we can now develop for. A project will need to change state dynamically to fit within a range of screen sizes, layout will be extremely important as people expect their content to adjust to different orientations and the implementation of themes is also going to be huge. The Flex framework is perfect for this type of development and the Spark/FXG partnership is lightweight and flexible.

Reading the FAQ I noticed this …

On what platforms will Slider run?
The initial Slider framework will be optimized to run on high-end smartphones (phones with a processor speed of 400Mhz or more, 128MB of RAM), and will initially target standalone application environments such as Adobe AIR. This matches the category of devices targeted by Flash Player 10.

Reading between the lines here but does this suggest that the AIR runtime will also be available on devices?

UPDATE: This video on Adobe TV talks about how the process of developing the iPhone app is very similar to building an AIR app. So I guess there wont be an AIR runtime for mobile devices.

Building Mobile Applications with Adobe AIR

Some interesting information in that video. Hardware acceleration will be supported via the use of the cacheAsSurface property.

Ted Patrick has a great post on developing iPhone apps with CS5 including source. Check it out.

Here’s a real good cast of the Secret Session from yesterday with Richard Galvan which explores a bit more about the new features of Flash Pro CS5 including the Text framework and support for ligatures and flow.

They’ve added integration between the Flash IDE and Flash Builder so you can launch FB4 from the Flash IDE and setup workflows between the two environments including launching Flash pro to test from FB. This is going to be great for managing assets in Flash while coding in Flash Builder. Code snippets in Flash Pro let non-coders add interactivity too. This will allow large agencies with teams to have their tech dude add all the common code the designers need to build banners for example. Code completion in Flash mimics FB too … finally!

I’m expecting more news today in the second keynote and will update this post. If you are at MAX and see any demos of the Slider framework then please leave me a comment and let me know what you saw and heard.

Spark ScrubBar bufferedArea bug

Actionscript, Flex 3 Comments »

I discovered a bug in the Spark ScrubBar class that I thought I’d better document. It’s a real git!

Firstly I noticed that despite setting the bufferEnd property of the class I wasn’t seeing any results. So I watched the numbers and sure enough the bufferEnd property was being set as my media loaded and was significantly larger than the playhead value which made sense.

So then I figured the skin part wasn’t being rendered so I forced a width on it in the skin class and sure enough it was rendered. I soon realised that the bufferedArea was being drawn and was being adjusted over time. Unfortunately its width was being set to exactly the same size as the playedArea element so it was hidden underneath.

So then I did some digging and I traced the calculation of the size of the skin part down to a private method in the ScrubBar class called ‘calculateAreaSize’. Both the playedArea and the bufferedArea get their sizes from this method as the ‘value’ and ‘bufferEnd’ properties change.

The problem is that the argument passed into this method is called ‘value’ which is the same name as the class property ‘value’ that is used to determine the width of playedArea. So when this method was being used to also calculate the width of bufferedArea it was yielding the same results.

The solution is to sub-class ScrubBar and then add the following methods …

  1. override protected function updateSkinDisplayList():void
  2.      {
  3.          super.updateSkinDisplayList();
  4.          
  5.          sizeBufferedArea(newCalculateAreaSize(bufferedEnd));
  6.          sizePlayedArea(newCalculateAreaSize(value));
  7.      }
  8.      
  9.      protected function newCalculateAreaSize(v:Number):Number
  10.      {
  11.          var trackPos:Number = track.getLayoutBoundsX();
  12.          var trackSize:Number = track.getLayoutBoundsWidth();
  13.          var thumbSize:Number = thumb.getLayoutBoundsWidth();
  14.          var range:Number = maximum – minimum;
  15.          var thumbPos:Number = (range > 0) ? (v – minimum) * ((trackSize – thumbSize) / range) : 0;
  16.          
  17.          return thumbSize + thumbPos;
  18.      }

You need to create the newCalculateAreaSize method because the Super class method is private.

Hope this helps someone out.

Getting your head around the Mate framework

Actionscript, Flex No Comments »

So I’ve been looking at Mate and trying to get my head around the way it manages the MVC process. The main difference between Mate and Cairngorm and the one thing I’ve been struggling to fix in my head is the relationship between the Views and the Model.

In Cairngorm your Commands will update the ModelLocator (usually a Singleton class) and your views will bind to the Model. The View basically says ‘give me the data’ and the reference to the Model is there in the View (in most cases).

Mate takes a different approach. With Mate your views are created with no reference to where the data is coming from. It provides public properties but should not provide a way to update them. Any internal logic should be done privately. Instead of a Singleton Model you create an EventMap and a Manager class to handle the injection of data into the views. Note the use of the word injection; this is the big mental shift. Your views are injected with the data they need but have no reference to where this data is coming from. This means your Views are completely decoupled from the Model and Controller … as it should be.

Now, how Mate does this is quite confusing at first. Especially problematic for a newbie is how it handles Class instantiation. In your EventMap you handle Events. These events may be requests for data from the back-end but may also be general requests from the views for some change in state. Within these EventHandler tags you can set properties on your Manager class or run methods on the Manager which will adjust its internal data ready for injectors to trigger changes in binding and inject the data from these Manager classes into the Views. Injectors are also setup in the EventMap and here’s where it gets confusing; the reference to the Manager class is not an instance of the class but the class itself …

<Injectors target=”{VideoScreen}” >
<PropertyInjector targetKey=”videoVO” source=”{AppManager}” sourceKey=”videoVO” />
</Injectors>

In this example, I want to inject my View (VideoScreen) with the videoVO property from the Manager (AppManager) classes videoVO property. Mate requires you to use the Class name as the target and will instantiate and cache the instance for you. The example above has now setup a binding between the AppManager and the VideoScreen class which is great … or is it? Originally I’d wanted to inject a property of the VO into my view and not the entire VO. What I wanted to do was this …

<Injectors target=”{VideoScreen}” >
<PropertyInjector targetKey=”source_url” source=”{AppManager}” sourceKey=”videoVO.source_url” />
</Injectors>

I like the idea of the Manager storing my VO classes but I want to inject specific properties from them into my views. To be completely decoupled it’s best that my views don’t reference VO classes but have very specific properties like the source_url property in my VideoScreen class. The only way I can think of doing this is to create the VO object within the EventMap and not in the AppManager. Like so …

<Injectors target=”{VideoScreen}” >
<PropertyInjector targetKey=”source_url” source=”{VideoVO}” sourceKey=”source_url” />
</Injectors>

… that would work. But then that got me thinking, what if I needed a whole bunch of VideoVO instances all stored in an ArrayCollection? I’d need to manage this logic within a Manager class but how would I manage the injection within the EventMap? My head is starting to hurt.

I know there must be some ingenious solution to these puzzles in my mind and I invite anyone who understands the framework a bit more than me to comment and offer me some insight. I can see the potential with this framework but at the moment these issues are preventing me from diving in.

More adventures in Mate soon no doubt.

[UPDATE]

Nahuel from ASFusion has posted on the forum about this here.
He pasted some code here.

Mate Framework and Flex 4 sdk

Actionscript, Flash, Flex 2 Comments »

I spent a good few hours trying to get the Mate framework working yesterday using the famous Cafe Townsend example. It was time well spent as I plunged quite deep into the architecture; putting my failures down to syntax and short-sightedness. I soon realised that something much deeper was wrong however and a quick look at the Mate forums revealed this post with this gem …

It seems the problem sticks inside SystemManager which GlobalDispatcher uses

… it seems that the use of Application.application in the framework was preventing the global events being dispatched from the SystemManager. In Flex 4 you use FlexGlobals.topLevelApplication to return the main Application class.
A member of the team soon posted a patch which (at the time of writing this post) is available here. Now, this is the reason for posting this information: anyone who may find themselves in the same situation that I was yesterday should NOT download the latest SWC for the Mate framework you’ll find this ‘fix’ is NOT in place. You’ll need the patch to publish using the Flex 4 sdk.
While I’m at it. Here’s my Cafe Townsend Mate example ported to Flex 4 with some of the code for you to check out. The only change is the use of the Spark Application tag and the Declarations tag. I did remove the Styles with the intention to put them back at some point but I don’t think I can be arsed now. You’ll just need to grab the code from the Flex 3 example and put it back. The views are the same. Grab the source here.

[note: RSS readers will not display the iFrame below]

Here’s the Application class. Note the Declarations tag and the EventMap classes. Don’t get caught out by this. You need to use the Declarations tag for non-visual components in your Application class.

What I like about Mate is the how minimal you can keep your views. Notice how I’m not listening for any of the FlexEvent events within the App class. Now look at the MainEventMap class …

… all your events are handled in here which makes your code really neat and the views end up being nicely decoupled from the logic and functionality.

Anyhoo, I hope this has saved someone a few hours of frustration.

Adobe Open Source Media Framework (OSMF) – formerly Strobe

Actionscript, Flash, Flex, video 13 Comments »

I’ve been looking at the Adobe Open Source Media Framework or OSMF today and I thought I’d post a little Flex quick-start project which should help people get up and running with it.

There’s a useful class in the adobe.strobe.players package which wraps up the Actionscript media player in a Flex UIcomponent. It’s called ‘MediaPlayerWrapper’ and it seems to be the only Flex based player supplied in the framework so far. This player isn’t a part of the official framework which is all contained within the org.openvideoplayer package. Instead it is offered as part of the examples that Adobe give to you in the download. It’s obviously meant as a base to work on because I have noticed a few bugs and omissions which brings me to this little example I’m posting.

The main thing I’ve noticed about the wrapper class is the absence of event metadata so I extended the class and added two. They are the ‘bufferingChange’ and ‘playheadChange’ events that are dispatched by the MediaPlayer class and re-dispatched by the wrapper. This allows you to listen for these events from within your flex tag like so …

  1. <players:MediaPlayerWrapperExtension
  2.    
  3.    id="wrapper"
  4.    width="100%"
  5.    height="100%"
  6.    
  7.    playheadChange="{debugTxt.text='PLAYHEAD: '+wrapper.playhead}"
  8.    />

In the code above the playheadChange event is available as a Flex event in my tag because of the metadata added to my class like so …

  1. package com.lyraspace.video.players
  2. {
  3.  import com.adobe.strobe.players.MediaPlayerWrapper;
  4.  
  5.  [Event(name="bufferingChange", type="org.openvideoplayer.events.BufferingChangeEvent")]
  6.  [Event(name="playheadChange", type="org.openvideoplayer.events.PlayheadChangeEvent")]
  7.  public class MediaPlayerWrapperExtension extends MediaPlayerWrapper
  8.  {
  9.   public function MediaPlayerWrapperExtension()
  10.   {
  11.    super();
  12.   }
  13.  }
  14. }

Here’s an example with the source.

Here’s the Application class. View-source to look at the wrapper class and the extension.

I’ve posted this quickly so anyone interested can get this working quickly but there’s a lot to be done with this wrapper. I need to add more metadata for a start and I need to take a good look at the binding.

More soon.

Slick Flex Tree control

Actionscript, Flex 6 Comments »

Following on from the recent post about automatically closing the open branches of the Tree control when you open a new branch; this is a slicker implementation that does the same thing but allows you to keep the animation. Currently the Flex control falls over if you try and animate multiple branches opening or closing.

Get Adobe Flash player

The main thing to point out here is that this example also works if you click the Tree disclosure icon (the little triangle) as well as the item. Most of the examples out there in the blogosphere that show you how to click on items to open branches forget that the disclosure button will open/close the branch and ignore the itemClick handler you’ve setup.

I listen for the itemOpening and itemClick events and pass on to a method called handleSelectedItem. This method then checks the depth of the selected item like so.

  1. var d:int = TreeListData(TreeItemRenderer(tree.itemToItemRenderer(selectedItem)).listData).depth;

This looks crazy but you need to grab the itemRenderer’s listData property to find the depth of the object. It’s quite convoluted but you can grab the renderer with the Tree’s itemToItemRenderer method, cast it to the default TreeItemRenderer class and cast the listData property to the default TreeListData class to get the depth property off that … phew!

We need the depth because I only want to work with the root level branches which is level 1 in the case of a Tree. I then cycle through the Tree’s dataprovider which gives me the items in my XMLListCollection. These will correspond to the root level items as they are XML nodes with all of the children nodes (branches) in them. I can then look for siblings to the selected item using the getRoot method and close any open siblings.

  1. if(tree.isItemOpen(i) &amp;&amp; i!=selectedItem &amp;&amp; idepth==1 &amp;&amp; isSibling)
  2.                   {
  3.                    tree.addEventListener(TreeEvent.ITEM_CLOSE,itemClosed);
  4.                    tree.expandItem(i,false,true,true); // CLOSE SIBLING
  5.                    openInstantly = false;
  6.                   }

I create an eventListener to listen for when the open root level branch is closed and because there will ever only be one branch closing I can use animation. The openInstantly Boolean prevents the selectedItem from opening … yet. When the closed item has finished I run a short Timer delay to make sure the animation listeners are all cleared and then open the selected item.

Here’s the Application class:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:Application
  3.  
  4.  xmlns:mx="http://www.adobe.com/2006/mxml"
  5.  layout="absolute"
  6.  width="200"
  7.  height="300"
  8.  >
  9.  
  10.  <mx:Script>
  11.  
  12.   <![CDATA[
  13.  
  14.   import mx.controls.treeClasses.TreeItemRenderer;
  15.   import org.osflash.thunderbolt.Logger;
  16.   import com.criticalmass.gucci.homepage.renderers.CustomTreeItemRenderer;
  17.   import mx.controls.listClasses.IListItemRenderer;
  18.   import mx.controls.treeClasses.TreeListData;
  19.  
  20.   import mx.collections.XMLListCollection;
  21.   import mx.events.TreeEvent;
  22.   import mx.controls.Tree;
  23.   import mx.events.ListEvent;
  24.  
  25.   private var dpx:XML = <nav>
  26.    
  27.    <node label="Womens">
  28.     <node label="Flora by Gucci" url="assets/swf/movies/flora.swf" />
  29.     <node label="Gucci by Gucci" url="assets/swf/movies/gucci.swf" />
  30.     <node label="Classics" url="assets/swf/movies/classics.swf" >
  31.      <node label="Classic 1" url="http://gucci.com/class/classic1.html" />
  32.      <node label="Classic 2" url="http://gucci.com/class/classic1.html" />
  33.      <node label="Classic 3" url="http://gucci.com/class/classic1.html" />
  34.     </node>
  35.    </node>
  36.    
  37.    <node label="Mens">
  38.     <node label="Pour Homme" url="assets/swf/movies/ph.swf" >
  39.      <node label="Pour Homme 1" url="http://gucci.com/ph/classic1.html" />
  40.      <node label="Pour Homme 2" url="http://gucci.com/ph/classic2.html" />
  41.     </node>
  42.    </node>
  43.    
  44.    <node label="Boys">
  45.     <node label="Pour Homme" url="assets/swf/movies/ph.swf" >
  46.      <node label="Pour Homme 1" url="http://gucci.com/ph/classic1.html" />
  47.      <node label="Pour Homme 2" url="http://gucci.com/ph/classic2.html" />
  48.     </node>
  49.    </node>
  50.    
  51.   </nav>;
  52.  
  53.   private var dp:XMLListCollection = new XMLListCollection(dpx.children());
  54.  
  55.   private var selectedItem:Object;
  56.  
  57.   private var timeDelay:Timer;
  58.  
  59.   //-----------------------------------------------------------------------------------
  60.   private function treeItemOpening(e:TreeEvent):void
  61.   {
  62.    if(!tree.isItemOpen(e.item))
  63.    {
  64.     selectedItem = e.item;
  65.     handleSelectedItem();
  66.    }
  67.   }
  68.   //-----------------------------------------------------------------------------------
  69.   private function treeItemClick(e:ListEvent):void
  70.   {
  71.                selectedItem = Tree(e.currentTarget).selectedItem;
  72.    handleSelectedItem();
  73.            }
  74.            
  75.            //-----------------------------------------------------------------------------------
  76.   private function handleSelectedItem():void
  77.   {
  78.    
  79.    var openItems:Array = tree.openItems as Array;
  80.             var openInstantly:Boolean = true;
  81.    
  82.                var d:int = TreeListData(TreeItemRenderer(tree.itemToItemRenderer(selectedItem)).listData).depth;
  83.                
  84.                if(tree.dataDescriptor.isBranch(selectedItem))
  85.                {
  86.                 for each (var i:Object in tree.dataProvider)
  87.                 {
  88.                  var idepth:int = TreeListData(TreeItemRenderer(tree.itemToItemRenderer(i)).listData).depth;
  89.      var isSibling:Boolean = XML(getRoot(i)).@label != XML(getRoot(selectedItem)).@label;        
  90.                  if(tree.isItemOpen(i) && i!=selectedItem && idepth==1 && isSibling)
  91.                  {
  92.                   tree.addEventListener(TreeEvent.ITEM_CLOSE,itemClosed);
  93.                   tree.expandItem(i,false,true,true); // CLOSE SIBLING
  94.                   openInstantly = false;
  95.                  }
  96.                 }
  97.                
  98.                 if(openInstantly) tree.expandItem(selectedItem,!tree.isItemOpen(selectedItem),true,false);
  99.                }
  100.                else
  101.                {
  102.                 // Clicked on an item -- DO STUFF!
  103.                }
  104.   }
  105.  
  106.   //-----------------------------------------------------------------------------------
  107.            /*
  108.             Function for accessing the Root item of the Tree
  109.            */
  110.            private function getRoot(childObj:Object):Object
  111.            {
  112.             var parentObj:Object = tree.getParentItem(childObj);
  113.             if(parentObj != null) return getRoot(parentObj);
  114.             else return childObj;
  115.            }
  116.  
  117.   //-----------------------------------------------------------------------------------
  118.   /*
  119.    Item closed handler
  120.   */
  121.   private function itemClosed(e:TreeEvent):void
  122.   {
  123.    tree.removeEventListener(TreeEvent.ITEM_CLOSE,itemClosed);
  124.    
  125.    timeDelay = new Timer(200,1);
  126.    timeDelay.addEventListener(TimerEvent.TIMER_COMPLETE,openSelectedItem);
  127.    timeDelay.start();
  128.   }
  129.   //-----------------------------------------------------------------------------------
  130.   private function openSelectedItem(e:TimerEvent):void
  131.   {
  132.    timeDelay.removeEventListener(TimerEvent.TIMER_COMPLETE,openSelectedItem);
  133.    if(selectedItem) tree.expandItem(selectedItem,true,true,false);
  134.   }
  135.  ]]>
  136.  </mx:Script>
  137.  
  138.  <mx:Tree
  139.  
  140.   id="tree"
  141.   width="200"
  142.   height="300"
  143.   dataProvider="{dp}"
  144.   labelField="@label"
  145.   itemClick="treeItemClick(event)"
  146.   itemOpening="treeItemOpening(event)"
  147.   />
  148.  
  149. </mx:Application>
WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in