Showcase

1 comment0 views
1 Star2 Stars

Using Metadata Tags in Components

Category: Flex Components    |    42 views    |    1 Comment

Metadata tags are special tags that are inserted within your source code that give the compiler information on how to compile the application. There are 12 documented metadata tags, each of which is described here.

[ArrayElementType]

Defining an Array is usually very generic in nature because the elements of the Array can be of any type. However, using the ArrayElementType metadata tag allows you to define the data types of the array elements. Here is the example syntax of [ArrayElementType]:


[ArrayElementType(”String”)]
public var arrayOfStrings:Array;

[ArrayElementType(”Number”)]
public var arrayOfNumbers:Array;

[ArrayElementType(”mx.core.UIComponent”)]
public var arrayOfUIComponents:Array;

[Bindable]

The Bindable metadata tag is one of the most used metadata tags because it allows for easy data synchronization within the components of your application. Bindable can be used to bind simple data, classes, complex data, and functions. To bind a simple piece of data, you must simply define the data with the metadata tag included, as shown in

SimpleBinding.mxml
<?xml version=”1.0″ encoding=”utf-8″?> <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” backgroundColor=”#FFFFFF”> <mx:Script> <![CDATA[ [Bindable] private var me:String=”Rich Tretola”; ]]> </mx:Script> <mx:Panel title=”Simple Binding” width=”500″ height=”90″ paddingTop=”10″ paddingLeft=”10″ paddingRight=”10″ paddingBottom=”10″ layout=”horizontal”> <mx:Label text=”{me}”/> </mx:Panel> </mx:Application>
BindWithGettersAndSetters.mxml
<?xml version=”1.0″ encoding=”utf-8″?> <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”> <mx:Script> <![CDATA[ private var _phoneNumeber:String = “”; // Bind getter function to phoneNumberChanged event [Bindable(event=”phoneNumberChanged”)] public function get phoneNumber():String { return _phoneNumeber; } // Setter method. public function set phoneNumber(value:String):void { if (value.length<10) { _phoneNumeber = value; } else { _phoneNumeber = phoneFormatter.format(value); } // Create and dispatch event var eventObj:Event = new Event(”phoneNumberChanged”); dispatchEvent(eventObj); } ]]> </mx:Script> <mx:PhoneFormatter id=”phoneFormatter” formatString=”() -#” validPatternChars=”#-() “/> <mx:Panel title=”Bind with Getters and Setters” width=”500″ height=”90″ paddingTop=”10″ paddingLeft=”10″ paddingRight=”10″ paddingBottom=”10″ layout=”horizontal”> <mx:TextInput id=”ti1″ change=”phoneNumber=ti1.text” maxChars=”10″ restrict=”0-9″/> <mx:TextInput id=”ti2″ text=”{phoneNumber}”/> </mx:Panel> </mx:Application>

This example has a private variable named phoneNumber, as well as a public getter and setter. The getter method uses the Bindable tag to bind to an event named phoneNumberChanged. This setter method dispatches the phoneNumberChanged event whenever its data changes. By using a setter method, the data can be manipulated before it is set to the private variable. In this example, the data is formatted only when the length of the value coming into the method is 10. When the phoneNumberChanged event is dispatched, the second TextInput component updates because its text property is bound to the phoneNumber variable.

[DefaultProperty]

The DefaultProperty metadata tag is used to set a single property as a default property of a class. This allows the property to be set within a container tag without the need to define the property name. A simple example of this would be a custom Button class.  shows a simple Button class that has the label property set as the DefaultProperty.  shows how the label is defined as a string within the custom Button container tags.

MyButton.as
package { import mx.controls.Button; [DefaultProperty(”label”)]
public class MyButton extends Button { } }
Main.mxml
<?xml version=”1.0″ encoding=”utf-8″?> <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” xmlns:comps=”*”> <comps:MyButton> <mx:String>Test</mx:String> </comps:MyButton> </mx:Application>

[Embed]

The Embed metadata tag is used to import images into your application. There are two ways to use Embed. You can either Embed the image within ActionScript and assign it to a variable (as in the first example in the following code), or you can assign it directly to the component property (using the syntax shown in the second example of the following code).


[Embed(source=”myIcon.gif”)]
[Bindable]
public var myIcon:Class;

<mx:Button label=”Icon Button 1″ icon=”{myIcon}”/>

<mx:Button label=”Icon Button 2″ icon=”{myIcon}”/>

The output from the following is identical to the previous code block. The benefits of creating the myIcon class are that it can be defined one time within a single class, and bound to multiple components within your application.

ButtonLabel.as

package { import mx.controls.Button; import flash.events.Event; // Define the custom event [Event(name=”labelChanged”, type=”flash.events.Event”)] public class ButtonLabel extends Button { // property to hold label value private var _myLabel:String; // public setter method public function set myLabel(s:String):void { _myLabel = s; this.label = s; // Create and dispatch custom event var eventObj:Event = new Event(”labelChanged”); dispatchEvent(eventObj); } } }

EventSample.mxml

<?xml version=”1.0″ encoding=”utf-8″?> <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” xmlns:comps=”*” backgroundColor=”#FFFFFF”> <mx:Script> <![CDATA[ import mx.controls.Alert; import flash.events.Event; // method to handle custom event public function labelChanged(eventObj:Event):void { myTA.text= myTA.text + “\n”+ eventObj.target.label; myTA.verticalScrollPosition = myTA.verticalScrollPosition + 20; } ]]> </mx:Script> <mx:Panel title=”Event Sample” width=”500″ height=”275″ paddingTop=”10″ paddingLeft=”10″ paddingRight=”10″ paddingBottom=”10″ layout=”absolute”> <mx:TextInput id=”buttonLabelTI” change=”myButton.myLabel=buttonLabelTI.text” x=”10″ y=”9″/> <!–Instantiate custom class and define method to handle labelChanged event–> <comps:ButtonLabel id=”myButton” labelChanged=”labelChanged(event);” x=”10″ y=”39″/> <mx:TextArea id=”myTA” width=”200″ height=”200″ x=”249″ y=”10″/> </mx:Panel> </mx:Application>

[Effect]

The Effect metadata tag is used to define a custom effect that will be dispatched when an event occurs. This can be easily demonstrated by building on the earlier Event examples. By simply changing a single line to the ButtonLabel class , an effect is defined that can be assigned to an Effect instance

Adding the Effect Metadata Tag
Adding labelChangedEffect to the Component Instantiation MXML Tag
<comps:ButtonLabel id=”myButton” labelChanged=”labelChanged(event);” labelChangedEffect=”myEffect” x=”10″ y=”39″/>

[IconFile]

IconFile is used to identify the filename of a jpg, gif, or png file that will be used as the icon for your custom class. Whereas the [Embed] metadata tag can be used to embed image files, SWF files, music files, video files, and so on, IconFile is only used to embed a file that will be used as the icon for the custom class. Here is the example of the IconFile syntax:


[IconFile(”icon.png”)]
public class CustomButton extends Button
{

[Inspectable]

The Inspectable metadata tag is used to define the attributes of your custom component that you would like to display within the code hints and property inspector of Flex Builder 2. The example shown in  defines a variable named ccType that is inspectable. It defines a defaultValue of Visa, a category of Credit Card, and enumeration values of Visa, Mastercard, Discover, and American Express.

Listing 14-11: MyComponent.mxml

}

<mx:Button label=”Icon Button 1″ icon=”@Embed(source=myIcon.gif’)”/>

<mx:Button label=”Icon Button 2″ icon=”@Embed(source=myIcon.gif’)”/>

[Event]

The Event metadata tag is used to declare events that will be dispatched by your custom class. Adding this metadata tag to your class definition allows you to add an event handler function to the MXML tag used to instantiate your custom class.  creates a custom Button class that will dispatch an event whenever its label property changes. The main application file shown in instantiates the custom Button and creates the event handler function, which dumps the new label property to a TextArea component to show the changes that occur.

<?xml version=”1.0″ encoding=”utf-8″?> <mx:HBox xmlns:mx=”http://www.adobe.com/2006/mxml”> <mx:Script> <![CDATA[ [Inspectable(defaultValue=”Visa”, enumeration=”Visa,Mastercard,Discover,American Express” category=”Credit Card” type=”String”)] public var ccType:String; ]]> </mx:Script> </mx:HBox>

[InstanceType]

The InstanceType metadata tag is used to declare the type of object that will be allowed when declaring a variable as IDeferredInstance within a template object. The syntax of InstanceType looks like this:


[InstanceType(”package.className“)]

[NonCommittingChangeEvent]

The NonCommittingChangeEvent is a metadata tag that will prevent a change from occurring when a specified event occurs.  demonstrates how this works. A private variable named s of type String is created and bound to the ti2 TextInput component. The other TextInput component with the id of ti1 sets the value of s equal to the value of its text property whenever the text changes. Additionally, the Binding metadata tag attached to the s variable is set to bind when the trigger Binding event is dispatched. The triggerBinding event is dispatched only when the Enter key is pressed while typing in the ti1 TextInput component.

NonCommittingChangeEventSample.mxml
<?xml version=”1.0″ encoding=”utf-8″?> <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” backgroundColor=”#FFFFFF”> <mx:Script> <![CDATA[ import flash.events.Event; private var eventObj:Event; [Bindable(event=”triggerBinding”)] [NonCommittingChangeEvent(”change”)] private var s:String; private function triggerBinding():void{ eventObj = new Event(”triggerBinding”); dispatchEvent(eventObj); } ]]> </mx:Script> <mx:Panel title=”NonCommittingChangeEvent Sample” width=”500″ height=”90″ paddingTop=”10″ paddingLeft=”10″ paddingRight=”10″ paddingBottom=”10″ layout=”horizontal”> <mx:TextInput id=”ti1″ change=”s=ti1.text” enter=”triggerBinding()” /> <mx:TextInput id=”ti2″ text=”{s}” /> </mx:Panel> </mx:Application>

[RemoteClass]

RemoteClass is used to bind an ActionScript class to a Java class. This will allow for automatic data type conversions. Following is an example of an ActionScript class named MyClass in package com.mydomain being bound to a Java class named MyClass in package com.mydomain:


package com.mydomain {
[Bindable]
[RemoteClass(alias=”com.mydomain.MyClass”)]
public class MyClass {
public var id:int;

public var myText:String;

}
}

[Style]

The Style metadata tag is used to define custom style properties for your components. Simply add the Style metadata tag or tags to your class definition, and then use the getStyle method to retrieve its value.

and  show examples of how to define two styles named borderColor and fillColor, both of which are defined as uint data types. The styles are set within the component tag when the class is instantiated. The updateDisplayList function is overridden and the custom styles are used to draw the circle border and fill.

CustomCircle.as
package { import mx.core.UIComponent; [Style(name=”borderColor”,type=”uint”,format=”Color”,inherit=”no”)] [Style(name=”fillColor”,type=”uint”,format=”Color”,inherit=”no”)] public class CustomCircle extends UIComponent { public function CustomCircle(){ super(); } override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth, unscaledHeight); graphics.lineStyle(1, getStyle(”borderColor”), 1.0); graphics.beginFill(getStyle(”fillColor”),1.0); graphics.drawEllipse(0,0,100,100); } } }
StyleSample.mxml
<?xml version=”1.0″ encoding=”utf-8″?> <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” xmlns:comps=”*” backgroundColor=”#FFFFFF”> <mx:Panel title=”Style Sample” width=”200″ height=”200″ paddingTop=”10″ paddingLeft=”10″ paddingRight=”10″ paddingBottom=”10″ layout=”horizontal”> <comps:CustomCircle borderColor=”#000000″ fillColor=”#FF0000″ /> </mx:Panel> </mx:Application>

Share/Save/Bookmark

 

Flex Components

Category: Flex Components    |    75 views    |    Add a Comment

This chapter discusses many aspects of custom components. It includes examples of using custom events in components and examples of all of the different types of metadata tags that can be used in custom components. It also includes examples of how to compile and deploy your custom components using both the free Flex SDK and Flex Builder.

Custom Events in Components

The ability to define and dispatch events from custom components makes it very easy to get feedback from your components and adjust your application. Adding a custom event to a component is a very simple thing to do. First, define the events within metadata tags at the top of the class definition and then dispatch the event when the criteria you determined necessary have been met.

Dispatching Custom Events

TextInputWithCountEvent.as
package { import mx.controls.TextInput; import flash.events.Event;
[Event(name=”lengthOf5Event”, type=”flash.events.Event”)]
[Event(name=”lengthOf10Event”, type=”flash.events.Event”)]
public class TextInputWithCountEvent extends TextInput
{ private var _myText:String; private var eventObj:Event;
public function set myText(s:String):void{ _myText = s;
this.text = s; if(s.length == 5){ // Create and dispatch custom event eventObj = new Event(”lengthOf5Event”); dispatchEvent(eventObj); }
else if (s.length==10){ eventObj = new Event(”lengthOf10Event”);
dispatchEvent(eventObj);
} } } }

This class declares two custom events by using the Event metadata tag right above the class declaration. There is additional information on the Event metadata tag later in this chapter. The set myText function accepts a String as an argument and sets the text property of the class to the value. It also will dispatch an event when the length of the String is 5 or 10 characters. To dispatch the event, first instantiate the event object and then use the dispatchEvent method to dispatch the event.

The main file, shown in, creates an instance of the TextInputWithCountEvent custom component and adds event handlers to respond when a custom event is dispatched. The event handler functions simply to show an Alert to demonstrate that they received the dispatched event.

TextInputLengthEventSample.mxml
<?xml version=”1.0″ encoding=”utf-8″?> <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” xmlns:comps=”*”
backgroundColor=”#FFFFFF”> <mx:Script>
<![CDATA[ import mx.controls.Alert; import flash.events.Event; //
method to handle custom event public
function lengthOf5EventHandler(eventObj:Event):void
{ mx.controls.Alert.show(”Length is 5″); } public function lengthOf10EventHandler(eventObj:Event):void { mx.controls.Alert.show(”Length is 10″); } ]]> </mx:Script>
<mx:Panel title=”Text Input Length Event Sample” width=”300″ height=”150″ paddingTop=”10″ paddingLeft=”10″ paddingRight=”10″ paddingBottom=”10″
layout=”absolute”> <!–Instantiate custom class and define method to handle labelChanged event–> <comps:TextInputWithCountEvent id=”myTI” myText=”{myTI.text}” lengthOf5Event=”lengthOf5EventHandler(event);” lengthOf10Event=
“lengthOf10EventHandler(event);” horizontalCenter=”0″ verticalCenter=”0″/> </mx:Panel> </mx:Application>

Share/Save/Bookmark

 

Creating Advanced Components in ActionScript

Category: Flex Components    |    93 views    |    Add a Comment

The shows an example of an advanced ActionScript component that includes many UIComponents, private variables, getters, setters, styles, and events. The class extends Canvas and is named MultiRowTabs. It has several import statements to give access to Flex containers, controls, and collections. There are also import statements to allow the use of the TabSkin and MouseEvent classes.

MultiRowTabs.as

package com.mydomain.components { import mx.containers.Canvas; import mx.containers.HBox; import mx.containers.ViewStack; import mx.controls.Button; import mx.collections.ArrayCollection; import mx.skins.halo.TabSkin; import flash.events.MouseEvent; public class MultiRowTabs extends Canvas { // declare class properties public var myViewStack:ViewStack; public var tabsPerRow:Number = 4; public var rowHeight:Number = 22; public var tabRows:Array = new Aray(); private var _dp:ArrayCollection; private var buttonArray:ArrayCollection; // default constructor public function MultiRowTabs(){ } // getters and setters public function get dp():ArrayCollection{ return _dp; } public function set dp(a:ArrayCollection):void{ _dp=a; this.removeAllChildren(); buttonArray = new ArrayCollection(); var start:Number = 0; var end:Number = tabsPerRow; var currentY:Number = 0; // add rows for(var i:Number=0; i<this.dp.length/tabsPerRow; i++){ // add a new row of tabs by adding a HBox tabRows[i] = new HBox(); // set HBox properties and style tabRows[i].percentWidth=100; tabRows[i].y = currentY; tabRows[i].setStyle(”paddingTop”,0); tabRows[i].setStyle(”paddingBottom”,0); tabRows[i].setStyle(”horizontalGap”,0); tabRows[i].setStyle(”verticalGap”,0); currentY = currentY + rowHeight; // add the HBox as a child this.addChild(tabRows[i]); // add buttons for(var j:Number=start; j<end; j++){ // add button and set properties and style var button:Button = new Button(); button.label = this.dp[j].label; button.data = i + “|” + j; button.setStyle(”upSkin”,TabSkin); button.setStyle(”downSkin”,TabSkin); button.setStyle(”overSkin”,TabSkin); button.setStyle(”selectedUpSkin”,TabSkin); button.setStyle(”selectedOverSkin”,TabSkin); button.setStyle(”selectedDownSkin”,TabSkin); button.setStyle(”selectedDisabledSkin”,TabSkin); button.percentWidth=100; button.height = rowHeight; // add eventListener for mouse clicks button.addEventListener(MouseEvent.CLICK, clickHandler); // add button to the HBox tabRows[i].addChild(button); // set button selected as false button.selected=false; // set as selected button if in the o position if(j==0)button.selected=true; buttonArray.addItem(button); } // calculate buttons per row start = start + tabsPerRow; end = end + tabsPerRow; if(end > this.dp.length){ end = this.dp.length; } var myRowNumber:Number = 0; var newCurrentY:Number = 0; // position rows so that selected tab is in bottom row for(var k:Number=0; k<tabRows.length; k++){ if(myRowNumber != k){ tabRows[k].y = newCurrentY; newCurrentY = newCurrentY + rowHeight; } } tabRows[myRowNumber].y = newCurrentY; } } private function clickHandler(event:MouseEvent):void{ // create array to hold row and button info var splitArray:Array = event.target.data.split(”|”); var myRowNumber:Number = Number(splitArray[0]); var myButtonIndex:Number = Number(splitArray[1]); // set viewStack selectedIndex this.myViewStack.selectedIndex=myButtonIndex; // set all buttons selected property to false for(var i:Number=0; i<buttonArray.length; i++){ this.buttonArray[i].selected = false; } // set clicked button to selected event.target.selected=true; var currentY:Number = 0; // position rows so that selected tab is in bottom row for(var j:Number=0; j<tabRows.length; j++){ if(myRowNumber != j){ this.tabRows[j].y = currentY; currentY = currentY + rowHeight; } } this.tabRows[myRowNumber].y = currentY; } } }

Several class properties are defined with both public and private access. The _dp property (which is declared as a private ArrayCollection) is the most important property of the class because it also has a public setter that re-creates the component whenever the dp property changes. The set dp function first clears all of the current child objects, then creates rows of HBox components and adds buttons to each row to act as the tabs. The buttons are styled as tabs, given eventListeners, and assigned data to hold their button index and row number. The clickHandler function is responsible for changing the ViewStack index, setting the clicked button to the selected state, and moving the selected button’s row to the bottom of the component.

Share/Save/Bookmark