24 October 2011
A good understanding of Flex 3 and basic understanding of Flex 4.5 is recommended. You should also complete Part 1 of this series before beginning this one.
Beginning
This article is Part 2 of a four-part series in which you import the Flex 3 Dashboard demonstration application available on the Flex Developer Center into Flash Builder 4.5, and then migrate the application to Flex 4.5 to take advantage of the Flex 4.5 Spark architecture and components.
Although a key feature of Flex 4.5 is its support for creating mobile applications in Flex, this article series does not cover converting the Dashboard application to a mobile application. A future article series will cover creating a mobile Dashboard application.
Part 1 of this series described how to import the Flex 3 Dashboard into Flash Builder 4.5 and make just enough changes to get it to compile and run. Part 2 of the series (this article) begins the process of migrating the Dashboard code to Flex 4.5.
Before you complete Part 2, you must complete the steps in Part 1. Alternatively, you can download the Dashboard-Part2-Start.zip sample file, unzip it, import it into Flash Builder, and continue from there. The other sample file for this article, Dashboard-Part2-End.zip, contains a project in which all the steps in Part 2 have already been completed. You may use this project as a reference if you wish.
Note: The Flex 3 Dashboard application hosted on the Adobe examples site does not display exactly the same (see Figure 1) as it will if you download the source code and compile it using Flex 3 (and the Flex 3.4 SDK). In this article series, you will migrate the Dashboard application to Flex 4.5 so it displays as it does when you compile it using Flex 3, not as it displays as hosted on the Adobe examples site.
The Dashboard application saves information on the location and the state of each pod to a Flex SharedObject, which is a similar concept to using cookies on a web page. As you go through the process of converting the Dashboard application to Flex 4.5, you may change the position of pods within the Dashboard, minimize or maximize pods, and so on. Runtime errors can also cause an unstable state to be saved in the SharedObject. In either case, you may need to reset the Dashboard to its initial state before continuing. You can do this by deleting the SharedObject file on your machine. The location of this file depends on the operating system you are using:
The Dashboard is a nontrivial application with code in 19 files (not including data and image files). The scope of the application presents a challenge in guiding you through the many changes required to migrate the Dashboard to Flex 4.5.
The general approach for the code conversion is to start with the top application object and proceed down through the various levels of the container hierarchy. However, changes in one file often make it necessary to make changes in other files to avoid errors and still be able to launch the application.
One goal of the approach followed in this series is to maintain the application, as much as possible, in a state in which it can be launched with no errors (warnings are acceptable).
Some sections include numerous steps for converting code, and missing or improperly applying one step can make it difficult to proceed. Take your time, read each step carefully, and keep these tips in mind:
id of an MXML tag, or more generalized text such as, "near the top of the file".You'll start with some basic changes to the main application file, main.mxml.
In main.mxml begin by changing the namespace prefix in the opening and closing Application tags from mx to s , to use the new Spark application class.
<mx:Application to <s:Application and change </mx:Application> to </s:Application> .Next, replace the one Flex 3 namespace definition with the three Flex 4.5 namespace definitions in the opening Application tag.
xmlns:mx="/2006/mxml" with the following lines:<mx:Script> tag to use the Flex 4.5 fx namespace instead of the mx namespace.</mx:Script> to </fx:Script> .The Flex 3 Dashboard <mx:Application> tag defaults to vertical layout, but the Flex 4.5 Spark <s:Application> tag defaults to BasicLayout (the Flex 4.5 equivalent of absolute layout). You'll need to specify a vertical layout for the Application container.
<mx:TabBar> component:The Dashboard application should compile with no errors and launch. Compared with the Flex 3 version, the application has some display issues, such as the background image not displaying (see Figure 2), but these will be eliminated as you continue to migrate the application to Flex 4.5.
You can see other differences when you compare the application with the Flex 3 version (see Figure 3).
Now that you've updated the main Application container and the namespaces, the next step is to implement a custom skin for the Application container.
The custom skin you implement will restore the Application container background image.
Next, you'll create the skin.
Flash Builder will create a new file named CustomApplicationSkin.mxml in the src/skins folder.
<s:Application> tag at the top of file main.mxml:skinClass="skins.CustomApplicationSkin"
Next you'll modify the skin class to implement styles previously defined in styles.css, and also the backgroundSize style property you removed in Part 1. You may want to refer to the Application type selector in assets/styles.css, as its styles will be implemented in the skin. CSS styles are not used in Flex 4.5 as they are in Flex 3 because the Spark architecture strives to provide a cleaner separation of a component's visual elements from its logic.
Rect tag with the id backgroundRect . Replace the entire Rect tag and its contents with the following BitmapImage tag:<s:BitmapImage top="0" bottom="0" left="0" right="0"
source="@Embed(source='/assets/application_background.png',
scaleGridTop='94', scaleGridBottom='791',
scaleGridLeft='350', scaleGridRight='690')"/>
Notice that this skin sets the top , bottom , left , and right constraint properties to 0 , which causes the image to fill the entire application background and fulfills the role of the backgroundSize style property removed from the <mx:Application> tag.
The background-color and background-gradient-colors styles in styles.css (and the Application tag) are unnecessary because the default Flex 4.5 Spark application background is white. The color style in styles.css is likewise unnecessary, because the default text color for the application is black.
Launch the application and you will see the background image applied to the application as it was for the Flex 3 Dashboard application (see Figure 6).
Next you'll make changes to use the new Flex 4.5 Spark TabBar.
Make the following changes in main.mxml:
s namespace prefix instead of the mx prefix.dataProvider value in binding curly braces: {viewStack} .change event instead of to the itemClick event.After completing these steps, the TabBar tag should look similar to this:
<s:TabBar id="tabBar"
change="onItemClickTabBar(event)"
height="35" dataProvider="{viewStack}" />
Now you need to make additional changes that are necessary because the Spark TabBar control dispatches a different event when the selected tab is changed.
import mx.events.ItemClickEvent;
import spark.events.IndexChangeEvent;
onItemClickTabBar() function in main.mxml and in the function signature, replace ItemClickEvent with IndexChangeEvent :private function onItemClickTabBar(e:IndexChangeEvent):void
e.index to e.newIndex because the IndexChangeEvent provides access to the clicked tab through a different property.onItemClickTabBar() function definition (near the bottom of the onResultHttpService() function definition).onItemClickTabBar(new ItemClickEvent(ItemClickEvent.ITEM_CLICK, false, false, null, index));
onItemClickTabBar(new IndexChangeEvent(IndexChangeEvent.CHANGE, false, false, -1, index));
This change is necessary because the code creates an event instance to simulate clicking a tab when the application is first launched.
It should compile with no errors. Launch the application and click on its tabs to ensure they still work.
This section and the next implement two custom skins so the tabs in the TabBar component display as they do in the Flex 3 Dashboard application. The skin in this section is for the TabBar component, and the skin in the next section is for the ButtonBarButton components making up the tabs.
To create the TabBar custom skin, follow these steps:
Flash Builder will create a new file named CustomTabBarSkin.mxml in the src/skins folder.
<s:TabBar> tag at the bottom of the main.mxml file:skinClass="skins.CustomTabBarSkin"
focusThickness="0" to the <s:ButtonBarButton> tag, so the tabs do not display a focus border when leaving and returning to the Dashboard window:<s:ButtonBarButton skinClass="spark.skins.spark.TabBarButtonSkin"
focusThickness="0"/>
In this section you'll create a custom skin for the ButtonBarButton components that make up the tabs. There are more steps to creating this skin, so follow along carefully.
Flash Builder will create CustomButtonBarButtonSkin.mxml in the src/skins folder.
<s:ButtonBarButton> tag at the bottom of the file replace spark.skins.spark.TabBarButtonSkin with skins.CustomButtonBarButtonSkin .The tag will now be:
<s:ButtonBarButton skinClass="skins.CustomButtonBarButtonSkin"
focusThickness="0"/>
Next you'll apply some of the more general styles that were defined in styles.css, specifically the tabBarButton and tabBarButtonSelected class selectors.
labelDisplay Label change the textAlign property value from center to left .labelDisplay properties left , right , and top style properties. Keep the left property value at 10 , but change right to 20 , and change top to -4 .labelDisplay Label tag: color="#333333" fontSize="12" fontFamily="arial"
fontWeight="bold" to the same tag. The Flex 3 Label control text is bold by default, but in Flex 4.5 the default fontWeight is "normal" .The next three general style properties require an explanation. In the tabBarButton style in styles.css, the text-roll-over-color property represents the tab text color when the pointer hovers over an unselected tab. In the tabBarButtonSelected style, the text-roll-over-color property represents the tab text color when the pointer hovers over a tab that is selected, and the color property represents the text color when the pointer is not hovering over a selected tab. Although the text-roll-over-color style property is used twice here, it is used in two different styles, so there is no conflict.
labelDisplay Label (this is an example of the new MXML states syntax at work): color.upAndSelected="#003399"
color.overAndSelected="#003399"
color.over="#858585"
The labelDisplay Label tag should now look similar to the following:
<s:Label id="labelDisplay"
textAlign="left"
verticalAlign="middle"
maxDisplayedLines="1"
horizontalCenter="0" verticalCenter="1"
left="10" right="20" top="-4" bottom="2"
color="#333333" fontSize="12" fontFamily="arial"
fontWeight="bold"
color.upAndSelected="#003399"
color.overAndSelected="#003399"
color.over="#858585">
</s:Label>
Lastly you need to apply the six graphic image styles for the actual tab display. Actually, only two individual images are used, one for the up , over , and down states of unselected tabs, and another for the up , over , and down states of the currently selected tab.
<fx:Script> tag except the following lines, which should remain:static private const exclusions:Array = ["labelDisplay"];
override public function get colorizeExclusions():Array {return exclusions;}
override protected function initializationComplete():void
{
useChromeColor = true;
super.initializationComplete();
}
</s:states> closing tag to the end of layer 7. Layer 8, which contains the labelDisplay Label, will remain.labelDisplay element. This adds two <s:BitmapImage> components, one for each of the tab images.<s:BitmapImage source="@Embed('/assets/tab_up.png', scaleGridTop='11',
scaleGridBottom='30', scaleGridLeft='10', scaleGridRight='92')"
includeIn="up, over, down" width="{labelDisplayWidth}"/>
<s:BitmapImage source="@Embed('/assets/tab_selected.png', scaleGridTop='13',
scaleGridBottom='31', scaleGridLeft='9', scaleGridRight='91')"
includeIn="upAndSelected, overAndSelected, downAndSelected"
width="{labelDisplayWidth}"/>
Notice the use of the includeIn property, which allows you to specify the states for which each image should display. Also notice that the width is set using binding to a variable named labelDisplayWidth ; this is necessary so the TabBar tabs adjust their size as appropriate for the text of each tab.
labelDisplayWidth variable and a method to set its value at the beginning of the <fx:Script> tag:[Bindable] private var labelDisplayWidth:Number = 0;
private function setTabWidth():void{
labelDisplayWidth = Label(labelDisplay).width + Label(labelDisplay).left
+ Label(labelDisplay).right + 3;
}
Note: The labelDisplay skin part has a type of IDisplayText, so you need to cast it as Label in the skin ActionScript code.
<s:Label id="labelDisplay"> tag:creationComplete="setTabWidth();"
When you launch the application, you'll see that the tab text is not positioned exactly as it was for the Flex 3 Dashboard application. In the Flex 4.5 Dashboard, the text is slightly lower than in the Flex 3 Dashboard (see Figure 7).
<s:states> tag as follows:<s:states>
<s:State name="up" stateGroups="nonSelected"/>
<s:State name="over" stateGroups="nonSelected" />
<s:State name="down" stateGroups="nonSelected" />
<s:State name="disabled" stateGroups="nonSelected, disabledStates" />
<s:State name="upAndSelected" stateGroups="selectedStates" />
<s:State name="overAndSelected" stateGroups="selectedStates" />
<s:State name="downAndSelected" stateGroups="selectedStates" />
<s:State name="disabledAndSelected" stateGroups="selectedStates, disabledStates" />
</s:states>
horizontalCenter and verticalCenter properties of the labelDisplay tag, change the left property to 12 , and replace the top property with top.selectedStates="0" top.nonSelected="-2" so the labelDisplay Label tag is similar to the following:<s:Label id="labelDisplay"
textAlign="left"
verticalAlign="middle"
maxDisplayedLines="1"
left="12" right="20" top.selectedStates="0" top.nonSelected="-2"
bottom="2"
color="#333333" fontSize="12" fontFamily="arial"
fontWeight="bold"
color.upAndSelected="#003399"
color.overAndSelected="#003399" color.over="#858585"
creationComplete="setTabWidth();">
</s:Label>
These changes specify a different position for the tab label when the tab is selected.
You are done with skinning the TabBar. The tabs should display as they do in the Flex 3 Dashboard, even when you hover over the tabs.
You've now completed Part 2 of this four-part series, which included the first code changes to migrate the Flex 4.5 Spark controls and architecture. In Part 3, you'll make the changes needed to have the application's ViewStack use the new Flex 4.5 Spark NavigatorContent container.
For more information on Flex 4.5—and in particular features relevant to the Dashboard application—see the following resources:
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.
Note: You may use the sample code in your products, commercial or not.