Flex3 Appdev Beta1
Flex3 Appdev Beta1
® ™
Adobe Flex 3
Developer’sGuide
Flex 3 Beta 1
© 2007 Adobe Systems Incorporated. All rights reserved.
If this guide is distributed with software that includes an end-user agreement, this guide, as well as the software described in it, is
furnished under license and may be used or copied only in accordance with the terms of such license. Except as permitted by any
such license, no part of this guide may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means,
electronic, mechanical, recording, or otherwise, without the prior written permission of Adobe Systems Incorporated. Please note
that the content in this guide is protected under copyright law even if it is not distributed with software that includes an end-user
license agreement.
The content of this guide is furnished for informational use only, is subject to change without notice, and should not be
construed as a commitment by Adobe Systems Incorporated. Adobe Systems Incorporated assumes no responsibility or liability
for any errors or inaccuracies that may appear in the informational content contained in this guide.
Please remember that existing artwork or images that you may want to include in your project may be protected under copyright
law. The unauthorized incorporation of such material into your new work could be a violation of the rights of the copyright
owner. Please be sure to obtain any permission required from the copyright owner.
Any references to company names in sample templates are for demonstration purposes only and are not intended to refer to any
actual organization.
Adobe, the Adobe logo, Flex, Flex Builder and Flash Player are either registered trademarks or trademarks of Adobe Systems
Incorporated in the United States and/or other countries. ActiveX and Windows are either registered trademarks or trademarks of
Microsoft Corporation in the United States and/or other countries. Linux is a registered trademark of Linus Torvalds. Solaris is a
registered trademark or trademark of Sun Microsystems, Inc. in the United States and other countries. All other trademarks are
the property of their respective owners.
This product includes software developed by the Apache Software Foundation (http://www.apache.org/). Macromedia Flash 8
video is powered by On2 TrueMotion video technology. © 1992-2005 On2 Technologies, Inc. All Rights Reserved. http://
www.on2.com. This product includes software developed by the OpenSymphony Group (http://www.opensymphony.com/).
Portions licensed from Nellymoser (www.nellymoser.com). Portions utilize Microsoft Windows Media Technologies. Copyright
(c) 1999-2002 Microsoft Corporation. All Rights Reserved. Includes DVD creation technology used under license from Sonic
Solutions. Copyright 1996-2005 Sonic Solutions. All Rights Reserved. This Product includes code licensed from RSA Data
Security. Portions copyright Right Hemisphere, Inc. This product includes software developed by the OpenSymphony Group
(http://www.opensymphony.com/).
Sorenson™ Spark™ video compression and decompression technology licensed from Sorenson Media, Inc.
Adobe Systems Incorporated, 345 Park Avenue, San Jose, California 95110, USA
Notice to U.S. government end users. The software and documentation are “Commercial Items,” as that term is defined at 48
C.F.R. §2.101, consisting of “Commercial Computer Software” and “Commercial Computer Software Documentation,” as such
terms are used in 48 C.F.R. §12.212 or 48 C.F.R. §227.7202, as applicable. Consistent with 48 C.F.R. §12.212 or 48 C.F.R.
§§227.7202-1 through 227.7202-4, as applicable, the Commercial Computer Software and Commercial Computer Software
Documentation are being licensed to U.S. Government end users (a) only as Commercial items and (b) with only those rights as
are granted to all other end users pursuant to the terms and conditions herein. Unpublished-rights reserved under the copyright
laws of the United States. Adobe Systems Incorporated, 345 Park Avenue, San Jose, CA 95110-2704, USA. For U.S.
Government End Users, Adobe agrees to comply with all applicable equal opportunity laws including, if appropriate, the
provisions of Executive Order 11246, as amended, Section 402 of the Vietnam Era Veterans Readjustment Assistance Act of
1974 (38 USC 4212), and Section 503 of the Rehabilitation Act of 1973, as amended, and the regulations at 41 CFR Parts 60-1
through 60-60, 60-250 ,and 60-741. The affirmative action clause and regulations contained in the preceding sentence shall be
incorporated by reference.
Contents
iii
Flex 3 Beta 1
iv
Flex 3 Beta 1
v
Flex 3 Beta 1
vi
Flex 3 Beta 1
vii
Flex 3 Beta 1
viii
Flex 3 Beta 1
ix
Flex 3 Beta 1
x
Flex 3 Beta 1
xi
Flex 3 Beta 1
xii
Flex 3 Beta 1
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .i
xiii
Flex 3 Beta 1
xiv
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1
CHAPTER 1
Contents
Using this manual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Accessing the Flex documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Part Description
Part 1, “Using Flex Programming Describes how to use MXML and ActionScript.
Languages”
Part 2, “Building User Interfaces Describes how to use Flex components to build the user
for Flex Applications” interface to your application.
Part 3, “Customizing the User Describes how to improve the user experience by adding
Interface” additional functionality to your application.
15
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1
Part Description
Part 5, “Data Access and Describes the Flex features that let you work with
Interconnectivity” external data and how to use Flex data representation
and data features.
Documentation set
The Flex documentation set includes the following titles:
Book Description
Flex Developer’s Guide Describes how to develop your dynamic web
applications.
Getting Started with Flex Contains an overview of Flex features and application
development procedures.
Building and Deploying Flex Describes how to build and deploy Flex applications.
Applications
Creating and Extending Flex Describes how to create and extend Flex components.
Components
Typographical conventions 17
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1
PART 1
19
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
CHAPTER 2
Developing Applications
in MXML
2
MXML is an XML language that you use to lay out user-interface components for Adobe Flex
applications. You also use MXML to declaratively define nonvisual aspects of an application,
such as access to server-side data sources and data bindings between user-interface
components and server-side data sources. This topic describes MXML and how you use
MXML to develop Flex applications.
For information on MXML syntax, see Chapter 3, “MXML Syntax,” on page 41.
Contents
About MXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Developing applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
About MXML
You use two languages to write Flex applications: MXML and ActionScript. MXML is an
XML markup language that you use to lay out user-interface components. You also use
MXML to declaratively define nonvisual aspects of an application, such as access to data
sources on the server and data bindings between user-interface components and data sources
on the server.
Like HTML, MXML provides tags that define user interfaces. MXML will seem very familiar
if you have worked with HTML. However, MXML is more structured than HTML, and it
provides a much richer tag set. For example, MXML includes tags for visual components such
as data grids, trees, tab navigators, accordions, and menus, as well as nonvisual components
that provide web service connections, data binding, and animation effects. You can also
extend MXML with custom components that you reference as MXML tags.
One of the biggest differences between MXML and HTML is that MXML-defined
applications are compiled into SWF files and rendered by Adobe® Flash® Player, which
provides a richer and more dynamic user interface than page-based HTML applications
provide.
21
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
You can write an MXML application in a single file or in multiple files. MXML also supports
custom components written in MXML and ActionScript files.
</mx:Panel>
</mx:Application>
Save this code to a file named hello.mxml. MXML filenames must end in a lowercase .mxml
file extension.
The following image shows the “Hello World” application rendered in a web browser
window:
About MXML 23
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The Flex also provides a command-line MXML compiler, mxmlc, that lets you compile
MXML files. You can use mxmlc to compile hello.mxml from a command line, as the
following example shows:
cd flexInstallDir/bin
mxmlc --show-actionscript-warnings=true --strict=true
c:/appDir/hello.mxml
In this example, flexInstallDir is the Flex installation directory, and appDir is the directory
containing hello.mxml. The resultant SWF file, hello.swf, is written to the same directory as
hello.mxml.
For more information about mxmlc, see Chapter 9, “Using the Flex Compilers,” in Building
and Deploying Flex Applications. For more information about the debugger version of Flash
Player, see Chapter 12, “Logging,” in Building and Deploying Flex Applications.
When you declare a control using an MXML tag, you create an instance object of that class.
This MXML statement creates a Button object, and initializes the label property of the
Button object to the string Submit.
An MXML tag that corresponds to an ActionScript class uses the same naming conventions as
the ActionScript class. Class names begin with an uppercase letter, and uppercase letters
separate the words in class names. Every MXML tag attribute corresponds to a property of the
ActionScript object, a style applied to the object, or an event listener for the object. For a
complete description of the Flex class library and MXML tag syntax, see the Adobe Flex
Language Reference.
Developing applications
MXML development is based on the same iterative process used for other types of web
application files such as HTML, JavaServer Pages (JSP), Active Server Pages (ASP), and
ColdFusion Markup Language (CFML). Developing a useful Flex application is as easy as
opening your favorite text editor, typing some XML tags, saving the file, requesting the file’s
URL in a web browser, and then repeating the same process.
Flex also provides tools for code debugging; for more information, see Chapter 13, “Using the
Command-Line Debugger,” in Building and Deploying Flex Applications.
Developing applications 25
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Laying out a user interface using containers
In the Flex model-view design pattern, user interface components represent the view. The
MXML language supports two types of user interface components: controls and containers.
Controls are form elements, such as buttons, text fields, and list boxes. Containers are
rectangular regions of the screen that contain controls and other containers.
You use container components for laying out a user interface, and for controlling user
navigation through the application. Examples of layout containers include the HBox
container for laying out child components horizontally, the VBox container for laying out
child components vertically, and the Grid container for laying out child components in rows
and columns. Examples of navigator containers include the TabNavigator container for
creating tabbed panels, the Accordion navigator container for creating collapsible panels, and
the ViewStack navigator container for laying out panels on top of each other.
The Container class is the base class of all Flex container classes. Containers that extend the
Container class add their own functionality for laying out child components. Typical
properties of a container tag include id, width, and height. For more information about the
standard Flex containers, see Chapter 15, “Introducing Containers,” on page 563.
The following image shows an example Flex application that contains a List control on the left
side of the user interface and a TabNavigator container on the right side. Both controls are
enclosed in a Panel container:
Panel container
<mx:HBox>
<!-- List with three items -->
<mx:List>
<mx:dataProvider>
</mx:TabNavigator>
</mx:HBox>
</mx:Panel>
</mx:Application>
The List control and TabNavigator container are laid out side by side because they are in an
HBox container. The controls in the TabNavigator container are laid out from top to bottom
because they are in a VBox container.
For more information about laying out user-interface components, see Chapter 7, “Using Flex
Visual Components,” on page 143.
<mx:HBox>
<mx:TextInput id="myText"/>
<mx:Button click="storeZipInDatabase(myText.text)"/>
</mx:HBox>
Developing applications 27
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
</mx:Application>
Typical properties of a control tag include id, width, height, fontSize, color, event
listeners for events such as click and change, and effect triggers such as showEffect and
rollOverEffect. For information about the standard Flex controls, see Chapter 10, “Using
Controls,” on page 267.
<mx:VBox>
<mx:TextInput id="myText" text="Hello World!" />
<mx:Button id="mybutton" label="Get Weather" click="writeToLog();"/>
</mx:VBox>
<mx:Script>
<![CDATA[
private function writeToLog():void {
trace(myText.text);
}
]]>
</mx:Script>
</mx:Application>
This code causes the MXML compiler to autogenerate a public variable named myText that
contains a reference to that TextInput instance. This autogenerated variable lets you access the
component instance in ActionScript. You can explicitly refer to the TextInput control’s
instance with its id instance reference in any ActionScript class or script block. By referring to
a component’s instance, you can modify its properties and call its methods.
Because each id value in an MXML file is unique, all objects in a file are part of the same flat
namespace. You do not qualify an object by referencing its parent with dot notation, as in
myVBox.myText.text.
For more information, see “Referring to Flex components” on page 60.
XML namespaces give you the ability to use custom tags that are not in the MXML
namespace. The following example shows an application that contains a custom tag called
CustomBox. The namespace value containers.boxes.* indicates that an MXML
component called CustomBox is in the containers/boxes directory.
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComps="containers.boxes.*">
<MyComps:CustomBox/>
</mx:Panel>
</mx:Application>
The containers/boxes directory can be a subdirectory of the directory that contains the
application file, or it can be a subdirectory of one of the ActionScript source path directories
assigned in the flex-config.xml file. If copies of the same file exist in both places, Flex uses the
file in the application file directory. The prefix name is arbitrary, but it must be used as
declared.
When using a component contained in a SWC file, the package name and the namespace
must match, even though the SWC file is in the same directory as the MXML file that uses it.
A SWC file is an archive file for Flex components. SWC files make it easy to exchange
components among Flex developers. You need only exchange a single file, rather than the
MXML or ActionScript files and images and other resource files. Also, the SWF file inside a
SWC file is compiled, which means that the code is obfuscated from casual view. For more
information on SWC files, see Chapter 9, “Using the Flex Compilers,” in Building and
Deploying Flex Applications.
Developing applications 29
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Using MXML to trigger run-time code
Flex applications are driven by run-time events, such as when a user selects a Button control.
You can specify event listeners, which consist of code for handling run-time events, in the event
properties of MXML tags. For example, the <mx:Button> tag has a click event property in
which you can specify ActionScript code that executes when the Button control is clicked at
run time. You can specify simple event listener code directly in event properties. To use more
complex code, you can specify the name of an ActionScript function defined in an
<mx:Script> tag.
The following example shows an application that contains a Button control and a TextArea
control. The click property of the Button control contains a simple event listener that sets
the value of the TextArea control’s text property to the text Hello World.
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:TextArea id="textarea1"/>
<mx:Button label="Submit" click="textarea1.text='Hello World';"/>
</mx:Panel>
</mx:Application>
The following image shows the application rendered in a web browser window:
The following example shows the code for a version of the application in which the event
listener is contained in an ActionScript function in an <mx:Script> tag:
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
private function hello():void {
textarea1.text="Hello World";
}
]]>
</mx:Script>
<mx:TextArea id="textarea1"/>
<mx:Button label="Submit" click="hello();"/>
</mx:Panel>
</mx:Application>
For more information about using ActionScript with MXML, see Chapter 4, “Using
ActionScript,” on page 55.
</mx:Panel>
</mx:Application>
The following image shows the application rendered in a web browser window after the user
clicks the Submit button:
As an alternative to the curly braces ({ }) syntax, you can use the <mx:Binding> tag, in which
you specify the source and destination of a binding. For more information about data
binding, see Chapter 43, “Storing Data,” on page 1517.
Developing applications 31
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Using RPC services
Remote-procedure-call (RPC) services let your application interact with remote servers to
provide data to your applications, or for your application to send data to a server.
Flex is designed to interact with several types of RPC services that provide access to local and
remote server-side logic. For example, a Flex application can connect to a web service that uses
the Simple Object Access Protocol (SOAP), a Java object residing on the same application
server as Flex using AMF, or an HTTP URL that returns XML. AMF is the protocol used in
Flash Remoting MX.
The MXML components that provide data access are called RPC components. MXML
includes the following types of RPC components:
■ WebService provides access to SOAP-based web services
■ HTTPService provides access to HTTP URLs that return data
■ RemoteObject provides access to Java objects using the AMF protocol (LiveCycle Data
Services ES only)
The following example shows an application that calls a web service that provides weather
information, and displays the current temperature for a given ZIP code. The application
binds the ZIP code that a user enters in a TextInput control to a web service input parameter.
It binds the current temperature value contained in the web service result to a TextArea
control.
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<!-- Bind the value of the ZIP code entered in the TextInput control
to the ZipCode parameter of the GetWeather operation. -->
<mx:operation name="GetWeather">
<mx:request>
<ZipCode>{zip.text}</ZipCode>
</mx:request>
</mx:operation>
</mx:WebService>
<!-- Call the web service operation with a Button click. -->
<mx:Button width="60" label="Get Weather"
click="WeatherService.GetWeather.send();"/>
<!-- Display the location for the specified ZIP code. -->
<mx:Label text="Location:"/>
<mx:TextArea text="{WeatherService.GetWeather.lastResult.Location}"/>
<!-- Display the current temperature for the specified ZIP code. -->
<mx:Label text="Temperature:"/>
<mx:TextArea
text="{WeatherService.GetWeather.lastResult.CurrentTemp}"/>
</mx:Panel>
</mx:Application>
The following image shows the application rendered in a web browser window:
For more information about using RPC services, see Chapter 40, “Accessing Server-Side Data
with Flex,” on page 1425.
Developing applications 33
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
You can declare a simple data model that does not require methods in an <mx:Model>,
<mx:XML>, or <mx:XMLList> tag. The following example shows an application that contains
TextInput controls for entering personal contact information and a data model, represented
by the <mx:Model> tag, for storing the contact information:
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
</mx:Application>
Validating data
You can use validator components to validate data stored in a data model, or in a Flex user-
interface component. Flex includes a set of standard validator components. You can also
create your own.
The following example uses validator components for validating that the expected type of data
is entered in the TextInput fields. Validation is triggered automatically when the users edits a
TextInput control. If validation fails, the user receives immediate visual feedback.
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
</mx:Application>
The following image shows the application rendered in a web browser window:
For more information about using data models, see Chapter 43, “Storing Data,” on
page 1517. For more information on validators, see Chapter 44, “Validating Data,” on
page 1529.
Formatting data
Formatter components are ActionScript components that perform a one-way conversion of
raw data to a formatted string. They are triggered just before data is displayed in a text field.
Flex includes a set of standard formatters. You can also create your own formatters. The
following example shows an application that uses the standard ZipCodeFormatter component
to format the value of a variable:
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
Developing applications 35
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
<mx:Script>
<![CDATA[
private var storedZipCode:Number=123456789;
]]>
</mx:Script>
<!-- Trigger the formatter while populating a string with data. -->
<mx:TextInput text="{ZipCodeDisplay.format(storedZipCode)}" />
</mx:Panel>
</mx:Application>
The following image shows the application rendered in a web browser window:
For more information about formatter components, see Chapter 45, “Formatting Data,” on
page 1575.
<mx:Style>
.myClass { color: Red } /* class selector */
Button { font-size: 18pt} /* type selector */
</mx:Style>
</mx:Panel>
</mx:Application>
A class selector in a style definition, defined as a label preceded by a period, defines a new
named style, such as myClass in the preceding example. After you define it, you can apply the
style to any component using the styleName property. In the preceding example, you apply
the style to the Button control to set the font color to red.
A type selector applies a style to all instances of a particular component type. In the preceding
example, you set the font size for all Button controls to 18 points.
The following image shows the application rendered in a web browser window:
For more information about using Cascading Style Sheets, see Chapter 20, “Using Styles and
Themes,” on page 767.
Using skins
Skinning is the process of changing the appearance of a component by modifying or replacing
its graphical elements. These graphical elements can be made up of images or the output of
drawing API methods. They are known as symbols. You can reskin Flex components without
changing their functionality. A file that contains new skins for use in your Flex applications is
known as a theme.
There are two types of skins in Flex: graphical and programmatic. Graphical skins are Adobe
Flash symbols that you can change directly in the Macromedia® Flash® Professional 8 from
Adobe® authoring environment. You draw programmatic skins by using ActionScript
statements and define these skins in class files. Sometimes it is more advantageous to reskin a
component graphically, and in some cases it makes more sense to reskin a component
programmatically. You cannot combine graphical and programmatic skins in a single theme
file.
For more information about using skins, see Chapter 22, “Creating Skins,” on page 879.
Developing applications 37
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Using effects
An effect is a change to a component that occurs over a brief period of time. Examples of
effects are fading, resizing, and moving a component. An effect is combined with a trigger,
such as a mouse click on a component, a component getting focus, or a component becoming
visible, to form a behavior. In MXML, you apply effects as properties of a control or container.
Flex provides a set of built-in effects with default properties.
The following example shows an application that contains a Button control with its
rollOverEffect property set to use the WipeLeft effect when the user moves the mouse over
it:
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
For more information about effects, see Chapter 19, “Using Behaviors,” on page 719.
You cannot access custom MXML component URLs directly in a web browser.
The following example shows a custom ComboBox control that is prepopulated with list
items:
<?xml version="1.0"?>
<!-- MyComboBox.mxml -->
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:ComboBox >
</mx:VBox>
The following example shows an application that uses the MyComboBox component as a
custom tag. The value * assigns the local namespace to the current directory.
<?xml version="1.0"?>
<!-- MyApplication.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComps="containers.boxes.*">
<MyComps:MyComboBox/>
</mx:Panel>
</mx:Application>
The following image shows the application rendered in a web browser window:
For more information about MXML components, see Chapter 7, “Creating Simple MXML
Components,” in Creating and Extending Flex Components.
You can also define custom Flex components in ActionScript. For more information, see
Chapter 9, “Creating Simple Visual Components in ActionScript,” in Creating and Extending
Flex Components.
Developing applications 39
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
CHAPTER 3
MXML Syntax 3
MXML is an XML language that you use to lay out user-interface components for Adobe Flex
applications. This topic describes basic MXML syntax.
Contents
Basic MXML syntax. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Setting component properties. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
41
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Naming MXML files
MXML filenames must adhere to the following naming conventions:
■ Filenames must be valid ActionScript identifiers, which means they must start with a
letter or underscore character (_), and they can only contain letters and numbers and
underscore characters after that.
■ Filenames must not be the same as ActionScript class names, component id values, or the
word application. Do not use filenames that match the names of MXML tags that are in
the mx namespace.
■ Filenames must end with a lowercase .mxml file extension.
You can set all component properties as child tags, in the form:
<mx:Label>
<mx:width>50</mx:width>
<mx:height>25</mx:height>
<mx:text>Hello World</mx:text>
</mx:Label>
You often use child tags when setting the value of a property to a complex Object because it is
not possible to specify a complex Object as the value of tag attribute. In the following
example, you use child tags to set the data provider of a ComboBox control of an
ArrayCollection object:
<mx:ComboBox>
<mx:dataProvider>
<mx:ArrayCollection>
<mx:String>AK</mx:String>
42 MXML Syntax
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
<mx:String>AL</mx:String>
<mx:String>AR</mx:String>
</mx:ArrayCollection>
<mx:dataProvider>
</mx:ComboBox>
The one restriction on setting properties that use child tags is that the namespace prefix of a
child tag, mx: in the previous example, must match the namespace prefix of the component
tag.
Each of a component’s properties is one of the following types:
■ Scalar properties, such as a number or string
■ Array of scalar values, such as an array of numbers or strings
■ ActionScript object
■ Array of ActionScript objects
■ ActionScript properties
■ XML data
Adobe recommends that you assign scalar values using tag attributes, and that you assign
complex types, such as ActionScript objects, by using child tags.
<!-- Set the property using the value of the static constant. -->
<mx:HBox width="200" horizontalScrollPolicy="off">
...
</mx:HBox>
In the first example, you set the horizontalScrollPolicy property using a static constant
named OFF, which is defined in the ScrollPolicy class. In MXML, you must use data binding
syntax when setting a property value to a static constant. The advantage of using the static
constant is that the Flex compiler recognizes incorrect property values, and issues an error
message at compile time.
Alternatively, you can set the value of the horizontalScrollPolicy property to the value of
the static constant. The value of the OFF static constant is "off". When you use the value of
the static constant to set the property value, the Flex compiler cannot determine if you used
an unsupported value. If you incorrectly set the property, you will not know until you get a
run-time error.
In ActionScript, you should always use static constants to set property values, as the following
example shows:
var myHBox:HBox = new HBox();
myHBox.horizontalScrollPolicy=ScrollPolicy.OFF;
If this tag defines a default property named default_property, the preceding tag definition
is equivalent to the following code:
<mx:SomeTag>
<default_property>
anything here
</default_property>
</mx:SomeTag>
44 MXML Syntax
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The default property provides a shorthand mechanism for setting a single property. For a
ComboBox, the default property is the dataProvider property. Therefore the two
ComboBox definitions in the following code are equivalent:
<?xml version="1.0"?>
<!-- mxml\DefProp.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" >
<mx:Label text="\{\}"/>
</mx:Application>
Do not use the backslash character (\) as a separator in the path to an application asset.
You should always use a forward slash character (/) as the separator.
In this example, you set the text property of the TextArea control to a value that includes a
newline character.
46 MXML Syntax
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Notice that this example includes the [Bindable] metadata tag before the property
definition. This metadata tag specifies that the myText property can be used as the source of a
data binding expression. Data binding automatically copies the value of a source property of
one object to the destination property of another object at run time when the source
property changes.
If you omit this metadata tag, the compiler issues a warning message specifying that the
property cannot be used as the source for data binding. For more information, see Chapter
42, “Binding Data,” on page 1481.
The <mx:Array> and </mx:Array> tags around the Array elements are optional. Therefore,
you can also write this example as the following example shows:
<mx:List width="150">
<mx:dataProvider>
<mx:Number>94062</mx:Number>
<mx:Number>14850</mx:Number>
<mx:Number>53402</mx:Number>
</mx:dataProvider>
</mx:List>
In this example, since the data type of the dataProvider property is defined as Array, Flex
automatically converts the three number definitions into a three-element array.
Component developers may have specified additional information within the component
definition that defines the data type of the Array elements. For example, if the developer
specified that the dataProvider property only supports String elements, then this example
would cause a compiler error because you specified numbers to it. The Adobe Flex Language
Reference documents the Array properties that define a required data type for the Array
elements.
The following example shows an ActionScript class that defines an Address object. This object
is used as a property of the PurchaseOrder component in the next example.
class Address
{
public var name:String;
public var street:String;
public var city:String;
public var state:String;
public var zip:Number;
}
The following example shows an ActionScript class that defines a PurchaseOrder component
that has a property type of Address:
import example.Address;
class PurchaseOrder {
public var shippingAddress:Address;
public var quantity:Number;
...
}
In MXML, you define the PurchaseOrder component as the following example shows:
<mynamespace:PurchaseOrder quantity="3" xmlns:e="example">
<mynamespace:shippingAddress>
<mynamespace:Address name="Fred" street="123 Elm St."/>
</mynamespace:shippingAddress>
</mynamespace:PurchaseOrder>
If the property is explicitly typed as Object like the value property in the following example,
you can specify an anonymous object using the <mx:Object> tag.
48 MXML Syntax
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
class ObjectHolder {
public var value:Object
}
The following example shows how you specify an anonymous object as the value of the value
property:
<mynamespace:ObjectHolder>
<mynamespace:value>
<mx:Object foo='bar' />
</mynamespace:value>
</mynamespace:ObjectHolder>
In this example, you initialize the Object to a three element array of numbers.
As described in the section “Setting Arrays of scalar values” on page 47, the <mx:Array> tag
and the </mx:Array> tag around the Array elements are optional and may be omitted, as the
following example shows:
<mynamespace:MyComponent>
<mynamespace:nameOfObjectProperty>
<mx:Number>94062</mx:Number>
<mx:Number>14850</mx:Number>
<mx:Number>53402</mx:Number>
</mynamespace:nameOfObjectProperty>
</mynamespace:MyComponent>
The only exception to this rule is when you specify a single Array element for the Object
property. In that case, Flex does not create an Object containing a single-element array, but
instead creates an object and sets it to the specified value. This is a difference between the
following:
object=[element] // Object containing a one-element array
object=element // object equals value
The component in the following example contains an Array of ListItem objects. Each
ListItem object has properties named label and data.
<mynamespace:MyComponent>
<mynamespace:dataProvider>
<mx:Array>
<mynamespace:ListItem label="One" data="1"/>
<mynamespace:ListItem label="Two" data="2"/>
</mx:Array>
</mynamespace:dataProvider>
</mynamespace:MyComponent>
The following example shows how you specify an anonymous object as the value of the
dataProvider property:
<mynamespace:MyComponent>
<mynamespace:dataProvider>
<mx:Array>
<mx:Object label="One" data="1"/>
<mx:Object label="Two" data="2"/>
</mx:Array>
</mynamespace:dataProvider>
</mynamespace:MyComponent>
50 MXML Syntax
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
As described in the section “Setting Arrays of scalar values” on page 47, the <mx:Array> tag
and the </mx:Array> tag around the Array elements are optional and may be omitted, as the
following example shows:
<mynamespace:MyComponent>
<mynamespace:dataProvider>
<mx:Object label="One" data="1"/>
<mx:Object label="Two" data="2"/>
</mynamespace:dataProvider>
</mynamespace:MyComponent>
You define event properties in ActionScript classes using the [Event] metadata tags, rather
than defining them as ActionScript variables or setter/getter methods. For more information,
see Chapter 5, “Using Metadata Tags in Custom Components,” in Creating and Extending
Flex Components.
For example, you can set the creationComplete event property in MXML, as the following
code shows:
<mx:TextArea id="myText" creationComplete="creationCompleteHandler()"/>
You specify a script in the source property of an <mx:Script> tag. You do not specify
ActionScript classes in the source property. For information on using ActionScript
classes, see “Creating ActionScript components” on page 75 in the Flex Developer’s
Guide.
■ A path used at run time that is relative to the context root of the Java web application in
which a Flex application is running; for example:
<mx:HTTPService url="@ContextRoot()/directory/myfile.xml"/>
52 MXML Syntax
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
■ A path used at compile-time that is relative to the context root of the Java web application
in which a Flex application is running; for example:
<mx:Script source="/myscript.as"/>
pattern Specifies the regular expression within the two slashes. Both slashes are required.
flags (Optional) specifies any flags for the regular expression.
For example, the regExpression property of an MXML component is of type RegExp.
Therefore, you can set its value, as the following example shows:
<mynamespace:MyComponent regExpression="/\Wcat/gi"/>
Or set it using child tags, as the following example shows:
<mynamespace:MyComponent>
<mynamespace:regExpression>/\Wcat/gi</mynamespace:regExpression>
</mynamespace:MyComponent>
The flags portion of the regular expression is optional, so you can also specify it as the
following example shows:
<mynamespace:MyComponent regExpression="/\Wcat/"/>
54 MXML Syntax
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
CHAPTER 4
Using ActionScript 4
Flex developers can use ActionScript to extend the functionality of their Adobe Flex
applications. ActionScript provides flow control and object manipulation features that are not
available in MXML. This topic explains how to use ActionScript in an MXML application.
For a complete introduction to ActionScript and a reference for using the language, see
Programming ActionScript 3.0 and ActionScript 3.0 Language Reference.
Contents
Using ActionScript in Flex applications. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Working with Flex components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
Comparing, including, and importing ActionScript code . . . . . . . . . . . . . . . . . . . . . . . 68
Techniques for separating ActionScript from MXML . . . . . . . . . . . . . . . . . . . . . . . . . 72
Creating ActionScript components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
Performing object introspection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
55
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
ActionScript is an object-oriented procedural programming language, based on the
ECMAScript (ECMA-262) edition 4 draft language specification. You can use a variety of
methods to mix ActionScript and MXML, including the following:
■ Use ActionScript to define event listeners inside MXML event attributes.
■ Add script blocks using the <mx:Script> tag.
■ Include external ActionScript files.
■ Import ActionScript classes.
■ Create ActionScript components.
ActionScript compilation
Although a simple Flex application can be written in a single MXML or ActionScript (AS)
file, most applications will be broken into multiple files. For example, it is common to move
the <mx:Script> and <mx:Style> blocks for an <mx:Application> into separate AS and
CSS files which the application then includes. It is also common for an application to import
custom MXML and ActionScript components. These must be defined in other files, and
MXML components may put their own <mx:Script> blocks into yet more AS files that they
include. Components may also be imported from precompiled SWC files rather than source
code. Finally, SWF files containing executable code can also be embedded in an application.
The end result of all these input files is a single SWF file.
You can use ActionScript code fragments in a number of places within your MXML files. The
Flex compiler transforms the main MXML file and other files it includes into a single
ActionScript class. So, you cannot define classes or use statements outside of functions in
MXML files and included ActionScript files.
You can reference imported ActionScript classes from your MXML application files, and
those classes are added to the final SWF file. When the transformation to an ActionScript file
is complete, Flex links all the ActionScript components and includes those classes in the final
SWF file.
56 Using ActionScript
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
An MXML application (a file starting with the <mx:Application> tag) defines a subclass of
the Application class. Similarly, an MXML component (a file starting with some other
component’s tag, such as <mx:Button>) defines a subclass of that component.
The name of the subclass is the name of the file. The base class is the class of the top-level tag.
An MXML application actually defines the following:
class MyApp extends Application
If MyButton.mxml starts with <mx:Button>, you are actually defining the following:
class MyButton extends Button
The variable and function declarations in an <mx:Script> block define properties and
methods of the subclass.
Setting an id property on a component instance within a class results in a public variable
being autogenerated in the subclass that contains a reference to that component instance. For
example, if the <mx:Button id="myButton"/> tag is nested deeply inside several containers,
you can still refer to it as myButton.
Event attributes become the bodies of autogenerated event listener methods in the subclass.
For example:
<mx:Button id="myButton" click="foo = 1; doSomething()">
becomes
private function __myButton_click(event:MouseEvent):void {
foo = 1;
doSomething()
}
The event attributes become method bodies, so they can access the other properties and
methods of the subclass.
All the ActionScript anywhere in an MXML file, whether in its <mx:Script> block or inside
tags, executes with the this keyword referring to an instance of the subclass.
The public properties and methods of the class are accessible by ActionScript code in other
components, as long as that code “dots down” (for example,
myCheckoutAccordion.myAddressForm.firstNameTextInput.text) or reaches up using
parentDocument, parentApplication, or Application.application to specify which
component the property or method exists on.
When the user clicks the button, this code sets the value of the TextArea control’s text
property to the String “Hello World.” In most cases, you do not need to look at the
generated code, but it is useful to understand what happens when you write an inline event
handler.
To see the generated code, set the value of the keep-generated-actionscript compiler
option to true. The compiler then stores the *.as helper file in the /generated directory, which
is a subdirectory of the location of the SWF file.
For more information about events, see Chapter 5, “Using Events,” on page 83. For more
information on using the command-line compilers, see Chapter 9, “Using the Flex
Compilers,” in Building and Deploying Flex Applications.
58 Using ActionScript
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Statements and expressions are allowed only if they are wrapped in a function. In addition,
you cannot define new classes or interfaces in <mx:Script> blocks. Instead, you must place
new classes or interfaces in separate AS files and import them.
All ActionScript in the block is added to the enclosing file’s class when Flex compiles the
application. The following example declares a variable and sets the value of that variable inside
a function:
<?xml version="1.0"?>
<!-- usingas/StatementSyntax.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="doSomething()">
<mx:Script><![CDATA[
public var s:Boolean;
public function doSomething():void {
// The following statements must be inside a function.
s = label1.visible;
label1.text = String(s);
}
]]></mx:Script>
<mx:Label id="label1"/>
</mx:Application>
Most statements must be inside functions in an <mx:Script> block. However, the following
statements can be outside functions:
■ import
■ var
■ include
■ const
■ namespace
■ use namespace
When using an <mx:Script> block, you should wrap the contents in a CDATA construct.
This prevents the compiler from interpreting the contents of the script block as XML, and
allows the ActionScript to be properly generated. Adobe recommends that you write all your
<mx:Script> open and close tags as the following example shows:
<mx:Script>
<![CDATA[
...
]]>
</mx:Script>
<mx:Label id="label1"/>
</mx:Application>
60 Using ActionScript
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
This property is optional if you do not want to access the component with ActionScript.
This code causes the MXML compiler to autogenerate a public variable named myButton that
contains a reference to that Button instance. This autogenerated variable lets you access the
component instance in ActionScript. You can explicitly refer to the Button control’s instance
with its id instance reference in any ActionScript class or script block. By referring to a
component’s instance, you can modify its properties and call its methods.
For example, the following ActionScript block changes the value of the Button control’s
label property when the user clicks the button:
<?xml version="1.0"?>
<!-- usingas/ButtonExample.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
private function setLabel():void {
myButton.label = "Clicked";
}
]]></mx:Script>
</mx:Application>
The IDs for all tags in an MXML component, no matter how deeply nested they are, generate
public variables of the component being defined. As a result, all id properties must be unique
within a document. This also means that if you specified an ID for a component instance, you
can access that component from anywhere in the application: from functions, external class
files, imported ActionScript files, or inline scripts.
You can refer to a Flex component if it does not have an id property by using methods of the
component’s container, such as the getChildAt() and getChildByName() methods.
You can refer to the current enclosing document or current object using the this keyword.
You can also get a reference to a component when you have a String that matches the name.
To access an object on the application, you use the this keyword, followed by square
brackets, with the String inside the square brackets. The result is a reference to the objects
whose name matches the String.
62 Using ActionScript
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The following example uses ActionScript to declare two Label controls in the application
scope. During initialization, the labels are instantiated and their text properties are set. The
example then gets a reference to the Label controls by appending the passed in variable to the
String when the user clicks the Button controls.
<?xml version="1.0"?>
<!-- usingas/ASLabels.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initLabels()">
<mx:Script><![CDATA[
import mx.controls.Label;
addChild(label1);
addChild(label2);
}
<mx:HSlider id="slider1"/>
</mx:Application>
To invoke a method from a child document (such as a custom MXML component), you can
use the parentApplication, parentDocument, or Application.application properties.
For more information, see Chapter 16, “Using the Application Container,” on page 601.
64 Using ActionScript
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The following example creates a Button control inside the HBox:
<?xml version="1.0"?>
<!-- usingas/ASVisualComponent.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import mx.controls.Button;
public var button2:Button;
You should declare an instance variable for each dynamically created component and store a
reference to the newly created component in it, just as the MXML compiler does when you
set an id property for a component instance tag. You can then access your dynamically
created components in the same way as those declaratively created in MXML.
To programmatically remove a control, you can use the removeChild() or removeChildAt()
methods. You can also use the removeAllChildren() method to remove all child controls
from a container. Calling these methods does not actually delete the objects. If you do not
have any other references to the child, Flash Player includes it in garbage collection at some
future point. But if you stored a reference to that child on some object, the child is not
removed from memory.
In some cases, you declaratively define a component with an MXML tag. You can set the
creationPolicy property of the component’s container to none to defer the creation of the
controls inside that container. Then, to create a component that has been declared with a tag
but not instantiated, you use the createComponentFromDescriptor() and
createComponentsFromDescriptors() methods. These methods let you create a
component programmatically rather than declaratively. For information on using the
creationPolicy property, see Chapter 6, “Improving Startup Performance,” in Building and
Deploying Flex Applications.
}
]]></mx:Script>
</mx:Application>
About scope
Scoping in ActionScript is largely a description of what the this keyword refers to at a
particular point. In your application’s core MXML file, you can access the Application object
by using the this keyword. In a file defining an MXML component, this is a reference to
the current instance of that component.
In an ActionScript class file, the this keyword refers to the instance of that class. In the
following example, the this keyword refers to an instance of myClass. Because this is
implicit, you do not have to include it, but it is shown here to illustrate its meaning.
class myClass {
var _x:Number = 3;
function get x():Number {
return this._x;
}
66 Using ActionScript
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
function set x(y:Number):void {
if (y > 0) {
this._x = y;
} else {
this._x = 0;
}
}
}
However, in custom ActionScript and MXML components or external ActionScript class files,
Flex executes in the context of those objects and classes, and the this keyword refers to the
current scope and not the Application object scope.
Flex includes an Application.application property that you can use to access the root
application. You can also use the parentDocument property to access the next level up in the
document chain of a Flex application, or the parentApplication property to access the next
level up in the application chain when one Application object uses a SWFLoader component
to load another Application object.
If you write ActionScript in a component’s event listener, the scope is not the component but
rather the application. For example, the following code changes the label of the Button
control to “Clicked” once the Button control is pressed:
<?xml version="1.0"?>
<!-- usingas/ButtonScope.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
</mx:Application>
Contrast the previous example with the following code:
<?xml version="1.0"?>
<!-- usingas/AppScope.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<!-- The following does nothing because the app level scope does
not have a label to set -->
<mx:Button id="myButton" label="Click Me" click="label='Clicked'"/>
</mx:Application>
This code does not work because when an event listener executes, the this keyword does not
refer to the Button instance; it is the Application or other top-level component instance. The
second example attempts to set the label property of the Application object, not the label
property of the Button.
68 Using ActionScript
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Variables and functions defined in an included ActionScript file are available to any
component in the MXML file. An included ActionScript file is not the same as an imported
ActionScript class. Flex provides access to the included file’s variables and functions, but does
not add a new class, because the MXML file itself is a class.
Included ActionScript files do not need to be in the same directory as the MXML file.
However, you should organize your ActionScript files in a logical directory structure.
If you are using Adobe LiveCycle Data Services ES, Flex detects changes in ActionScript files
using timestamps. If the file has changed since the last request, Flex regenerates the
application before responding to the client. If you change the ActionScript in one of the
imported ActionScript files, the next time the application is requested, the changes appear.
There are two ways to include an external ActionScript file in your Flex application:
■ The source attribute of the <mx:Script> tag. This is the preferred method for including
external ActionScript class files.
■ The include statement inside <mx:Script> blocks.
The following sections describe these two methods of including an external ActionScript file.
<mx:Script><![CDATA[
include "includes/myfunctions.as";
]]></mx:Script>
</mx:Application>
You can specify only a single file for each include directive, but you can use any number of
include directives. You can nest include directives; files with include directives can include
files that have include directives.
The include directive supports only relative paths. For more information, see “Referring to
external files that have been included” on page 71.
You can use the include only where multiple statements are allowed. For example, the
following is not allowed:
if (expr)
include "foo.as"; // First statement is guarded by IF, but rest are not.
...
70 Using ActionScript
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The use of curly braces ({ }) allows multiple statements because you can add multiple
statements inside the braces.
Adobe recommends that you not use the include directive if you use a large number of
included ActionScript files. You should try to break the code into separate class files where
appropriate and store them in logical package structures.
<mx:Script><![CDATA[
import MyPackage.Util.MyClass;
]]></mx:Script>
</mx:Application>
In your ActionScript code, instead of referring to the class with its fully qualified package
name (MyPackage.Util.MyClass), you refer to it as MyClass.
You can also use the wildcard character (*) to import the entire package. For example, the
following statement imports the entire MyPackage.Util package:
import MyPackage.Util.*;
Flex searches the source path for imported files and packages, and includes only those that are
used in the final SWF file.
It is not sufficient to simply specify the fully qualified class name. You should use fully
qualified class names only when necessary to distinguish two classes with the same class name
that reside in different packages.
If you import a class but do not use it in your application, the class is not included in the
resulting SWF file’s bytecode. As a result, importing an entire package with a wildcard does
not create an unnecessarily large SWF file.
72 Using ActionScript
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The following image shows the sample Temperature application:
In this simple application that calls a single function, there are several ways to separate
MXML and ActionScript:
■ “One MXML document (Event handling logic in event attribute)” on page 73
■ “One MXML document (Event handling logic in <mx:Script> block)” on page 74
■ “One MXML document and one ActionScript file (Event handling logic in separate script
file)” on page 75
The following sections describe these methods.
74 Using ActionScript
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
One MXML document and one ActionScript file
(Event handling logic in separate script file)
Here the function call is in an MXML event attribute, and the function is defined in a
separate ActionScript file, as the following code shows:
<?xml version="1.0"?>
<!-- usingas/ASSourceFile.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<!-- Specify the ActionScript file that contains the function. -->
<mx:Script source="includes/Sample3Script.as"/>
In this example, you write your MyButton control to the MyButton.as file, and you store the
file in the myControls subdirectory of the root directory of your Flex application. The fully
qualified class name of your component reflects its location. In this example, the component’s
fully qualified class name is myControls.MyButton.
You can reference your custom Button control from a Flex application file, such as
MyApp.mxml, as the following example shows:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:cmp="myControls.*">
<cmp:MyButton label="Jack"/>
</mx:Application>
In this example, you define the cmp namespace that defines the location of your custom
component in the application’s directory structure. You then reference the component as an
MXML tag using the namespace prefix.
Typically, you put custom ActionScript components in directories that are in the source path.
These include your application’s root directory, the flex_app_root/WEB-INF/flex/user_classes
directory (LiveCycle Data Services ES only), or any directory that you specify in the
<source-path> tag in the flex-config.xml file.
You can also create custom components using MXML. For more information, see Creating
and Extending Flex Components.
76 Using ActionScript
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Nonvisual components Nonvisual components define no visual elements. A nonvisual
component is an ActionScript class that does not extend the UIComponent class. They can
provide greater efficiency at run time.
78 Using ActionScript
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
You can also use the mx.utils.ObjectUtil.toString() method to print all the
dynamically added properties of an object; for example:
<?xml version="1.0"?>
<!-- usingas/IntrospectionForIn.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp()">
<mx:Script><![CDATA[
import mx.utils.ObjectUtil;
80 Using ActionScript
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The output displays accessors, variables, and methods of the Button control, and appears
similar to the following:
Class mx.controls::Button
...
Variable id=button1 (String)
Variable __width=66 (Number)
Variable layoutWidth=66 (Number)
Variable __height=22 (Number)
Variable layoutHeight=22 (Number)
...
Property label=Submit (String)
Property enabled=true (Boolean)
Property numChildren=2 (uint)
Property enabled=true (Boolean)
Property visible=true (Boolean)
Property toolTip=null (String)
...
Method dispatchEvent():Boolean
Method hasEventListener():Boolean
Method layoutContents():void
Method getInheritingStyle():Object
Method getNonInheritingStyle():Object
Another useful method is the ObjectUtil’s getClassInfo() method. This method returns an
Object with the name and properties of the target object. The following example uses the
getClassInfo() and toString() methods to show the properties of the Button control:
<?xml version="1.0"?>
<!-- usingas/IntrospectionObjectUtil.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import mx.controls.Alert;
import mx.utils.ObjectUtil;
private function showProps(b:Button):void {
var o:Object = ObjectUtil.getClassInfo(b);
ta1.text = ObjectUtil.toString(o);
}
]]></mx:Script>
<mx:Button id="b1" label="Show Properties" click="showProps(b1)"/>
<mx:TextArea id="ta1" width="300" height="500"/>
</mx:Application>
For more information about using E4X, see Programming ActionScript 3.0.
82 Using ActionScript
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
CHAPTER 5
Using Events 5
One of the most important parts of your Adobe Flex application is handling events. This
topic describes the event flow and how to handle events by using controls and ActionScript in
your Flex applications.
Contents
About events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Using events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Manually dispatching events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
Event propagation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .115
Event priorities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
Using event subclasses. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
About keyboard events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
About events
This section introduces you to the event model in Flex 2. In addition, this section describes
the Event object and its subclasses, and describes the event dispatching model. For a quick
start in using events in Flex, you can skip this section and see sample code in “Using events”
on page 87.
Events let a developer know when something happens within a Flex application. They can be
generated by user devices, such as the mouse and keyboard, or other external input, such as
the return of a web service call. Events are also triggered when changes happen in the
appearance or life cycle of a component, such as the creation or destruction of a component or
when the component is resized.
83
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Any user interaction with your application can generate events. Events can also occur without
any direct user interaction, such as when data finishes loading from a server or when an
attached camera becomes active. You can “handle” these events in your code by adding an
event handler. Event handlers are the functions or methods that you write to respond to
specific events. They are also sometimes referred to as event listeners.
The Flex event model is based on the Document Object Model (DOM) Level 3 Events
Model. Although Flex does not adhere specifically to the Document Object Model standard,
the implementations are very similar.
Components generate and dispatch events and consume (listen to) other events. An object that
requires information about another object’s events registers a listener with that object. When
an event occurs, the object dispatches the event to all registered listeners by calling a function
that was requested during registration. To receive multiple events from the same object, you
must register your listener for each event.
Components have built-in events that you can handle in ActionScript blocks in your MXML
applications. You can also take advantage of the Flex event system’s dispatcher-listener model
to define your own event listeners outside of your applications, and define which methods of
your custom listeners will listen to certain events. You can register listeners with the target
object so that when the target object dispatches an event, the listeners get called.
All visual objects, including Flex controls and containers, are subclasses of the DisplayObject
class. They are in a tree of visible objects that make up your application. The root of the tree is
the Stage. Below that is the SystemManager object, and then the Application object. Child
containers and components are leaf nodes of the tree. That tree is known as the display list. An
object on the display list is analogous to a node in the DOM hierarchical structure. The terms
display list object and node are used interchangeably in this topic.
For information about each component’s events, see the component’s description in Chapter
10, “Using Controls,” on page 267 or the control’s entry in Adobe Flex Language Reference.
For a detailed description of a component’s startup life cycle, including major events in that
life cycle, see Chapter 10, “Creating Advanced Visual Components in ActionScript,” in
Creating and Extending Flex Components.
84 Using Events
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
About the Event flow
You can instruct any container or control to listen for events dispatched by another container
or control. When Adobe Flash Player dispatches an Event object, that Event object makes a
round-trip journey from the root of the display list to the target node, checking each node for
registered listeners. The target node is the node in the display list where the event occurred.
For example, if a user clicks a Button control named Child1, Flash Player dispatches an Event
object with Child1 defined as the target node.
The event flow is conceptually divided into three parts. The following sections introduce you
to these parts. For more information about the event flow, see “Event propagation”
on page 115.
About events 85
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
About the Event class
The flash.events.Event class is an ActionScript class with properties that contain information
about the event that occurred. An Event object is an implicitly created object, similar to the
way the request and response objects in a JavaServer Page (JSP) are implicitly created by the
application server.
Flex creates an Event object each time an event is dispatched. You can use the Event object
inside an event listener to access details about the event that was dispatched, or about the
component that dispatched the event. Passing an Event object to, and using it in, an event
listener is optional. However, if you want to access the Event object’s properties inside your
event listeners, you must pass the Event object to the listener.
Flex creates only one Event object when an event is dispatched. During the bubbling and
capturing phases, Flex changes the values on the Event object as it moves up or down the
display list, rather than creating a new Event object for each node.
86 Using Events
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
About the EventDispatcher class
Every object in the display list can trace its class inheritance back to the DisplayObject class.
The DisplayObject class, in turn, inherits from the EventDispatcher class. The
EventDispatcher class is a base class that provides important event model functionality for
every object on the display list. Because the DisplayObject class inherits from the
EventDispatcher class, any object on the display list has access to the methods of the
EventDispatcher class.
This is significant because every item on the display list can participate fully in the event
model. Every object on the display list can use its addEventListener() method—inherited
from the EventDispatcher class—to listen for a particular event, but only if the listening
object is part of the event flow for that event.
Although the name EventDispatcher seems to imply that this class’s main purpose is to send
(or dispatch) Event objects, the methods of this class are used much more frequently to
register event listeners, check for event listeners, and remove event listeners.
The EventDispatcher class implements the IEventDispatcher interface. This allows developers
who create custom classes that cannot inherit from EventDispatcher or one of its subclasses to
implement the IEventDispatcher interface to gain access to its methods.
The addEventListener() method is the most commonly used method of this class. You use
it to register your event listeners. For information on using the addEventListener()
method, see “Using the addEventListener() method” on page 95.
Advanced programmers use the dispatchEvent() method to manually dispatch an event or
to send a custom Event object into the event flow. For more information, see “Manually
dispatching events” on page 112.
Several other methods of the EventDispatcher class provide useful information about the
existence of event listeners. The hasEventListener() method returns true if an event
listener is found for that specific event type on a particular display list object. The
willTrigger() method checks for event listeners on a particular display list object, but it
also checks for listeners on all of that display list object’s ancestors for all phases of the event
flow. The method returns true if it finds one.
Using events
Using events in Flex is a two-step process. First, you write a function or class method, known
as an event listener or event handler, that responds to events. The function often accesses the
properties of the Event object or some other settings of the application state. The signature of
this function usually includes an argument that specifies the event type being passed in.
Using events 87
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The following example shows a simple event listener function that reports when a control
triggers the event that it is listening for:
<?xml version="1.0"?>
<!-- events/SimpleEventHandler.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp()">
<mx:Script><![CDATA[
import mx.controls.Alert;
</mx:Application>
As you can see in this example, you also register that function or class method with a display
list object by using the addEventListener() method.
Most Flex controls simplify listener registration by letting you specify the listener inside the
MXML tag. For example, instead of using the addEventListener() method to specify a
listener function for the Button control’s click event, you specify it in the click attribute of
the <mx:Button> tag:
<?xml version="1.0"?>
<!-- events/SimplerEventHandler.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import mx.controls.Alert;
</mx:Application>
88 Using Events
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
This is equivalent to the addEventListener() method in the previous code example.
However, it is best practice to use the addEventListener() method. This method gives you
greater control over the event by letting you configure the priority and capturing settings, and
use event constants. In addition, if you use addEventListener() to add an event handler,
you can use removeEventListener() to remove the handler when you no longer need it. If
you add an event handler inline, you cannot call removeEventListener() on that handler.
Each time a control generates an event, Flex creates an Event object that contains information
about that event, including the type of event and a reference to the dispatching control. To
use the Event object, you specify it as a parameter in the event handler function, as the
following example shows:
<?xml version="1.0"?>
<!-- events/EventTypeHandler.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import mx.controls.Alert;
</mx:Application>
If you want to access the Event object in an event handler that was triggered by an inline
event, you must add the event keyword inside the MXML tag so that Flex explicitly passes it
to the handler, as in the following:
<mx:Button id="b1" label="Click Me" click="myEventHandler(event)"/>
Using events 89
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
You are not required to use the Event object in a handler function. The following example
creates two event handler functions and registers them with the events of a ComboBox
control. The first event handler, openEvt(), takes no arguments. The second event handler,
changeEvt(), takes the Event object as an argument and uses this object to access the value
and selectedIndex of the ComboBox control that triggered the event.
<?xml version="1.0"?>
<!-- events/MultipleEventHandlers.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
private function openEvt():void {
forChange.text="";
}
private function changeEvt(e:Event):void {
forChange.text=e.currentTarget.value + " " +
e.currentTarget.selectedIndex;
}
]]></mx:Script>
<mx:ComboBox open="openEvt()" change="changeEvt(event)">
<mx:dataProvider>
<mx:Array>
<mx:String>AK</mx:String>
<mx:String>AL</mx:String>
<mx:String>AR</mx:String>
</mx:Array>
</mx:dataProvider>
</mx:ComboBox>
<mx:TextArea id="forChange" width="150"/>
</mx:Application>
This example shows accessing the target property of the Event object. For more
information, see “Accessing the target property” on page 91.
However, if you want to access properties that are specific to the type of event that was
dispatched, you must instead specify a more specific event type, such as ToolTipEvent or
KeyboardEvent, as the following example shows:
import mx.events.ToolTip
function myEventListener(e:ToolTipEvent):void { ... }
In some cases, you must import the event’s class in your ActionScript block.
90 Using Events
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Most objects have specific events that are associated with them, and most of them can
dispatch more than one type of event.
If you declare an event of type Event, you can cast it to a more specific type to access its event-
specific properties. For more information, see “Using event subclasses” on page 124.
If you try to call a method, such as setStyle(), on the currentTarget, Flex compiles the
application but throws a run-time error. This is because at compile time, the target is
considered to be of type Object, which can have any property or method. At run-time,
however, the target is now more strongly typed, and calling a method or accessing a property
that does not exist on that type causes the error.
A method such as setStyle() is defined on UIComponent, which is a subclass of
DisplayObject. Therefore, the best practice is to cast currentTarget to UIComponent
before calling its methods or accessing its properties.
Using events 91
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The following example casts the current target to a UIComponent before calling the
setStyle() method:
<?xml version="1.0"?>
<!-- events/InvokingOnCurrentTarget.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import mx.core.UIComponent;
</mx:Application>
In this example, whenever the user clicks the Button control, Flex calls the
myClickHandler() function.
For more information on defining event handlers inline, see “Defining event listeners
inline” on page 93.
92 Using Events
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
■ Use the addEventListener() method, as follows:
<?xml version="1.0"?>
<!-- events/SimpleEventHandler.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp()">
<mx:Script><![CDATA[
import mx.controls.Alert;
</mx:Application>
As with the previous example, whenever the user clicks the Button control, Flex calls the
myClickHandler() handler function. But registering your event handlers using this
method provides more flexibility. You can register multiple components with this event
handler, add multiple handlers to a single component, or remove the handler. For more
information, see “Using the addEventListener() method” on page 95.
■ Create an event handler class and register components to use the class for event handling.
This approach to event handling promotes code reuse and lets you centralize event
handling outside your MXML files. For more information on creating custom event
handler classes, see “Creating event handler classes” on page 101.
The following sections describe these methods of handling events.
For example, to listen for a Button control’s click event, you add a statement in the
<mx:Button> tag’s click attribute. If you add a function, you define that function in an
ActionScript block. The following example defines the submitForm() function as the handler
for the Button control’s click event:
Using events 93
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
<mx:Script><![CDATA[
function submitForm():void {
// Do something.
}
]]></mx:Script>
<mx:Button label="Submit" click="submitForm();" />
Event handlers can include any valid ActionScript code, including code that calls global
functions or sets a component property to the return value. The following example calls the
trace() global function:
<mx:Button label="Get Ver" click="trace('The button was clicked');"/>
There is one special parameter that you can pass in an inline event handler definition: the
event parameter. If you add the event keyword as a parameter, Flex passes the Event object.
Inside the handler function, you can then access all the properties of the Event object.
The following example passes the Event object to the submitForm() handler function and
specifies it as type MouseEvent:
<?xml version="1.0"?>
<!-- events/MouseEventHandler.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
private function myEventHandler(event:MouseEvent):void {
// Do something with the MouseEvent object;
}
]]></mx:Script>
</mx:Application>
It is best practice to include the event keyword when you define all inline event listeners and
to specify the most stringent Event object type in the resulting listener function (for example,
specify MouseEvent instead of Event).
You can use the Event object to access a reference to the target object (the object that
dispatched the event), the type of event (for example, click), or other relevant properties,
such as the row number and value in a list-based control. You can also use the Event object to
access methods and properties of the target component, or the component that dispatched the
event.
94 Using Events
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Although you will most often pass the entire Event object to an event listener, you can just
pass individual properties, as the following example shows:
<?xml version="1.0"?>
<!-- events/PropertyHandler.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
private function myEventHandler(s:String):void {
trace(s);
}
]]></mx:Script>
</mx:Application>
Registering an event listener inline provides less flexibility than using the
addEventListener() method to register event listeners. The drawbacks are that you cannot
set the useCapture or priority properties on the Event object and that you cannot remove
the listener once you add it.
The event_type argument is the kind of event that this component dispatches. This can be
either the event type String (for example, click or mouseOut), or the event type static
constant (such as MouseEvent.CLICK or MouseEvent.MOUSE_OUT). This argument is
required.
The constants provide an easy way to refer to specific event types. You should use these
constants instead of the strings that they represent. If you misspell a constant name in your
code, the compiler catches the mistake. If you instead use strings and make a typographical
error, it can be harder to debug and could lead to unexpected behavior.
Using events 95
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
You should use the constants wherever possible. For example, when you are testing to see
whether an Event object is of a certain type, use the following code:
if (myEventObject.type == MouseEvent.CLICK) {/* your code here */}
rather than:
if (myEventObject.type == "click") {/* your code here */}
The event_listener argument is the function that handles the event. This argument is
required.
The use_capture parameter of the addEventListener() method lets you control the phase
in the event flow in which your listener will be active. It sets the value of the useCapture
property of the Event object. If useCapture is set to true, your listener is active during the
capturing phase of the event flow. If useCapture is set to false, your listener is active during
the targeting and bubbling phases of the event flow but not during the capturing phase. The
default value is determined by the type of event, but is false in most cases.
To listen for an event during all phases of the event flow, you must call addEventListener()
twice, once with the use_capture parameter set to true, and again with use_capture set to
false. This argument is optional. For more information, see “Capturing phase” on page 117.
The priority parameter sets the priority for that event listener. The higher the number, the
sooner that event handler executes relative to other event listeners for the same event. Event
listeners with the same priority are executed in the order that they were added. This parameter
sets the priority property of the Event object. The default value is 0, but you can set it to
negative or positive integer values. If several event listeners were added without priorities, the
earlier a listener is added, the sooner it is executed. For more information on setting priorities,
see “Event priorities” on page 122.
The weakRef parameter provides you with some control over memory resources for listeners.
A strong reference (when weakRef is false) prevents the listener from being garbage
collected. A weak reference (when weakRef is true) does not. The default value is false.
When you add a listener function and that function is invoked, Flex implicitly creates an
Event object for you and passes it to the listener function. You must declare the Event object
in the signature of your listener function.
If you add an event listener by using the addEventListener() method, you are required to
declare an event object as a parameter of the listener_function, as the following example
shows:
b1.addEventListener(MouseEvent.CLICK, performAction);
In the listener function, you declare the Event object as a parameter, as follows:
public function performAction(e:MouseEvent):void {
...
}
96 Using Events
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The following example defines a new handler function myClickListener(). It then registers
the click event of the Button control with that handler. When the user clicks the button,
Flex calls the myClickHandler() function.
<?xml version="1.0"?>
<!-- events/AddEventListenerExample.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
initialize="createListener()">
<mx:Script><![CDATA[
import mx.controls.Alert;
private function createListener():void {
b1.addEventListener(MouseEvent.CLICK, myClickHandler, false, 0);
}
private function myClickHandler(e:MouseEvent):void {
Alert.show("The button was clicked");
}
]]></mx:Script>
<mx:Button label="Click Me" id="b1"/>
</mx:Application>
<mx:Button id='b1'
label="Click Me"
initialize='b1.addEventListener(MouseEvent.CLICK, myClickHandler,
false, 1);'
/>
</mx:Application>
Using events 97
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
This is the equivalent of defining the event handler inline. However, defining a handler by
using the addEventListener() method rather than setting click="handler_function"
lets you set the value of the useCapture and priority properties of the Event object.
Furthermore, you cannot remove a handler added inline, but when you use the
addEventListener() method to add a handler, you can call the removeEventListener()
method to remove that handler.
98 Using Events
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
For example, the following code creates two functions: foo(), which returns a nested
function named rectArea() that calculates the area of a rectangle, and bar(), which calls
foo() and stores the returned function closure in a variable named myProduct. Even though
the bar() function defines its own local variable x (with a value of 2), when the function
closure myProduct() is called, it retains the variable x (with a value of 40) defined in function
foo(). The bar() function therefore returns the product of the numbers in the TextInput
controls, rather than 8.
<?xml version="1.0"?>
<!-- events/FunctionReturnsFunction.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="foo()">
<mx:Script><![CDATA[
[Bindable]
private var answer:String;
]]></mx:Script>
<mx:Form>
<mx:FormItem label="X">
<mx:TextInput id="ti1" text="10"/>
</mx:FormItem>
<mx:FormItem label="Y">
<mx:TextInput id="ti2" text="20"/>
</mx:FormItem>
<mx:Label id="label1" text="{answer}"/>
</mx:Form>
Using events 99
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
function(e:Event) { /* My listener function. */ },
false, 0, true);
In this example, passing true as the last argument can lead to unexpected results. To Flex, an
inner function is actually an object, and can be freed by the garbage collector. If you set the
value of the useWeakReference argument to true, as shown in the previous example, then
there are no persistent references at all to the inner function. The next time the garbage
collector runs, it might free the function, and the function will not be called when the event is
triggered.
If there are other references to the inner function (for example, if you saved it in another
variable), then the garbage collector will not free it.
Regular class-level member functions are not subject to garbage collection; as a result, you can
set the value of the useWeakReference argument to true and they will not be garbage
collected.
The event_type and listener_function parameters are required. These are the same as the
required parameters for the addEventListener() method.
The use_capture parameter is also identical to the parameter used in the
addEventListener() method. Recall that you can listen for events during all event phases by
calling addEventListener() twice; once with use_capture set to true, and again with it set
to false. To remove both event listeners, you must call removeEventListener() twice; once
with use_capture set to true, and again with it set to false.
You can only remove event listeners that you added with the addEventListener() method
in an ActionScript block. You cannot remove an event listener that was defined in the MXML
tag, even if it was registered using a call to the addEventListener() method that was made
inside a tag attribute.
import flash.events.Event;
</mx:Application>
</mx:Application>
In the class file, you just add the static keyword to the method signature:
// events/MyStaticEventHandler.as
import flash.events.Event;
<mx:Button id="b1"
label="Do Both Actions"
click='submitForm(event); debugMessage(event);'
/>
</mx:Application>
]]></mx:Script>
</mx:Application>
</mx:Application>
You can set the order in which event listeners are called by using the priority parameter of
the addEventListener() method. You cannot set a priority for a listener function if you
added the event listener using MXML inline. For more information on setting priorities, see
“Event priorities” on page 122.
]]></mx:Script>
<mx:Button id="b1"
label="Click Me"
click="submitForm(event)"
/>
<mx:Button id="b2"
label="Click Me"
click="submitForm(event)"
/>
</mx:Application>
]]></mx:Script>
</mx:Application>
When doing this, you should add logic to the event listener that processes the type of event.
The event target (or object that dispatched the event) is added to the Event object for you. No
matter what triggered the event, you can conditionalize the event processing based on the
target or type properties of the Event object. Flex adds these two properties to all Event
objects.
</mx:Application>
<mx:VBox horizontalAlign="center">
<mx:Button id="b1"
label="Up"
click='runMove("up",event);'
width="50"
/>
<mx:HBox horizontalAlign="center">
<mx:Button id="b2"
label="Left"
click='runMove("left",event);'
width="50"
/>
<mx:Button id="b3"
label="Right"
click='runMove("right",event);'
</mx:Application>
When dispatching an event, you must create a new Event object. The syntax for the Event
object constructor is as follows:
Event(event_type:String, bubbles:Boolean, cancelable:Boolean)
The event_type parameter is the type property of the Event object. The bubbles and
cancelable parameters are optional and both default to false. For information on bubbling
and capturing, see “Event propagation” on page 115.
]]></mx:Script>
<mx:VBox id="vb1">
<mx:Button id="b1" label="B1"/>
<mx:Button id="b2" label="B2"/>
<mx:TextArea id="ta1"/>
</mx:VBox>
</mx:Application>
For more information on creating custom classes, see Creating and Extending Flex Components.
Event propagation
When events are triggered, there are three phases in which Flex checks whether there are event
listeners. These phases occur in the following order:
■ First, capturing
■ Next, targeting
■ Finally, bubbling
During each of these phases, the nodes have a chance to react to the event. For example,
assume the user clicks a Button control that is inside a VBox container. During the capturing
phase, Flex checks the Application object and the VBox for listeners to handle the event. Flex
then triggers the Button’s listeners in the target phase. In the bubbling phase, the VBox and
then the Application are again given a chance to handle the event now in the reverse order
from the order in which they were checked in the capturing phase.
In ActionScript 3.0, you can register event listeners on a target node and on any node along
the event flow. Not all events, however, participate in all three phases of the event flow. Some
types of events are dispatched directly to the target node and participate in neither the
capturing nor the bubbling phases. All events can be captured unless they are dispatched from
the top node.
Other events may target objects that are not on the display list, such as events dispatched to an
instance of the Socket class. These event objects flow directly to the target node, without
participating in the capturing or bubbling phases. You can also cancel an event as it flows
through the event model so that even though it was supposed to continue to the other phases,
you stopped it from doing so. You can do this only if the cancelable property is set to true.
Capturing and bubbling happen as the Event object moves from node to node in the display
list: parent-to-child for capturing and child-to-parent for bubbling. This process has nothing
to do with the inheritance hierarchy. Only DisplayObject objects (visual objects such as
containers and controls) can have a capturing phase and a bubbling phase in addition to the
targeting phase.
In this case, in the Button event’s click event listener, the event.currentTarget property
always refers to the Button, while event.target might be either the Button or its
UITextField, depending on where on the Button control the user clicked.
If your listener is on the click event of the Button control, the following steps occur during
the capturing phase if capturing is enabled:
1. Check the Application container for click event listeners.
2. Check the Panel container for click event listeners.
3. Check the TitleWindow container for click event listeners.
During the capturing phase, Flex changes the value of the currentTarget property on the
Event object to match the current node whose listener is being called. The target property
continues to refer to the dispatcher of the event.
By default, no container listens during the capturing phase. The default value of the
use_capture argument is false . The only way to add a listener during this phase is to pass
true for the use_capture argument when calling the addEventListener() method, as the
following example shows:
myPanel.addEventListener(MouseEvent.MOUSE_DOWN, clickHandler, true);
If you add an event listener inline with MXML, Flex sets this argument to false; you cannot
override it.
If you set the use_capture argument to true—in other words, if an event is propagated
through the capturing phase—the event can still bubble, but capture phase listeners will not
react to it. If you want your event to traverse both the capturing and bubbling phases, you
must call addEventListener() twice: once with use_capture set to true, and then again
with use_capture set to false.
The capturing phase is very rarely used, and it can also be computationally intensive. By
contrast, bubbling is much more common.
Bubbling phase
In the bubbling phase, Flex examines an event’s ancestors for event listeners. Flex starts with
the dispatcher’s immediate ancestor and continues up the display list to the root ancestor. This
is the reverse of the capturing phase.
For example, if you have an application with a Panel container that contains a TitleWindow
container that contains a Button control, the structure appears as follows:
Application
Panel
TitleWindow
Button
If your listener is on the click event of the Button control, the following steps occur during
the bubble phase if bubbling is enabled:
1. Check the TitleWindow container for click event listeners.
2. Check the Panel container for click event listeners.
3. Check the Application container for click event listeners.
An event only bubbles if its bubbles property is set to true. Mouse events and keyboard
events are among those that bubble; it is less common for higher-level events that are
dispatched by Flex to bubble. Events that can be bubbled include change, click,
doubleClick, keyDown, keyUp, mouseDown, and mouseUp. To determine whether an event
bubbles, see the event’s entry in Adobe Flex Language Reference.
During the bubbling phase, Flex changes the value of the currentTarget property on the
Event object to match the current node whose listener is being called. The target property
continues to refer to the dispatcher of the event.
When Flex invokes an event listener, the Event object might have actually been dispatched by
an object deeper in the display list. The object that originally dispatched the event is the
target. The object that the event is currently bubbling through is the currentTarget. So,
you should generally use the currentTarget property instead of the target property when
referring to the current object in your event listeners.
</mx:Application>
Stopping propagation
During any phase, you can stop the traversal of the display list by calling one of the following
methods on the Event object:
■ stopPropagation()
■ stopImmediatePropagation()
Event priorities
You can register any number of event listeners with a single event. Flex registers event listeners
in the order in which the addEventListener() methods are called. Flex then calls the
listener functions when the event occurs in the order in which they were registered. However,
if you register some event listeners inline and some with the addEventListener() method,
the order in which the listeners are called for a single event can be unpredictable.
You can change the order in which Flex calls event listeners by using the priority parameter
of the addEventListener() method. It is the fourth argument of the addEventListener()
method.
</mx:Application>
You can set the event priority to any valid integer, positive or negative. The default value is 0.
If multiple listeners have the same priority, Flex calls them in the order in which they were
registered.
If you want to change the priority of an event listener once the event listener has already been
defined, you must remove the listener by calling the removeEventListener() method. You
add the event again with the new priority.
The priority parameter of the addEventListener() method is not an official part of the
DOM Level 3 events model. ActionScript 3.0 provides it so that programmers can be more
flexible when organizing their event listeners.
<mx:Canvas id="myCanvas"/>
</mx:Application>
</mx:Application>
</mx:Application>
<mx:Canvas id="myCanvas"/>
</mx:Application>
Notice that this application must have focus when you run it in a browser so that the
application can capture keyboard events.
<mx:VBox id="my_vbox">
<mx:TextInput id="my_textinput"/>
</mx:VBox>
</mx:Application>
When you examine the trace() method output, you will notice that the target property of
the KeyboardEvent object stays the same because it refers to the original dispatcher of the
event (in this case, my_textinput). But the currentTarget property changes depending on
what the current node is during the bubbling (in this case, it changes from my_textinput to
my_vbox to the application itself).
The order of calls to the event listener is determined by the object hierarchy and not the order
in which the addEventListener() methods were called. Child controls dispatch events
before their parents. In this example, for each key pressed, the TextInput control dispatches
the event first, the VBox container next, and finally the application.
When handling a key or key combination that the underlying operating system or browser
recognizes, the operating system or browser generally processes the event first. For example, in
Microsoft Internet Explorer, pressing Control+w closes the browser window. If you trap that
combination in your Flex application, Internet Explorer users never know it, because the
browser closes before the ActiveX Flash Player has a chance to react to the event.
Property Description
altKey Is set to true if the Alt key was held down when the user pressed the mouse
button; otherwise, false.
ctrlKey Is set to true if the Control key was held down when the user pressed
mouse button; otherwise, false.
shiftKey Is set to true if the Shift key was held down when the user pressed mouse
button; otherwise, false.
The following example deletes button controls, based on whether the user holds down the
Shift key while pressing the mouse button:
<?xml version="1.0"?>
<!-- events/DetectingShiftClicks.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp()">
<mx:Script><![CDATA[
import mx.controls.Button;
b1.addEventListener(MouseEvent.CLICK, removeButtons);
b2.addEventListener(MouseEvent.CLICK, removeButtons);
addChild(b1);
addChild(b2);
}
</mx:Application>
CHAPTER 6
Another common name for an HTTP service is a REST-style web service. REST stands
for Representational State Transfer and is an architectural style for distributed
hypermedia systems. For more information about REST, see www.ics.uci.edu/~fielding/
pubs/dissertation/rest_arch_style.htm.
Contents
About data access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
Comparing Flex data access to other technologies . . . . . . . . . . . . . . . . . . . . . . . . . . 137
133
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
■ What is the best type of service to use? For more information, see “HTTPService
components” on page 134, “WebService components” on page 135, and “RemoteObject
components” on page 136.
■ What is the best way to pass data to a service? For more information, see “Explicit
parameter passing and parameter binding” on page 1454.
■ How do you want to handle data results from a service? For more information, see
“Handling service results” on page 1465.
HTTPService components
HTTPService components let you interact with HTTP services, which can be any HTTP
URI that accepts HTTP requests and sends responses. Although you can use the
HTTPService component to consume different types of responses, it is typically used to
consume XML. You can use an HTTPService component with any kind of server-side
technology, including PHP pages, ColdFusion Pages, JavaServer Pages (JSPs), Java servlets,
Ruby on Rails, and Microsoft ASP pages.
HTTPService components are a good option for working server-side technologies that are
accessible over HTTP and are not available as a web service or remoting service.
HTTPService components let you send HTTP GET, POST, HEAD, OPTIONS, PUT,
TRACE or DELETE requests, and include data from HTTP responses in a Flex application.
Flex does not support mulitpart form POSTs.
You can use an HTTPService component for CGI-like interaction in which you use HTTP
GET, POST, HEAD, OPTIONS, PUT, TRACE, or DELETE to send a request to a specified
URI. When you call the HTTPService object’s send() method, it makes an HTTP request to
the URI specified in the url property, and an HTTP response is returned. Optionally, you
can pass request arguments to the specified URI.
The following example shows an HTTPService component that calls a PHP page. This
HTTPService component provides two request arguments, username and emailaddress.
Additional code in the application calls the PHP page to perform database queries and inserts,
and provide the data returned from the PHP page to the user interface of the Flex application.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application>
...
<mx:HTTPService id="userRequest" url="http://server/myproj/
request_post2.php" useProxy="false" method="POST">
<mx:request xmlns="">
<username>{username.text}</username>
<emailaddress>{emailaddress.text}</emailaddress>
</mx:request>
For more information on creating HTTP services and accessing them with HTTPService
components, see “Using HTTPService components” on page 1425.
WebService components
WebService components let you access web services, which are software modules with
methods, commonly referred to as operations; web service interfaces are defined by using
XML. Web services provide a standards-compliant way for software modules that are running
on a variety of platforms to interact with each other. For more information about web
services, see the web services section of the World Wide Web Consortium’s website at
www.w3.org/2002/ws/.
Flex applications can interact with web services that define their interfaces in a Web Services
Description Language (WSDL) document, which is available as a URL. WSDL is a standard
format for describing the messages that a web service understands, the format of its responses
to those messages, the protocols that the web service supports, and where to send messages.
The Flex web service API generally supports SOAP 1.1, XML Schema 1.0 (versions 1999,
2000 and 2001), WSDL 1.1 rpc-encoded, rpc-literal, document-literal (bare and wrapped
style parameters). The two most common types of web services use RPC-encoded or
document-literal SOAP bindings; the terms encoded and literal indicate the type of WSDL-to-
SOAP mapping that a service uses.
Flex applications support web service requests and results that are formatted as SOAP
messages and are transported over HTTP. SOAP provides the definition of the XML-based
format that you can use for exchanging structured and typed information between a web
service client, such as a Flex application, and a web service.
You can use a WebService component to connect to a SOAP-compliant web service when web
services are an established standard in your environment.
The following example shows a WebService component that calls a web service. This
WebService component calls two web service operations, returnRecords() and
insertRecord(). Additional code in the application calls the web service to perform database
queries and inserts, and provide the data returned from the web service to the user interface of
the Flex application.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application>
...
<mx:WebService
id="userRequest"
wsdl="http://server:8500/flexapp/returncfxml.cfc?wsdl">
For more information about accessing web services with WebService components, see “Using
WebService components” on page 1436.
RemoteObject components
RemoteObject components let you access the methods of server-side objects, such as
ColdFusion components (CFCs), Java objects, PHP objects, and .NET objects, without
configuring the objects as web services. You can use RemoteObject components in MXML or
ActionScript
You can use RemoteObject components with Macromedia® ColdFusion® MX 7.0.2 from
Adobe or Adobe LiveCycle Data Services ES. To access a remote object, you specify its fully
qualified classname or ColdFusion CFC name in the RemoteObject component’s source
property, or you use the destination property to specify a logical name that is mapped to a
fully qualified Java class name in a server-side configuration file, the remoting-config.xml file.
You can also use RemoteObject components with PHP and .NET objects in conjunction
with third-party software, such as the open source projects AMFPHP and SabreAMF, and
Midnight Coders WebORB. Visit the following websites for more information:
■ AMFPHP http://amfphp.sourceforge.net/
■ SabreAMF http://www.osflash.org/sabreamf
■ Midnight Coders WebORB http://www.themidnightcoders.com/
When you use a RemoteObject tag, data is passed between your application and the server-
side object in the binary Action Message Format (AMF) format.
The following example shows a RemoteObject component that calls a web service. This
WebService component calls two web service operations, returnRecords() and
insertRecord(). Additional code in the application calls the web service to perform database
queries and inserts, and provide the data returned from the web service to the user interface of
the Flex application.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application>
...
<mx:RemoteObject
For more information about creating remoting services and accesing them with
RemoteObject components, see“Using RemoteObject components” on page 1447.
<mx:TextInput id="input"/>
</mx:Application>
The following example shows JSP code for calling a web service using a JSP custom tag.
When a user requests this JSP, the web service request is made on the server instead of on the
client, and the result is used to generate content in the HTML page. The application server
regenerates the entire HTML page before sending it back to the user’s web browser.
<%@ taglib prefix="web" uri="webservicetag" %>
PART 2
141
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
CHAPTER 7
Contents
About visual components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Class hierarchy for visual components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
Using the UIComponent class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
Sizing visual components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .151
Handling events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
Using styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
Using behaviors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
Applying skins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
Changing the appearance of a component at run time . . . . . . . . . . . . . . . . . . . . . . . 165
Extending components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
143
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
This topic contains an overview of many of the characteristics of visual components,
including the following:
Size Height and width of a component. All visual components have a default size. You can
use the default size, specify your own size, or let Flex resize a component as part of laying out
your application.
Events Application or user actions that require a component response. Events include
component creation, mouse actions such as moving the mouse over a component, and button
clicks.
Styles Characteristics such as font, font size, and text alignment. These are the same styles
that you define and use with Cascading Style Sheets (CSS).
Behaviors Visible or audible changes to the component triggered by an application or user
action. Examples of behaviors are moving or resizing a component based on a mouse click.
Skins Classes that control a visual component’s appearance.
Object
EventDispatcher
DisplayObject
InteractiveObject
DisplayObjectContainer
Sprite
UIComponent
All components
<mx:Script>
<![CDATA[
public function handleClick():void {
text1.text="Thanks for the click!";
}
]]>
</mx:Script>
<mx:Button id="button1"
label="Click here!"
width="100"
fontSize="12"
click="handleClick();"/>
<mx:TextArea id="text1"/>
</mx:Application>
This example has the following elements:
■ The id property is inherited by the Button control from the UIComponent class. You use
it to specify an identifier for the component. This property is optional, but you must
specify it if you want to access the component in ActionScript.
■ The label property is defined by the Button control. It specifies the text that appears in
the button.
■ The width property is inherited from the UIComponent class. It optionally specifies the
width of the button, in pixels.
■ The Button control dispatches a click event when the user when a user presses and
releases the main mouse button. The MXML click attribute specifies the ActionScript
code to execute in response to the event.
■ The fontSize style is inherited from the UIComponent class. It specifies the font size of
the label text, in pixels.
<mx:Button id="button1"
label="Click here!"
width="100"
fontSize="12"
click="text1.text='Thanks for the click!';"/>
<mx:TextArea id="text1"/>
</mx:Application>
Both of these examples result in the following image, shown after the button was clicked:
N OTE
Although you can specify multiple lines of ActionScript code, separated by semicolons,
as the value of the click event attribute, for readability you should limit the click event to
only one or two lines of code.
For more information on how components are created, see “About the component
instantiation life cycle” on page 159.
You can use the initialize event to configure most component characteristics; in particular,
use it to configure any value that affects the component’s size. Use the creationComplete
event if your initialization code must get information about the component layout.
The following example configures Flex to call the initDate() function when it initializes the
Label control. When Flex finishes initializing the Label control, and before the application
appears, Flex calls the initDate() function.
<?xml version="1.0"?>
<!-- components\LabelInit.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
private function initDate():void {
label1.text += new Date();
}
]]>
</mx:Script>
<mx:Box borderStyle="solid">
<mx:Label id="label1"
text="Today's Date: "
initialize="initDate();"/>
</mx:Box>
</mx:Application>
This example produces the following image:
<mx:Box borderStyle="solid">
<mx:Label id="label1"
text="Today's Date:"
initialize="label1.text += new Date();"/>
</mx:Box>
</mx:Application>
As with other calls that are embedded within component definitions, you can add multiple
ActionScript statements to the initialize MXML attribute by separating each function or
method call with a semicolon. The following example calls the initDate() function and
writes a message in the flexlog.txt file when the label1 component is instantiated:
<?xml version="1.0"?>
<!-- components\LabelInitASAndEvent.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
private function initDate():void {
label1.text += new Date();
}
]]>
</mx:Script>
<mx:Box borderStyle="solid">
<mx:Label id="label1"
text="Today's Date:"
initialize="initDate(); trace('The label is initialized!');"/>
</mx:Box>
</mx:Application>
Read-only You cannot use a read-only To get the value of a read-only property:
property property as an attribute in MXML. var theClass:String=mp1.className;
Percentage-based sizing You specify the component size as a percentage of its container
size. To do this, you specify the percentHeight and percentWidth properties, or, in an
MXML tag, set the height and width properties to percentage values such as 100%. The
following code, for example, sets percentage-based dimensions for an HBox container:
<mx:HBox id="hBox1" xmlns:mx="http://www.adobe.com/2006/mxml"
height="30%"
width="90%"/>
The following ActionScript line resets the HBox width to a different percentage value:
hBox1.percentWidth=40;
Constraint-based layout You can control size and position by anchoring components sides,
centers, or baselines to locations in their container by specifying the top, bottom, left,
right, baseline, horizontalCenter, and verticalCenter styles. You can use constraint-
based layout only for the children of a container that uses absolute layout; the Application and
Panel containers can optionally use this layout, and the Canvas container always uses it. The
following example uses constraint-based layout to position an HBox horizontally, and explicit
sizing and positioning to determine the vertical width and position:
<mx:HBox id="hBox2" xmlns:mx="http://www.adobe.com/2006/mxml"
left="30"
right="30"
y="150"
height="100"/>
You can mix sizing techniques; however, you must ensure that the mix is appropriate. Do not
specify more than one type of sizing for a component dimension; for example, do not specify
a height and a percentHeight for a component. Also, ensure that the resulting sizes are
appropriate; for example, if you do not want scroll bars or clipped components, ensure that
the sizes of a container’s children do not exceed the container size.
For detailed information on how Flex sizes components, and how you can specify sizing, see
Chapter 9, “Sizing and Positioning Components,” on page 225.
<mx:Script>
<![CDATA[
private function logSizes():void {
trace("HBox: "+ hb1.width);
trace("Label: "+ lb1.width);
trace("Image: "+ img1.width);
trace("Button: "+ b1.width);
}
]]>
</mx:Script>
<mx:Script>
<![CDATA[
private function logSizes():void {
trace("HBox: "+ hb1.width);
trace("Label: "+ lb1.width);
trace("Image: "+ img1.width);
trace("Button: "+ b1.width);
}
]]>
</mx:Script>
<mx:Script>
<![CDATA[
private function logSizes():void {
trace("HBox: "+ hb1.width);
trace("Label: "+ lb1.width);
trace("Image: "+ img1.width);
trace("Button: "+ b1.width);
}
]]>
</mx:Script>
<mx:HBox width="100%">
<mx:HBox id="hb1" width="40%" borderStyle="solid">
<mx:Label id="lb1"
text="Hello"
width="50"/>
<mx:Image id="img1"
source="@Embed(source='assets/flexlogo.jpg')"
width="60%"/>
<mx:Button id="b1"
label="Button"
width="40%"
click="logSizes();"/>
</mx:HBox>
<mx:Script>
<![CDATA[
import mx.controls.Alert;
private function handleAccChange():void {
Alert.show("You just changed views");
}
]]>
</mx:Script>
You can pass an event object, which contains information about the event, from the
component to the event listener.
<mx:Script>
<![CDATA[
// Import the class that defines the event object.
import mx.events.IndexChangedEvent;
import mx.controls.Alert;
The following steps show what occurs when you execute the ActionScript code to create the
Button control, and add it to the Box container. When you create the component in MXML,
Flex SDK generates equivalent code.
1. You call the component’s constructor, as the following code shows:
// Create a Button control.
var button1:Button = new Button()
2. You configure the component by setting its properties, as the following code shows:
// Configure the button control.
button1.label = "Submit";
3. You call the addChild() method to add the component to its parent, as the following code
shows:
// Add the Button control to the Box container.
box1.addChild(button1);
Using styles
Flex defines styles for setting some of the characteristics of components, such as fonts,
padding, and alignment. These are the same styles as those defined and used with Cascading
Style Sheets (CSS). Each visual component inherits many of the styles of its superclasses, and
can define its own styles. Some styles in a superclass might not be used in a subclass. To
determine the styles that a visual component supports, see the styles section of the page for the
component in Adobe Flex Language Reference.
You can set all styles in MXML as tag attributes. Therefore, you can set the padding between
the border of a Box container and its contents by using the paddingTop and paddingBottom
properties, as the following example shows:
<?xml version="1.0"?>
<!-- components\MXMLStyles.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:VBox id="myVBox2"
borderStyle="solid"
paddingTop="12"
paddingBottom="12" >
<mx:Button label="Submit"/>
</mx:VBox>
</mx:Application>
<mx:Script>
<![CDATA[
private function initVBox():void {
myVBox2.setStyle("paddingTop", 12);
myVBox2.setStyle("paddingBottom", 12);
}
]]>
</mx:Script>
<mx:VBox id="myVBox2"
borderStyle="solid"
initialize="initVBox();">
<mx:Button label="Submit"/>
</mx:VBox>
</mx:Application>
When you use the <mx:Style> tag, you set the styles using CSS syntax or a reference to an
external file that contains style declarations, as the following example shows:
<?xml version="1.0"?>
<!-- components\TagStyles.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Style>
.myStyle {paddingTop: 12; paddingBottom: 12;}
</mx:Style>
<mx:VBox id="myVBox2"
styleName="myStyle"
borderStyle="solid">
<mx:Button label="Submit"/>
</mx:VBox>
</mx:Application>
<mx:Style>
Box {paddingTop: 12; paddingBottom: 12;}
</mx:Style>
For more information on styles, see Chapter 20, “Using Styles and Themes,” on page 767.
Using behaviors
A behavior is a combination of a trigger paired with an effect. A trigger is an action similar to
an event, such as a mouse click on a component, a component getting focus, or a component
becoming visible. An effect is a visible or audible change to the component that occurs over a
period of time, measured in milliseconds. Examples of effects are fading, resizing, or moving a
component. You can define multiple effects for a single trigger.
For detailed information on using behaviors, see Chapter 19, “Using Behaviors,” on page 719.
<mx:Script>
<![CDATA[
public function moveButton():void {
myButton.x += 15;
myButton.y += 15;
}
]]>
</mx:Script>
<mx:Button id="myButton"
x="15"
y="15"
label="Move"
click="moveButton();"/>
</mx:Application>
The following example shows the initial image and the results after the user clicks the button
each of two times:
In this application, you can move the Button control without concern for other components.
However, moving a component in an application that contains multiple components, or
modifying one child of a container that contains multiple children, can cause one component
to overlap another, or in some other way affect the layout of the application. Therefore, you
should be careful when you perform run-time modifications to container layout.
<mx:Script>
<![CDATA[
public function resizeButton():void {
myButton.height = myButton.height + 15;
myButton.width = myButton.width + 15;
}
]]>
</mx:Script>
<mx:VBox
borderStyle="solid"
height="80"
width="100" >
<mx:Button id="myButton"
label="Resize"
click="resizeButton();"/>
</mx:VBox>
</mx:Application>
This example results in the following progression when the user clicks the button:
If the container that holds the Button does not use absolute positioning, it repositions its
children based on the new size of the Button control. The Canvas container and Panel and
Application containers with layout="absolute" perform no automatic layout, so changing
the size of one of their children does not change the position or size of any of the other
children.
N OTE
The stored values of width and height are always in pixels regardless of whether the
values were originally set as fixed values, as percentages, or not set at all.
<MyComps:MyComboBox id="stateNames"/>
</mx:Application>
In this example, the new component is in the same directory as your application file, and
maps the local namespace, indicated by the asterisk (*), to the MyComps identifier.
Flex lets you create custom components using either of the following methods. The method
you choose depends on your application and the requirements of your component.
■ Create components as MXML files and use them as custom tags in other MXML files.
MXML components provide an easy way to extend an existing component, particularly to
modify the behavior of an existing component or add a basic feature to an existing
component.
CHAPTER 8
Contents
About data providers and collections. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
Using IList interface methods and properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
Using ICollectionView interface methods and properties . . . . . . . . . . . . . . . . . . . . . 186
</mx:Application> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
Using hierarchical data providers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .207
Using remote data providers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .223
171
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
About data providers
Several Flex framework components, including all List based controls, represent data from a
data provider, an object that contains data required by the control. For example, a Tree
control’s data provider determines the structure of the tree and any associated data assigned to
each tree node, and a ComboBox control’s data provider determines the items in the control’s
drop-down list. Many standard controls, including the ColorPicker and MenuBar controls
also get data from a data provider. Controls that display application data are sometimes
referred to as data provider controls.
The following components use data providers:
■ Repeater component
■ Chart controls, such as the LineChart control
■ ColorPicker control
■ ComboBox control
■ DataGrid control
■ DateField control
■ HorizontalList control
■ List control
■ Menu control
■ MenuBar control
■ PopUpMenuButton control
■ TileList control
■ Tree control
■ ButtonBar control
■ LinkBar control
■ TabBar control
■ ToggleButtonBar control
When Flex creates a UID for an object, such as an item in an ArrayCollection, it adds the
UID as an mx_internal_uid property of the item. Flex creates mx_internal_uid properties
for any objects that are dynamic and do not have bindable properties. To avoid having
Flex create mx_internal_uid properties, the object class should do any of the following
things: have at least one property with a [Bindable] metadata tag, implement the IUID
interface, or have a uid property with a value.
If Flex must consider two or more different objects to be identical you must implement the
IUID interface so that you can assign the same uid to multiple objects. A typical case where
you must implement the IUID interface is an application that uses windowed paged
collections. As the cursor moves through the collection, a particular item might be pulled
down from the server and released from memory repeatedly. Every time the item is pulled into
memory a new object is created to represent the item. If you need to compare items for
equality, Flex should consider all objects that represent the same item to be the same “thing.”
More common than the case where you must implement the IUID interface is the case where
you can improve processing efficiency by doing so. As a general rule, you do not implement
the IUID interface if the data provider elements are members of dynamic classes. Flex can
automatically create a uid property for these classes. There is still some inefficiency however,
so you might consider implementing the IUID interface if processing efficiency is particularly
important.
In all other cases, Flex uses the Dictionary mechanism to manage the uid, which might not be
as efficient as supplying your own UID.
Because the Object and Array classes are dynamic, you normally do not do anything special
for data providers whose items belong to these classes. However, you should consider
implementing the IUID if your data provider members belong to custom classes that you
define.
[Bindable]
public class Person implements IUID {
public var id:String;
public var firstName:String;
public var lastName:String;
private var _uid:String;
You do not need to use the UIDUtil class in a case where the objects contain a uniquely-
identifying field such as an employee ID. In this case, you can use the person’s ID as the uid
property, because the uid property values have uniquely identify the object only in the data
provider. The following example implements this approach.
package
{
import mx.core.IUID;
[Bindable]
public class Person implements IUID {
public var employee_id:String;
public var firstName:String;
public var lastName:String;
Object cloning does not manage or have a relationship with UIDs, so if you clone
something that has an internal UID you must also change that internal UID. UIDs are
stored on mx_internal_uid only for dynamic Objects. Instances of data classes that
implement IUID will store their UIDs in a .uid property so that is the property that must be
changed after cloning.
However, dataproviders do not need to implement IUID. If they are instances of data
classes that do not implement IUID and are not dynamic objects, the clone technique
should work correctly, but most dataprovider items should implement IUID, especially if
cloning those objects is not required.
About collections
A collection provides a uniform method to access and represent a data provider’s data. The
collection creates a level of abstraction between Flex components and the data that you use to
populate them. The collection interfaces and implementations provide the following features:
■ They ensure that a control is properly updated when the underlying data changes.
Controls do not update when non-collection data providers change. (They do update to
reflect the new data the next time they are refreshed.) If the data provider is a collection,
the controls update immediately after the collection change occurs.
■ They provide mechanisms for handling paged data coming from remote data providers
that may not initially be available and may arrive over a period of time.
■ They provide a consistent set of operations on the data, independent of those provided by
the raw data provider objects. For example, you could create a custom class that
implements the IList interface and lets you insert and delete objects by using an index into
the collection, independent of whether the underlying data is, for example, in an array or
an object.
■ Collections that conform to the ICollectionView interface provide a specific view of the
data that can be in sorted order, or filtered by a developer-supplied method. These
limitations affect only the collection’s view, and do not change the underlying data.
■ You can use a single collection to populate multiple components from the same data
provider.
If you use a raw object, such as an Array, as a control’s data provider, Flex automatically
wraps the object in a collection wrapper. The control does not automatically detect
changes that are made directly to the raw object. A change in the length of an array, for
example, does not result in an update of the control. You can, however, use an object
proxy, a listener interface, or the itemUpdated property to notify the view of certain
changes.
Collection interfaces
The Flex framework collection model uses these interfaces to define how a collection
represents data and provides access to it:
Interface Description
IList A direct representation of items organized in an ordinal fashion. The
interface presents the data from the data provider in the same order as it
exists in the provider, and provides access and manipulation methods
based on an index. The IList class does not provide sorting, filtering, or
cursor functionality.
ICollectionView A view of a collection of items. You can modify the view to show the data
in sorted order and to show a subset of the items in the data provider, as
specified by a filter function. A class that implements this interface can
use an IList interface as the underlying collection.
The interface provides access to an IViewCursor object for access to the
items.
The IList and ICollectionView interfaces provide two alternate methods for accessing and
changing data. The IList interface is simpler; it provides add, set, get, and remove operations
that operate directly on linear data.
The ICollectionView interface (also called the collection view) provides a more complex set of
operations than the IList interface, and is appropriate when the underlying data may not be
organized linearly. Its data access techniques, however, are more complex than those of the
IList interface, so you should use the IList interface if you need only simple, indexed access to
a linear collection. The collection view can represent a subset of the underlying data, as
determined by a sort or filter operation.
Collection classes
The following table describes the public classes in the mx.collections package. It does not
include constant classes, event and error classes. For complete reference information on
collection-related classes, see the collections and collections.errors packages, and the
CollectionEvent and CollectionEventKind classes in Adobe Flex Language Reference.
Class Description
ArrayCollection Implements the IList and ICollectionView interfaces for use with array-
based data providers.
SortField Provides properties and methods that determine how a specific field
affects how data is sorted in an ICollectionView instance.
ItemResponder (Used only if the data source is remote.) Handles cases when requested
data is not yet available.
It is generally a better practice, and highly recommended, to reference the collection directly,
as in the following example:
<mx:Button label="Add AZ"
click="stateArray.addItem({'label':'AZ', 'data':'Phoenix'});"/>
You can then manipulate the interface as needed to select data for viewing, or to get and
modify the data in the underlying data source. For more detailed information the techniques
provided by the collection interfaces, see Using IList interface methods and
properties on page 184 and Using ICollectionView interface methods and
properties on page 186.
<mx:HBox width="100%">
<!-- A ComboBox populated by the underlying Array object.
This control shows that Array retains its original order
and MD is inserted at the end of the Array. -->
<mx:ComboBox id="cb2" rowCount="10" dataProvider="{myArray}"/>
<!-- A ComboBox populated by the collection view of the Array. -->
<mx:ComboBox id="cb1" rowCount="10" dataProvider="{myAC}"/>
<mx:Button id="b1" label="Add MD" click="addItemToMyAC();"/>
If you use the ICollectionView interface to sort or filter a collection, do not use the IList
interface to manipulate the data, as the results are indeterminate.
The interface includes properties and methods that let you do the following:
■ Get, set, add, or remove an item at a specific index into the collection.
■ Add an item at the end of the collection.
■ Get the index of a specific item in the collection.
■ Remove all items in the collection.
■ Get the length of the collection.
You can use the IList interface methods and properties directly on any of the following classes
or properties:
■ ArrayCollection class
■ XMLList class
■ dataProvider property of standard Flex controls.
The following sample code uses an ArrayCollection object and its implementation of the IList
interface methods to display an array of elements in a ComboBox control. For an example
that uses IList interface methods to manage an ArrayCollection of objects with multiple fields,
see “Example: Modifying data in DataGrid control” on page 204.
In the following example the Array data source initially consists of the following elements:
"AZ", "MA", "MZ", "MN", "MO", "MS"
■ Display in a TextArea control information about the tasks it performed and the resulting
array.
The code includes comments that describe the changes to the data provider.
<?xml version="1.0"?>
<!-- dpcontrols\UseIList.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
initialize="initData()">
<mx:Script>
<![CDATA[
import mx.collections.*;
Sorting
The Sort class lets you sort data in the collection. You can specify multiple fields to use in
sorting the data, require that the resulting entries be unique, and specify a custom comparison
function to use for ordering the sorted output. You can also use the Sort class to find items in
a collection. When you create a Sort class, or change its properties, you must call the
refresh() method on the collection to show the results.
You use the SortField class to specify the fields to use in the sort. You create the SortField
objects and put them in the Sort class object’s fields array.
The following shows a function to sort a collection. In this example, myAC is a collection
view of an Array of objects containing label and name fields. The primary sort is a descending,
case-insensitive sort on the area field and the secondary sort is an ascending case-sensitive sort
on the label field. You might call it as the initialize event handler for a control that must
display a specific sorted view of a collection.
//Sort the ICollectionView in descending order.
public function sortAC():void {
//Create a Sort object.
var sortA:Sort = new Sort();
// Sort first on the area field, then the label field.
// The second parameter specifies that the sort is case-insensitive.
// A true third parameter specifies a descending sort.
sortA.fields=[new SortField("area", true, true),
new SortField("label")];
myAC.sort=sortA;
//Refresh the collection view to show the sort.
myAC.refresh();
}
]]>
</mx:Script>
<!-- Buttons to filter, sort, or reset the view in the second ComboBox
control. -->
<mx:HBox width="100%">
<mx:Button id="sortButton" label="Sort" click="sortAC();"/>
<mx:Button id="filterButton" label="Filter" click="filterAC();"/>
<mx:Button id="resetButton" label="Reset" click="resetAC();"/>
</mx:HBox>
<mx:HBox width="100%">
<!-- A ComboBox populated by the underlying Array object.
This control shows that Array retains its original order. -->
<mx:ComboBox id="cb2" rowCount="10" dataProvider="{myArray}"/>
<!-- A ComboBox populated by the collection view of the Array. -->
<mx:ComboBox id="cb1" rowCount="10" dataProvider="{myAC}"/>
</mx:HBox>
</mx:Application>
For a more complex example of sorting a DataGrid control, which both does an initial sort of
the data and does a custom sort when you click a column heading, see “Example: Sorting a
DataGrid on multiple columns” on page 484
■ The findAny(), findFirst(), and findLast(), methods move the cursor to an item
that matches the parameter. Before you can use these methods, you must apply a Sort to
the ICollectionView implementation (because the functions use Sort methods).
If it is not important to find the first occurrence of an item or last occurrence of an item in
a non-unique index, the findAny() method can be somewhat more efficient than either
the findFirst() or the findLast() method.
To find a complex object, the findFirst() method can search on multiple sort fields.
You cannot, however, skip fields in the parameter of any of the find methods. If an object
has three fields, for example, you can specify any of the following field combinations in
the parameter: 1, 1,2, 1,2,3, but you cannot specify only fields 1 and 3.
Both of the following lines will find an object with the label value "ME" and data value
"Augusta":
myCursor.findFirst({label:"ME"});
myCursor.findFirst({label:"ME", data:"Augusta"});
■ The seek() method moves the cursor to a position relative to a bookmark. You use this
method to move the cursor to the first or last item in a view, or to move to a bookmark
position that you have saved. For more information on using bookmarks and the seek()
method, see “Using bookmarks” on page 193
// Initialize variables.
public function run():void {
// Initialize the cursor.
myCursor=myAC.createCursor();
// The findFirst() method, used in
// countFromSelection() requires a
// sorted view.
var sort:Sort = new Sort();
sort.fields=[new SortField("label")];
myAC.sort=sort;
//You must refresh the view to apply the sort.
myAC.refresh();
}
When you click the Update View button, the application uses the length property and
several methods of the ICollectionView interface to do the following:
■ Changes the data in the array and the displayed data in the ComboBox control to a
correct alphabetical list of the U.S. ZIP codes for states that start with M:
MA, ME, MI, MN, MO, MS, MT
■ Saves a bookmark that points to the ME item that it adds, and later restores the cursor to
this position.
■ Displays in a TextArea control information about the tasks it performed and the resulting
array.
When you click the Sort button, the application reverses the order of the items in the view,
and limits the viewed range to ME–MO.
<mx:Script>
<![CDATA[
import mx.collections.*;
// The data provider is an array of Strings.
public var myArray:Array = ["AZ", "MA", "MZ", "MN", "MO", "MS"];
// Declare an ArrayCollection that represents the Array.
// The variable must be bindable so the ComboBox can update
properly.
[Bindable]
public var myAC:ArrayCollection;
//Boolean flag to ensure the update routine hasn't been run
before.
public var runBefore:Boolean=false;
//Reset the Array and update the display to run the example
again.
public function resetView():void {
myArray = ["AZ", "MA", "MZ", "MN", "MO", "MS"];
myAC = new ArrayCollection(myArray);
ta1.text="Reset";
runBefore=false;
}
]]>
</mx:Script>
The CollectionEvent listener method, named reservationsChanged, tests the event kind
field and does the following:
case CollectionEventKind.REMOVE:
for (var i:uint = 0; i < event.items.length; i++) {
removeReservationBox(Reservation(event.items[i]));
}
break;
case CollectionEventKind.UPDATE:
for (var i:uint = 0; i < event.items.length; i++) {
if (event.items[i] is PropertyChangeEvent) {
if (PropertyChangeEvent(event.items[i]) != null) {
updateReservationBox(Reservation(PropertyChangeEvent(
event.items[i]).source));
}
}
else if (event.items[i] is Reservation) {
updateReservationBox(Reservation(event.items[i]));
}
}
break;
case CollectionEventKind.RESET:
refreshReservations();
break;
}
}
For more information on the application and the individual methods, see the sample code.
Assume you have a class that you do not control or edit that looks like the following:
public class ClassICantEdit {
public var field1:String;
public var field2:String;
}
You have an ArrayCollection that uses these object, such as the following, which you populate
with classICantEdit objects.
public var myCollection:ArrayCollection = new ArrayCollection();
When you update a field in the myCollection ArrayCollection, as follows, the DataGrid
does not automatically update.
myCollection.getItemAt(0).field1="someOtherValue";
To update the DataGrid control, you must use the collection’s itemUpdated() method:
myCollection.itemUpdated(collectionOfThoseClasses.getItemAt(0));
<mx:Script>
<![CDATA[
import mx.events.*;
import mx.collections.*;
<mx:HBox>
<!-- Buttons to initiate operations on the collection. -->
<mx:Button label="Add New" click="addPerson()"/>
<mx:Button label="Update Selected" click="updatePerson()"/>
<mx:Button label="Remove Selected" click="removePerson()"/>
<!-- Clear the text input fields. -->
<mx:Button label="Clear" click="clearInputs()"/>
</mx:HBox>
Both Boolean value For all cases, inserts the node as a child object
addChildAt(node, indicating whether before the node currently in the index location.
child, index, [model]) the operation
succeeded.
Both Boolean value For all cases, removes the child of the node in the
removeChildAt indicating whether index location.
(node, index, [model]) the operation
succeeded.
IMenuDataDescriptor Boolean value For XML, returns the value of the enabled attribute
isEnabled(node) indicating if a of the node.
menu node is For other Objects, returns the contents of the
enabled. node’s enabled field.
IMenuDataDescriptor Boolean value For XML, returns the value of the selected
isToggled(node) indicating if a attribute of the node.
menu node is For other Objects, returns the contents of the
selected node’s enabled field.
IMenuDataDescriptor For XML, sets the value of the selected attribute
setToggled(node, of the node to true or false.
value) For other Objects, sets the contents of the node’s
enabled field.
IMenuDataDescriptor The name of the For XML, returns the value of the groupName
getGroupName radio button group attribute of the node.
(node) to which the node For other Objects, returns the contents of the
belongs. node’s groupName field.
The following example Object follows the default data provider structure for a Tree control,
and is correctly handled by the DefaultDataDescriptor class:
[Bindable]
public var fileSystemStructure:Object =
{label:"mx", children: [
{label:"Containers", children: [
{label:"Accordian", children:[]},
{label:"DividedBox", children: [
{label:"BoxDivider.as", data:"BoxDivider.as"},
{label:"BoxUniter.as", data:"BoxUniter.as"}]},
{label: "Grid", children:[]}]},
{label: "Controls", children: [
{label: "Alert", data: "Alert.as"},
{label: "Styles", children: [
{label: "AlertForm.as", data:"AlertForm.as"}]},
For objects, the root is the Object instance, so there must always a single root (as with XML).
You could also use an Array containing nested Arrays as the data provider; in this case the
provider has no root; each element in the top level array appears at the top level of the control.
The DefaultDataDescriptor can properly handle well formed XML nodes. The isBranch()
method, however, returns true only if the parameter node has child nodes or if the node has
an isBranch attribute with the value true. If your XML object uses any technique other than
a true isBranch attribute to indicate empty branches, you must therefore create a custom
data descriptor.
The DefaultDataDescriptor handles collections properly. For example, if a node’s children
property is an ICollectionView, the getChildren() method returns the children as an
ICollectionView object.
import mx.controls.Menu;
public var productMenu:Menu;
]]>
</mx:Script>
<mx:Model id="Products">
<Root>
<Department label="Toys">
<children label="Care Bear"/>
<children label="GI Joe"/>
<children label="Telly Tubbies"/>
</Department>
<Department label="Kitchen">
<children label="Electronics">
<children label="Crock Pot"/>
<children label="Panini Grill"/>
</children>
<children label="Cookware">
<children label="Grill Pan"/>
<children label="Iron Skillet" enabled="false"/>
</children>
</Department>
<!-- The items in this entry are bound to the form data -->
<Department label="{menuName.text}">
<children label="{item1.text}"/>
<children label="{item2.text}"/>
<children label="{item3.text}"/>
</Department>
</Root>
</mx:Model>
}
}
<mx:Script>
<![CDATA[
import mx.collections.*;
import mx.controls.treeClasses.*;
import myComponents.*;
]]>
</mx:Script>
You can use an XML object directly as a dataProvider to a hierarchical data control. However,
if the object changes dynamically, you should do the following:
1. Convert the XML or XMLList object to an XMLListCollection object.
2. Make all update to the data by modifying the XMLListCollection object.
Doing this ensures that the component represents the dynamic data. The XMLListCollection
class supports the use of all IList and ICollectionView interface methods, and adds many of
the most commonly used XMLList class methods. For more information on using
XMLListCollections see “Using the XMLListCollection class” on page 221.
<mx:HBox>
<mx:Button id="treeSelect" label="Add to List"
click="doTreeSelect()"/>
<mx:Button id="listRemove" label="Remove from List"
click="doListRemove()"/>
</mx:HBox>
<mx:ArrayCollection id="ac"
source="mx.utils.ArrayUtil.toArray(employeeWS.getList.lastResult)"/>
<mx:DataGrid dataProvider="{ac}" width="100%">
For more information on using RPC data sources, see Chapter 40, “Accessing Server-Side
Data with Flex,” on page 1425.
CHAPTER 9
Contents
About sizing and positioning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .225
Sizing components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .232
Positioning and laying out controls. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .252
Constraint-based layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
225
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Although Flex has built-in default layout rules, you can use the component’s properties and
methods to customize the layout. All components have several properties, including height
and width, for specifying the component’s size in absolute or container-relative terms. Each
container also has properties and styles that you can use to configure aspects of layout. You
can use settings such as the verticalGap and horizontalGap styles of a Tile container to set
the spacing between children, and the direction property to specify a row or column layout.
You can also use different positioning techniques for laying out components in a container;
some containers, for example, support absolute x- and y-coordinate–based positioning.
Flex coordinates increase from the upper left corner of the frame of reference. Thus, an
x,y position of 100,300 in the local coordinate system is 100 pixels is to the right and
300 pixels down from the component’s upper left corner.
For more information on Flex coordinate systems, see “Using Flex coordinates” on page 582.
There are very few situations where an application programmer must force the layout of a
component; for more information, see “Manually forcing layout” on page 231.
Flex provides two mechanisms for positioning and laying out controls:
Automatic positioning Flex automatically positions a container’s children according to a set
of container- and component-specific rules. Most containers, such as Box, Grid, or Form, use
automatic positioning. Automatic positioning is sometimes referred to as automatic layout.
Absolute positioning You specify each child’s, x and y properties, or use a constraint-based
layout that specifies the distance between one or more of the container’s sides and the child’s
sides, baseline, or center. Absolute positioning is sometimes referred to as absolute layout.
Three containers support absolute positioning:
■ The Application and Panel containers use automatic positioning by default, and absolute
positioning if you specify the layout property as "absolute".
■ The Canvas container always uses absolute positioning.
Controls that General layout: All children of the container are arranged in a single
arrange all children row or column. Each child’s height and width can differ from all other
linearly, such as children’s heights or widths.
Box, HBox, VBox Default sizing: The container fits the default or explicit sizes of all
children and all gaps, borders, and padding.
Percentage based children: If children with percentage-based
sizing request more than the available space, the actual sizes are set to
fit in the space, proportionate to the requested percentages.
Tile General layout: The container is a grid of equal-sized cells. The cells
can be in row-first or column-first order.
If you do not specify explicit or percentage-based dimensions, the
control has as close as possible to an equal number of rows and
columns, with the direction property determining the orientation with
the larger number of items, if necessary.
Default sizing: If you do not specify tileWidth and tileHeight
properties, the container uses the measured or explicit size of the
largest child cell for the size of each child cell.
Percentage based children: The percentage-based sizes of a child
component specify a percentage of the individual cell, not of the Tile
container.
Navigators: General layout: The container displays one child at a time.
ViewStack, Default sizing: The container size is determined by the measured or
Accordion, explicit dimensions of the initially selected child, and thereafter, all
TabNavigator children are forced to be that initial size. If you set the resizeToChild
property to true the container resizes to accommodate the measured
or explicit size of each child, as that child appears.
Percentage based children: As a general rule, you either use 100%
for both height and width, which causes the children to fill the navigator
bounds, or do not use percentage-based sizing.
Sizing components
Flex provides several ways for controlling the size of components. You can do the following:
■ Have Flex automatically determine and use default component sizes.
■ Specify pixel sizes.
■ Specify component size as a percentage of the parent container.
■ Combine layout and sizing by specifying a constraint-based layout.
The following sections describe the basic sizing properties, provide details on how Flex
determines component sizes, describe how to use automatic, explicit, and percentage-based
sizing, and describe various techniques for controlling component size. For information on
constraint-based layout, see “Constraint-based layout” on page 259.
For a summary of the basic rules for component sizing, see “Basic layout rules and
considerations” on page 230.
Setting a component’s includeInLayout property to false does not prevent Flex from
laying out or displaying the component; it only prevents Flex from considering the
component when it lays out other components. As a result, the next component or
components in the display list overlap the component. To prevent Flex from
displaying the component, also set the visible property to false.
Notice the empty space to the right of the third button, because the sum of the default sizes is
less than the available space.
<mx:HBox id="myHBox">
<mx:TextInput id="myInput"
width="200"
height="40"/>
</mx:HBox>
</mx:Application>
In this example, Flex sets the component sizes to 200 by 40 pixels.
The following example shows setting the sizes of a container and its child:
<?xml version="1.0"?>
<!-- components\ExplicitHBoxSize.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
The exact techniques Flex uses to determine the dimensions of a component that uses
percentage-based sizing depend on the type of container that holds the container. For
example, a Tile container has cells that are all the largest default or explicit dimensions of the
largest child. Child control percentage values specify a percentage of the tile cell size, not of
the Tile control size. The percentage sizes of the Box, HBox, and VBox containers, on the
other hand, are relative to the container size.
<mx:Canvas
width="200" height="75"
borderStyle="solid">
<mx:HBox
x="20" y="10"
width="100%" height="25"
backgroundColor="#666666"/>
</mx:Canvas>
<mx:Canvas
width="200" height="75"
borderStyle="solid">
<mx:HBox
left="20" top="10"
width="100%" height="25"
backgroundColor="#666666"/>
</mx:Canvas>
</mx:Application>
Flex draws the following application:
<mx:HBox width="400">
<mx:Button label="Label 1" width="25%"/>
<mx:Button label="Label 2" width="40%"/>
<mx:Button label="Label 3"/>
</mx:HBox>
</mx:Application>
In this example, the default width of the third button is 66 pixels. The HBox container has no
padding by default, but it does put a 8-pixel horizontal gap between each component. Because
this application has three components, these gaps use 16 pixels, so the available space is 384.
The first button requests 25% of the available space, or 96 pixels. The second button requests
40% of 384 pixels, rounded down to 153 pixels. There is still unused space to the right of the
third button.
Flex draws the following application:
Now change the percentage values requested to 50% and 40%, respectively:
<?xml version="1.0"?>
<!-- components\PercentHBoxChildren5040.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:HBox width="400">
<mx:Button label="Label 1"
width="50%"/>
<mx:Button label="Label 2"
width="40%"/>
<mx:Button label="Label 3"/>
</mx:HBox>
</mx:Application>
In this example, the first button requests 50% of the available HBox space, or 192 pixels. The
second button still requests 40%, or 153 pixels, for a total of 345 pixels. However, the HBox
only has 318 pixels free after reserving 66 pixels for the default-width button and 16 pixels for
the gaps between components. Flex divides the available space proportionally between the two
buttons, giving .5/(.5 + .4) * 318 = 176 pixels, to the first button and .4/(.5 + .4) * 318 = 141
pixels, to the second button. (All calculated values are rounded down to the nearest pixel.)
<mx:HBox width="400">
<mx:Button label="Label 1"
width="50%"/>
<mx:Button label="Label 2"
width="40%"
minWidth="150"/>
<mx:Button label="Label 3"/>
</mx:HBox>
</mx:Application>
To determine the widths of the percentage-based button sizes, Flex first determines the sizes as
described in the second example in “Examples: Using percentage-based children of an HBox
container” on page 245, which results in requested values of 176 for the first button and 141
for the second button. However, the minimum width of the second button is 150, so Flex sets
its size to 150 pixels, and reduces the size of the first button to occupy the remaining available
space, which results in a width of 168 pixels.
Flex draws the following application:
For more information on sizing the Application container, see Chapter 16, “Using the
Application Container,” on page 601.
<mx:HBox width="400">
<mx:Button label="Label 1"
width="50%"
minWidth="200"/>
<mx:Button label="Label 2"
width="40%"
minWidth="150"/>
<mx:Button label="Label 3"/>
</mx:HBox>
</mx:Application>
In this example, the default width of the fixed-size button is 66 pixels, so there are 324 pixels
of space available for the percentage-based buttons after accounting for the gap between
components. The minimum widths of the first and second buttons are greater than the
percentage-based values, so Flex assigns those buttons the set widths of 200 and 150 pixels,
even though the HBox container only had 324 pixels free. The HBox container uses scroll
bars to provide access to its contents because they now consume more space than the
container itself.
<mx:HBox id="myHBox"
width="150"
height="150"
borderStyle="solid"
backgroundColor="#996666"
clipContent="false">
<mx:TextInput id="myInput"
width="200" height="40"
backgroundColor="#99FF99"/>
</mx:HBox>
</mx:Application>
The following image shows the application, with the TextInput control extending past the
right edge of the HBox control:
To ensure that components fit in the container, reduce the sizes of the child components. You
can do this by setting explicit sizes that fit in the container, or by specifying percentage-based
sizes. If you set percentage-based sizes, Flex shrinks the children to fit the space, or their
minimum sizes, whichever is larger. By default, Flex sets the minimum height and width of
most components to 0. You can set these components’ minimum properties to nonzero values
to ensure that they remain readable.
<mx:HBox
width="400"
borderStyle="solid"
paddingLeft="5"
paddingRight="5"
horizontalGap="5">
<mx:HBox width="400">
<mx:Image source="assets/flexlogo.jpg"/>
<mx:Label text="Company XYZ"/>
<mx:Spacer width="100%"/>
<mx:Button label="Close"/>
</mx:HBox>
</mx:Application>
In this example, the Spacer control is the only percentage-based component in the HBox
container. Flex sizes the Spacer control to occupy all available space in the HBox container
that is not required for other components. By expanding the Spacer control, Flex pushes the
Button control to the right edge of the container.
You can use all sizing and positioning properties with the Spacer control, such as width,
height, maxWidth , maxHeight, minWidth, and minHeight.
You can prevent Flex from performing automatic positioning updates that conflict with the
requested action of your application by setting the autoLayout property of a container to
false. Setting this property to false prevents Flex from laying out the container’s contents
when a child moves or resizes. Flex defines the autoLayout property in the Container class,
and all containers inherit it; its default value is true, which enables Flex to update layouts.
<mx:VBox autoLayout="false"
width="200"
height="200">
<mx:Button/>
<mx:Button id="btn"
click="btn.x += 10;"/>
<mx:Button id="btn2"
creationComplete="btn2.x = 100; btn2.y = 75;"/>
</mx:VBox>
</mx:Application>
In this example, Flex initially lays out all three Button controls according to the rules of the
VBox container. The creationComplete event listener for the third button is dispatched after
the VBox control has laid out its children, but before Flex displays the buttons. Therefore,
when the third button appears, it is at the x and y positions specified by the creationComplete
listener. After the buttons appear, Flex shifts the second button 10 pixels to the right each
time a user clicks it.
Setting the autoLayout property of a container to false prohibits Flex from updating a
container’s layout after a child moves or resizes, so you should set it to false only when
absolutely necessary. You should always test your application with the autoLayout property
set to the default value of true, and set it to false only as necessary for the specific container
and specific actions of the children in that container.
For more information on effects, see Chapter 19, “Using Behaviors,” on page 719.
<mx:VBox>
<mx:Panel id="p1"
title="Panel 1"
backgroundColor="#FF0000"/>
<mx:Panel id="p2"
title="Panel 2"
backgroundColor="#00FF00"/>
<mx:Panel id="p3"
title="Panel 3"
backgroundColor="#0000FF"/>
</mx:VBox>
<mx:HBox>
<mx:Button label="Toggle Panel 2 Visible"
click="{p2.visible=!p2.visible;}"/>
<mx:Button label="Toggle Panel 2 in Layout"
click="{p2.includeInLayout=!p2.includeInLayout;}"/>
</mx:HBox>
</mx:Application>
Run this application and click the buttons to see the results of different combinations of
visible and includeInLayout properties. The example shows the following behaviors:
■ If you include the second Panel control in the layout and make it invisible, Flex reserves
space for it; you see the background of its VBox container in its place.
■ If you do not include the second Panel control in the layout, the VBox resizes and the
HBox with the buttons moves up. If you then include it in the layout, the VBox resizes
again, and the HBox and buttons move down.
■ If you do not include the second Panel control in the layout and make it visible, Flex still
draws it, but does not consider it in laying out the third Panel control, so the two panels
overlap. Because the title of a Panel control has a default alpha of 0.5, you see the
combination of the second and third Panel controls in the second Panel position.
<mx:Canvas
width="100" height="100"
backgroundColor="#999999">
<mx:VBox id="b1"
width="80" height="80"
x="20" y="20"
backgroundColor="#A9C0E7">
</mx:VBox>
</mx:Canvas>
</mx:Application>
This example produces the following image:
<mx:Canvas
width="100" height="100"
backgroundColor="#999999">
<mx:VBox id="b1"
width="80" height="80"
x="20" y="20"
backgroundColor="#A9C0E7">
</mx:VBox>
<mx:VBox id="b2"
width="50" height="50"
x="0" y="50"
backgroundColor="#FF0000">
</mx:VBox>
</mx:Canvas>
</mx:Application>
This example produces the following image:
NOTE
If you use percentage-based sizing for the children of a control that uses absolute
positioning, be aware that percentage-based components resize when the parent
container resizes, and the result may include unwanted overlapping of controls.
For an introduction to using constraint-based layout in Flex Builder, see Getting Started
with Flex.
You can use constraint-based layout to determine the position and size of the immediate
children of any container that supports absolute positioning.
With constraint-based layout you can do the following:
■ Anchor one or more edges of a component at a pixel offset from the corresponding edge of
its container’s viewable region. The anchored child edge stays at the same distance from
the parent edge when the container resizes. If you anchor both edges in a dimension, such
as top and bottom, the component resizes if the container resizes.
■ Anchor the child’s horizontal or vertical center (or both) at a pixel offset from the center of
the container’s viewable region. The child does not resize in the specified dimension unless
you also use percentage-based sizing.
■ Anchor the baseline of a component at a pixel offset from the top edge of its parent
container.
The layout="absolute" attribute is the default for the Canvas component. For
Application and Panel containers, you must specify layout="absolute" explicitly.
<!-- Anchor the top of the form at the top of the canvas.
Anchor the form sides 20 pixels from the canvas sides. -->
<mx:Form id="myForm"
backgroundColor="#DDDDDD"
top="0"
left="20"
right="20">
<mx:FormItem label="Date">
<mx:DateField/>
</mx:FormItem>
<mx:FormItem width="100%"
direction="horizontal"
label="Hours:">
<mx:TextInput width="75"/>
<mx:Label text="Minutes" width="48"/>
<mx:TextInput width="75"/>
</mx:FormItem>
</mx:Form>
<!-- Anchor the box with the buttons 20 pixels from the canvas
right edge and 10 pixels from the bottom. -->
<mx:HBox id="okCancelBox"
right="20"
bottom="10">
<mx:Button label="OK"/>
<mx:Button label="Cancel"/>
</mx:HBox>
</mx:Canvas>
</mx:Application>
<mx:Canvas>
<mx:constraintColumns>
<mx:ConstraintColumn id="col1" width="20%"/>
</mx:constraintColumns>
</mx:Canvas>
■ Fixed size means the space allocated to the constraint region is a fixed pixel size.
■ Content size means that the space allocated to the region is dictated by the size of the child
objects in that space. As the size of the content changes, so does the size of the region.
N OTE
Content sizing is the default when you do not specify either fixed or percentage
sizing parameters.
■ Percent size means that the space allocated to the constraint region is calculated as a
percentage of the space remaining in the parent container after the space allocated to fixed
and content size child objects has been deducted from the available space.
Best practice in specifying percent constraints is to ensure that the sum of all percent
constraints is less than or equal to 100%. However, if the total value of percent
specifications is greater than 100%, the actual allocated percentages are calculated so that
the proportional values for all constraints total 100%. For example, if the percentages for
two constraint objects are specified as 100% and 50%, the values are adjusted to 66.6%
and 33.3% (two-thirds for the first value and one-third for the second).
If constraint parameters (left, right, top, and bottom) are NOT qualified by a constraint
region identifier (ConstraintRow ID or ConstraintColumn ID), the component is
constrained relative to the edges of its parent container. Components can occupy a single
constraint region (row or column) or can span mulitple regions.
While you may specify any combination of qualified and unqualified constraints, some
constraint properties may be overridden; for example, if you specify constraints that cannot be
rendered, such as left and right constraints that overlap. In all cases, the priority of sizing and
positioning are as follows:
Minimum and maximum sizes for constraint columns and rows (minWidth, maxWidth,
minHeight, and maxHeight) limit how much the constraint regions grow or shrink when you
resize their parent containers. If the parent container with a constraint region shrinks to less
than the minimum size for that region when you resize the container, scrollbars appear to
show clipped content.
N OTE
Minimum and maximum limits are only applicable to percentage and content sized
constraint regions. For fixed size constraint regions, minimum and maximum values,
if specified, are ignored.
CHAPTER 10
Using Controls 10
Controls are user-interface components such as Button, TextArea, and ComboBox controls.
This topic describes how to use controls in a Flex application.
Adobe Flex has two types of controls: basic and data provider. This topic contains an overview
of all Flex controls, and describes the basic Flex controls. For information on data provider
controls, see Chapter 13, “Using Data-Driven Controls,” on page 447.
Contents
About controls. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .268
Working with controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
Button control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
PopUpButton control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
ButtonBar and ToggleButtonBar controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .284
LinkBar control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .288
TabBar control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
CheckBox control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
RadioButton control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .296
NumericStepper control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
DateChooser and DateField controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304
LinkButton control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
HSlider and VSlider controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
SWFLoader control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .328
Image control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .334
VideoDisplay control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
ColorPicker control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
Alert control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
ProgressBar control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .365
HRule and VRule controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .370
ScrollBar control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
267
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
About controls
Controls are user-interface components, such as Button, TextArea, and ComboBox controls.
You place controls in containers, which are user-interface components that provide a
hierarchical structure for controls and other containers. Typically, you define a container, and
then insert controls or other containers in it.
At the root of a Flex application is the <mx:Application> tag, which represents a base
container that covers the entire Flash Player drawing surface. You can place controls or
containers directly under the <mx:Application> tag or in other containers. For more
information on containers, see Chapter 15, “Introducing Containers,” on page 563.
Most controls have the following characteristics:
■ MXML API for declaring the control and the values of its properties and events
■ ActionScript API for calling the control’s methods and setting its properties at run time
■ Customizable appearance using styles, skins, and fonts
The following image shows several controls used in a Form container:
Form container
TextInput controls
ComboBox control
Button control
Although you commonly use MXML as the language for building Flex applications, you can
also use ActionScript to configure controls. For example, the following code example
populates a DataGrid control by providing an Array of items as the value of the DataGrid
control’s dataProvider property:
<?xml version="1.0"?>
<!-- controls\DataGridConfigAS.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
<mx:DataGrid id="myGrid"
width="350" height="150"
color="#7B0974"
creationComplete="myGrid_initialize();"/>
</mx:Application>
RichTextEditor Compound control that contains a multiline text field and controls that let a
user format text by selecting such characteristics as font, size, weight,
alignment, and so on
These controls can display plain text that all has the same appearance. The controls can also
display rich text formatted by using a subset of the standard HTML formatting tags. For
information on using text controls, see Chapter 11, “Using Text Controls,” on page 377.
Control Description
Menu A visual menu that can have cascading submenus
MenuBar A horizontal bar with multiple submenus
For information on menu controls, see Chapter 12, “Using Menu-Based Controls,” on
page 415
Flex controls
The following table lists all the controls available with Flex:
Button Displays a variable-size button that can “Button control” on page 277
include a label, an icon image, or both.
DateField Displays the date with a calendar icon “DateChooser and DateField
on its right side. When a user clicks controls” on page 304
anywhere inside the control, a
DateChooser control pops up and
displays a month of dates.
HorizontalList Displays a horizontal list of items. “HorizontalList control”
on page 458
Image Imports GIF, JPEG, PNG, SVG, and “Image control” on page 334
SWF files.
MenuBar Displays a horizontal menu bar that “MenuBar control” on page 439
contains one or more submenus of
Menu controls.
ScrollBar Displays horizontal and vertical scroll “ScrollBar control” on page 374
(HScrollBar and bars.
VScrollBar)
SWFLoader Displays the contents of a specified “SWFLoader control”
SWF file or JPEG file. on page 328
TextArea Displays an editable text field for user “Using Text Controls”
input that can accept more than a on page 377
single line of input.
TextInput Displays an editable text field for a “TextInput control” on page 401
single line of user input. Can contain
alphanumeric data, but input is
interpreted as a String data type.
TileList Displays a tiled list of items. The items “TileList control” on page 462
are tiled in vertical columns or
horizontal rows.
Sprite
UIComponent
Controls
The Sprite and UIComponent classes are the base classes for all Flex components. Subclasses
of the UIComponent class can have shape, draw themselves, and be invisible. Each subclass
can participate in tabbing, accept low-level events like keyboard and mouse input, and be
disabled so that it does not receive mouse and keyboard input.
For information on the interfaces inherited by controls from the Sprite and UIComponent
classes, see Chapter 7, “Using Flex Visual Components,” on page 143.
Sizing controls
This section briefly describes how Flex sizes controls. For more information on sizing
components, see Chapter 9, “Sizing and Positioning Components,” on page 225.
All controls define rules for determining their size in a Flex application. For example, a Button
control sizes itself to fit its label text and optional icon image, while an Image control sizes
itself to the size of the imported image. Each control has a default height and a default width.
The default size of each standard control is specified in the description of each control.
You can also specify explicit sizes for a control. In MXML or ActionScript by setting the its
height and width properties to numeric pixel values. The following example sets the height
and width of the addr2 TextInput control to 20 pixels and 100 pixels, respectively:
<mx:TextInput id="addr2" width="100" height ="20"/>
To resize a control at run time, use ActionScript to set its width and height properties. For
example, the click event listener for the following Button control sets the width property of
the addr2 TextInput control to increase its width by 10 pixels:
<mx:Button id="button1" label="Slide" height="20"
click="addr2.width+=10;"/>
N OTE
The preceding technique works even if the width property was originally set as a
percentage value. The stored values of the width and height properties are always in
pixels.
Many components have arbitrarily large maximum sizes, which means that Flex can make
them as large as necessary to fit the requirements of your application. While some
components have a defined nonzero minimum size, most have a minimum size of 0. You can
use the maxHeight, maxWidth, minHeight, and minWidth properties to set explicit size ranges
for each component.
Positioning controls
You place controls inside containers. Most containers have predefined layout rules that
automatically determine the position of their children. The Canvas container absolutely
positions its children, and the Application, and Panel containers optionally let you use
absolute or container-relative positioning.
To reposition a control within an absolutely-positioned container at run time, you set its x
and y properties. For example, the click event listener for the following Button control
moves the TextInput control down 10 pixels from its current position:
<mx:Button id="button1" label="Slide" height="20" x="0" y="250"
click="addr2.y = addr2.y+10;"/>
A theme defines the look and feel of a Flex application. A theme can define something as
simple as the color scheme or common font for an application, or it can be a complete
reskinning of all the Flex components. The current theme for your application defines the
styles that you can set on the controls within it. That means some style properties might not
always be settable. For more information, see Chapter 20, “Using Styles and Themes,” on
page 767.
You can use customized graphic skins to customize your buttons to match your application’s
look and functionality. You can give the Button control different image skins for the up,
down, and disabled states, and the skins for these states can differ depending on whether the
button is selected or not selected. The control can change the image skins dynamically.
The following example shows seven Button controls to control video recording and playback
arranged in an HBox layout container. All buttons are in their up state.
Minimum size 0
<mx:Button
label="Icon Button"
icon="@Embed(source='assets/logo.jpg')"/>
</mx:Application>
The icon is in the assets subdirectory of the directory containing the application file. This
results in a button with the icon displayed to the left of the label text:
For an overview of resource embedding, see Chapter 32, “Embedding Assets,” on page 1237.
Text that is vertically larger than the Button control is also clipped. If you explicitly size a
Button control so that it is not large enough to accommodate its icon, icons larger than the
Button control extend outside the Button control’s bounding box.
PopUpButton control
The PopUpButton control consists of two horizontal buttons: a main button, and a smaller
button called the pop-up button, which only has an icon. The main button is a Button
control.
The pop-up button, when clicked, opens a second control called the pop-up control. Clicking
anywhere outside the PopUpButton control, or in the pop-up control, closes the pop-up
control
The PopUpButton control adds a flexible pop-up control interface to a Button control. One
common use for the PopUpButton control is to have the pop-up button open a List control or
a Menu control that changes the function and label of the main button, as the following
example shows using a Menu control:
PopUpButton control
Minimum size 0
<mx:Script>
<![CDATA[
import mx.controls.*;
import mx.events.*;
// Define the event listener for the Menu control's change event.
private function changeHandler(event:MenuEvent):void {
var label:String = event.label;
popTypeB.text=String("Moved to " + label);
popB.label = "Put in: " + label;
popB.close();
}
]]>
</mx:Script>
<mx:VBox>
<mx:Spacer height="50"/>
<mx:TextInput id="popTypeB"/>
</mx:VBox>
</mx:Application>
User interaction
You navigate the PopUpButton control using the mouse as follows:
■ Moving the mouse over any part of the PopUpButton control highlights the button
border and the main button or the pop-up button.
■ Clicking the button dispatches the click event.
■ Clicking the pop-up button pops up the pop-up control and dispatches an open event.
■ Clicking anywhere outside the PopUpButton control, or in the pop-up control, closes the
pop-up control and dispatches a close event.
The following keystrokes let users navigate the PopUpButton control:
Key Use
Spacebar Behaves like clicking the main button.
Control+Down Arrow Opens the pop-up control and initiates an open event. The pop-up
control’s keyboard handling takes effect.
Control+Up Arrow Closes the pop-up control and initiates a close event.
NO TE
You cannot use the Tab key to leave an opened pop-up control; you must make a
selection or close the control with the Control+Up Arrow key combination.
The following image shows an example of a ToggleButtonBar control that defines a set of
buttons, where the Dreamweaver button is the currently selected button in the control:
Control resizing The controls do not resize by default. Specify percentage sizes if you want
rules your ButtonBar to resize based on the size of its parent container.
Padding 0 pixels for the top, bottom, left, and right properties.
You use the dataProvider property to specify the labels of the four buttons. You can also
populate the dataProvider property with an Array of Objects; where each object can have
up to three fields: label, icon, and toolTip.
In the following example, you use an Array of Objects to specify a label and icon for each
button:
<?xml version="1.0"?>
<!-- controls\bar\BBarLogo.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.events.ItemClickEvent;
<mx:ButtonBar
borderStyle="solid"
horizontalGap="5"
itemClick="clickHandler(event);">
<mx:dataProvider>
<mx:String>Flash</mx:String>
<mx:String>Director</mx:String>
<mx:String>Dreamweaver</mx:String>
<mx:String>ColdFusion</mx:String>
</mx:dataProvider>
</mx:ButtonBar>
</mx:Application>
In this example, the event listener displays the index and label of the selected button in a
TextArea control in response to a itemClick event.
LinkBar control
A LinkBar control defines a horizontal or vertical row of LinkButton controls that designate a
series of link destinations. You typically use a LinkBar control to control the active child
container of a ViewStack container, or to create a standalone set of links.
The following shows an example of a LinkBar control that defines a set of links:
Control resizing LinkBar controls do not resize by default. Specify percentage sizes if you
rules want your LinkBar to resize based on the size of its parent container.
Padding 2 pixels for the top, bottom, left, and right properties.
<mx:LinkBar borderStyle="solid"
itemClick="navigateToURL(new URLRequest('http://www.adobe.com/' +
String(event.label).toLowerCase()), '_blank');">
<mx:dataProvider>
<mx:String>Flash</mx:String>
<mx:String>Director</mx:String>
<mx:String>Dreamweaver</mx:String>
<mx:String>ColdFusion</mx:String>
</mx:dataProvider>
</mx:LinkBar>
</mx:Application>
In this example, you use the <mx:dataProvider> and <mx:Array> tags to define the label
text. The event object passed to the itemClick handler contains the label selected by the user.
The handler for the itemClick event constructs an HTTP request to the Adobe website
based on the label, and opens that page in a new browser window.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var linkData:ArrayCollection = new ArrayCollection([
"Flash", "Director", "Dreamweaver", "ColdFusion"
]);
]]>
</mx:Script>
<mx:LinkBar
horizontalAlign="right"
borderStyle="solid"
itemClick="navigateToURL(new URLRequest('http://www.adobe.com/' +
String(event.label).toLowerCase()), '_blank');">
<mx:dataProvider>
{linkData}
</mx:dataProvider>
</mx:LinkBar>
</mx:Application>
In this example, you define the data for the LinkBar control as a variable in ActionScript, and
then you bind that variable to the <mx:dataProvider> tag. You could also bind to the
<mx:dataProvider> tag from a Flex data model, from a web service response, or from any
other type of data model.
A LinkBar control creates LinkButton controls based on the value of its dataProvider
property. Even though LinkBar is a subclass of Container, do not use methods such as
Container.addChild() and Container.removeChild() to add or remove LinkButton
controls. Instead, use methods such as addItem() and removeItem() to manipulate the
dataProvider property. A LinkBar control automatically adds or removes the necessary
children based on changes to the dataProvider property.
As with the LinkBar control, you can use a TabBar control to control the active child
container of a ViewStack container. The syntax for using a TabBar control to control the
active child of a ViewStack container is the same as for a LinkBar control. For an example, see
“ViewStack navigator container” on page 700.
While a TabBar control is similar to a TabNavigator container, it does not have any children.
For example, you use the tabs of a TabNavigator container to select its visible child container.
You can use a TabBar control to set the visible contents of a single container to make that
container’s children visible or invisible based on the selected tab.
A TabBar control has the following default properties:
<mx:TabBar>
<mx:dataProvider>
<mx:String>Alabama</mx:String>
<mx:String>Alaska</mx:String>
<mx:String>Arkansas</mx:String>
</mx:dataProvider>
</mx:TabBar>
</mx:Application>
The <mx:String> tags define the text for each tab in the TabBar control.
You can also use the <mx:Object> tag to define the entries as an array of objects, where each
object contains a label property and an associated data value, as the following example
shows:
<?xml version="1.0"?>
<!-- controls\bar\TBarObject.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:TabBar>
<mx:dataProvider>
<mx:Object label="Alabama" data="Montgomery"/>
<mx:Object label="Alaska" data="Juneau"/>
<mx:Object label="Arkansas" data="Little Rock"/>
</mx:dataProvider>
</mx:TabBar>
</mx:Application>
The label property contains the state name and the data property contains the name of its
capital. The data property lets you associate a data value with the text label. For example, the
label text could be the name of a color, and the associated data value could be the numeric
representation of that color.
<mx:TabBar labelField="state">
<mx:dataProvider>
<mx:Object state="Alabama" data="Montgomery"/>
<mx:Object state="Alaska" data="Juneau"/>
<mx:Object state="Arkansas" data="Little Rock"/>
</mx:dataProvider>
</mx:TabBar>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var STATE_ARRAY:ArrayCollection = new ArrayCollection([
{label:"Alabama", data:"Montgomery"},
{label:"Alaska", data:"Juneau"},
{label:"Arkansas", data:"LittleRock"}
]);
]]>
</mx:Script>
<mx:TabBar >
<mx:dataProvider>
{STATE_ARRAY}
</mx:dataProvider>
</mx:TabBar>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.events.ItemClickEvent;
import mx.controls.TabBar;
import mx.collections.ArrayCollection;
[Bindable]
private var STATE_ARRAY:ArrayCollection = new ArrayCollection([
{label:"Alabama", data:"Montgomery"},
{label:"Alaska", data:"Juneau"},
{label:"Arkansas", data:"LittleRock"}
]);
CheckBox control
The CheckBox control is a commonly used graphical control that can contain a check mark
or be unchecked (empty). You can use CheckBox controls wherever you need to gather a set of
true or false values that aren’t mutually exclusive.
You can add a text label to a CheckBox control and place it to the left, right, top, or bottom of
the check box. Flex clips the label of a CheckBox control to fit the boundaries of the control.
The following image shows a checked CheckBox control:
For the code used to generate this example, see “Creating a CheckBox control” on page 296.
When a user clicks a CheckBox control or its associated text, the CheckBox control changes
its state from checked to unchecked, or from unchecked to checked.
A CheckBox control can have one of two disabled states, checked or unchecked. By default, a
disabled CheckBox control displays a different background and check mark color than an
enabled CheckBox control.
The CheckBox control has the following default properties:
Minimum size 0
RadioButton control
The RadioButton control is a single choice in a set of mutually exclusive choices. A
RadioButton group is composed of two or more RadioButton controls with the same group
name. Only one member of the group can be selected at any given time. Selecting an
unselected group member deselects the currently selected RadioButton control in the group.
For the code used to generate this example, see “Creating a RadioButton control”
on page 297.
The RadioButton control has the following default properties:
Minimum size 0
Maximum size Undefined
<mx:RadioButton groupName="cardtype"
id="americanExpress"
label="American Express"
width="150"/>
<mx:RadioButton groupName="cardtype"
id="masterCard"
label="MasterCard"
width="150"/>
<mx:RadioButton groupName="cardtype"
id="visa"
label="Visa"
width="150"/>
</mx:Application>
This code results in the application shown in “About the RadioButton control” on page 297.
<mx:Script>
<![CDATA[
import flash.events.Event;
<mx:RadioButton groupName="cardtype"
id="americanExpress"
label="American Express"
width="150"
click="handleAmEx(event);"/>
<mx:RadioButton groupName="cardtype"
id="masterCard"
label="MasterCard"
width="150"
click="handleMC(event);"/>
<mx:RadioButton groupName="cardtype"
id="visa"
label="Visa"
width="150"
click="handleVisa(event);"/>
<mx:TextArea id="myTA"/>
</mx:Application>
Key Action
Control+Arrow keys Move focus among the buttons without selecting a button.
<mx:Script>
<![CDATA[
import mx.events.ItemClickEvent;
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.ItemClickEvent;
NumericStepper control
You can use the NumericStepper control to select a number from an ordered set. The
NumericStepper control consists of a single-line input text field and a pair of arrow buttons
for stepping through the valid values; you can also use the Up Arrow and Down Arrow keys to
cycle through the values.
The following example shows a NumericStepper control:
For the code used to create this image, see “Creating a NumericStepper control” on page 303.
If the user clicks the up arrow, the value displayed is increased by one unit of change. If the
user holds down the arrow, the value increases or decreases until the user releases the mouse
button. When the user clicks the arrow, it is highlighted to provide feedback to the user.
Users can also type a legal value directly into the text field. Although editable ComboBox
controls provide similar functionality, NumericStepper controls are sometimes preferred
because they do not require a drop-down list that can obscure important data.
NumericStepper control arrows always appear to the right of the text field.
User interaction
If the user clicks the up or down arrow button, the value displayed is increased by one unit of
change. If the user presses either of the arrow buttons for more than 200 milliseconds, the
value in the input field increases or decreases, based on step size, until the user releases the
mouse button or the maximum or minimum value is reached.
Keyboard navigation
The NumericStepper control has the following keyboard navigation features:
Key Description
Down Arrow Value decreases by one unit.
Right Arrow Moves the insertion point to the right within the Numeric Stepper control’s
text field.
In order to use the keyboard to navigate through the stepper, it must have focus.
Changing the displayed month does not change the selected date. Therefore, the currently
selected date might not always be visible. The DateChooser control resizes as necessary to
accommodate the width of the weekday headings. Therefore, if you use day names, instead of
letters, as headings, the calendar will be wide enough to show the full day names.
Minimum size 0
You can use the DateField control anywhere you want a user to select a date. For example, you
can use a DateField control in a hotel reservation system, with certain dates selectable and
others disabled. You can also use the DateField control in an application that displays current
events, such as performances or meetings, when a user selects a date.
Minimum size 0
<mx:Script>
<![CDATA[
import mx.events.CalendarLayoutChangeEvent;
<mx:Form>
<mx:FormItem label="Day">
<mx:TextInput id="day" width="100"/>
</mx:FormItem>
<mx:FormItem label="Day of month">
<mx:TextInput id="date" width="100"/>
</mx:FormItem>
<mx:FormItem label="Month">
<mx:TextInput id="month" width="100"/>
</mx:FormItem>
<mx:FormItem label="Year">
<mx:TextInput id="year" width="100"/>
</mx:FormItem>
<mx:FormItem label="Date">
<mx:TextInput id="wholeDate" width="300"/>
</mx:FormItem>
</mx:Form>
</mx:Application>
Notice that the first line of the event listener determines if the selectedDate property is null.
This check is necessary because selecting the currently selected date deselects it, sets the
selectedDate property to null, then dispatches the change event.
N OTE
The code that determines the value of the wholeDate field adds 1 to the month number
because the DateChooser control uses a zero-based month system, where January is
month 0 and December is month 11.
The following example uses inline ActionScript to set the initial selected date for a DateField
control:
<mx:DateField id="date3" selectedDate="{new Date (2005, 9, 10)}"/>
You can also set the selectedDate property in a function, as the following example shows:
<mx:Script>
<![CDATA[
private function initDC():void {
date2.selectedDate=new Date (2003, 3, 10);
}
]]>
</mx:Script>
You can use property notation to access the ActionScript setter and getter methods of the
selectedDate property Date object. For example, the following line displays the four-digit
year of the selected date in a text box.
<mx:TextInput text="{date1.selectedDate.fullYear}"/>
These properties let you specify styles for the text in the header, week day list and today’s date.
You cannot use these properties to set non-text styles such as todayColor.
<mx:Style>
.myHeaderStyle{
color:#6666CC;
font-family:Times New Roman, Times, serif;
font-size:16px; font-weight:bold;}
.myTodayStyle{
color:#CC6633;
font-family:Times New Roman, Times, serif;
font-size:12px; font-weight:bold;}
.myDayStyle{
color:#006600;
font-family:Courier New, Courier, mono;
font-size:15px; font-style:italic; font-weight:bold;}
</mx:Style>
<mx:DateChooser
headerStyleName="myHeaderStyle"
todayStyleName="myTodayStyle"
todayColor="#CCCCCC"
weekDayStyleName="myDayStyle"/>
</mx:Application>
Property Description
disabledDays An array of days of the week that the user cannot select. Often used to
disable weekend days.
disabledRange An array of dates that the user cannot select. The array can contain
individual Date objects, objects specifying date ranges, or both.
selectableRange A single range of dates that the user can select. The user can navigate only
among the months that include this range; in these months any dates
outside the range are disabled. Use the disabledRange property to disable
dates within the selectable range.
<mx:DateChooser
selectableRange="{{rangeStart: new Date(2006,0,1),
rangeEnd: new Date(2006,2,15)}}"
disabledRanges="{[new Date(2006,0,11),
{rangeStart: new Date(2006,0,23), rangeEnd: new Date(2006,1,10)}]}"
disabledDays="{[0,6]}"/>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.events.DateChooserEvent;
<mx:DateChooser id="myDC"
width="200"
creationComplete="dateChooser_init();"
scroll="onScroll();"/>
</mx:Application>
To set the selectableRange property, the code creates two Date objects that represent the
first date and last date of the range. Users can only select dates within the specified range. This
example also changes the fontStyle of the DateChooser control to italics after the first
time the user scrolls it.
You can select multiple dates in a DateChooser control by using the selectedRanges property.
This property contains an Array of objects. Each object in the Array contains two dates: a start
date and an end date. By setting the dates within each object to the same date, you can select
any number of individual dates in the DateChooser.
The following example uses an XML object to define the date for the DateChooser control. It
then iterates over the XML object and creates a new object for each date. These objects are
then used to determine what dates to select in the DateChooser.
<mx:DateChooser id="dc1"
showToday="false"
creationComplete="displayDates()"
/>
</mx:Application>
<mx:Label text="{date2.formatString}"/>
<mx:DateField id="date2"
editable="true"
width="100"
formatString="MM/DD/YY"/>
</mx:Application>
The DateField control also lets you specify a formatter function that converts the date to a
string in your preferred format for display in the control’s text field. The DateField
labelFunction property and the DateFormatter class help you format dates.
By default, the date in the DateField control text field is formatted in the form "MM/DD/
YYYY". You use the labelFunction property of the DateField control to specify a function
to format the date displayed in the text field, and return a String containing the date. The
function has the following signature:
public function formatDate(currentDate:Date):String {
...
return dateString;
}
<mx:Script>
<![CDATA[
private function formatDate(date:Date):String {
return dfconv.format(date);
}
]]>
</mx:Script>
Where the valueString argument contains the text string entered by the user in the text
field, and the inputFormat argument contains the format of the string. For example, if you
only allow the user to enter a text sting using two characters for month, day, and year, then
pass "MM/DD/YY" to the inputFormat argument.
User interaction
The date chooser includes arrow buttons that let users move between months. Users can select
a date with the mouse by clicking the desired date.
Key Use
Left Arrow Moves the selected date to the previous enabled day in the month.
Does not move to the previous month.
Right Arrow Moves the selected date to the next enabled day in the month. Does
not move to the next month.
Up Arrow Moves the selected date up the current day of week column to the
previous enabled day. Does not move to the previous month.
Down Arrow Moves the selected date down the current day of week column to
next enabled day. Does not move to the next month.
Home Moves the selection to the first enabled day of the month.
End Moves the selection to the last enabled day of the month.
The user must select the control before using navigation keystrokes. In a DateField
control, all listed keystrokes work only when the date chooser is displayed.
LinkButton control
The LinkButton control creates a single-line hypertext link that supports an optional icon.
You can use a LinkButton control to open a URL in a web browser.
Minimum size 0
<mx:LinkButton label="ADBE"
width="100"
click="navigateToURL(new URLRequest('http://quote.yahoo.com/
q?s=ADBE'), 'quote')"/>
</mx:Application>
This example uses the navigateToURL() method to open the URL.
The LinkButton control automatically provides visual cues when you move your mouse
pointer over or click the control. The previous code example contains no link handling logic
but does change color when you move your mouse pointer over or click a link:
<mx:VBox>
<!-- Put the links in an HBox container across the top. -->
<mx:HBox>
<mx:LinkButton label="Link1"
click="viewStack.selectedIndex=0;"/>
<mx:LinkButton label="Link2"
click="viewStack.selectedIndex=1;"/>
<mx:LinkButton label="Link3"
click="viewStack.selectedIndex=2;"/>
</mx:HBox>
Label
Tick mark
Thumb
HSlider control
with data tip
VSlider control
This example includes the data tip, slider thumb, track, tick marks, and labels. You can
optionally show or hide data tips, tick marks, and labels.
The following code example reproduces this image (without annotations):
<?xml version="1.0"?>
<!-- controls\slider\HSliderSimple.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:HBox>
<mx:VBox>
<mx:HSlider
tickInterval="2"
labels="['min', 'max']" height="150"/>
<mx:HSlider/>
</mx:VBox>
<mx:VSlider
tickInterval="2"
labels="['min', 'max']"/>
</mx:HBox>
</mx:Application>
Maximum None
size
<mx:VBox>
<mx:HSlider
maximum="100"/>
<mx:HSlider
maximum="100"
snapInterval="5"/>
<mx:HSlider
maximum="100"
snapInterval="5"
tickInterval="25"/>
<mx:HSlider
maximum="100"
snapInterval="5"
tickInterval="25"
labels="[0,25,50,75,100]"/>
</mx:VBox>
</mx:Application>
This example produces the following image:
<mx:HBox>
<mx:VSlider
maximum="100"/>
<mx:VSlider
maximum="100"
snapInterval="5"/>
<mx:VSlider
maximum="100"
snapInterval="5"
tickInterval="25"/>
<mx:VSlider
maximum="100"
snapInterval="5"
tickInterval="25"
labels="[0,25,50,75,100]"/>
</mx:HBox>
</mx:Application>
This code results in the following application:
You can bind the value property of a slider to another control to display the current value of
the slider. The following example binds the value property to a Text control:
<?xml version="1.0"?>
<!-- controls\slider\HSliderBinding.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
Event Description
change Dispatches when the user moves the thumb. If the liveDragging property is
true, the event is dispatched continuously as the user moves the thumb. If
liveDragging is false, the event is dispatched when the user releases the
slider thumb.
thumbDrag Dispatches when the user moves a thumb.
thumbPress Dispatches when the user selects a thumb using the mouse pointer.
thumbRelease Dispatches when the user releases the mouse pointer after a thumbPress
event occurs.
<mx:Script>
<![CDATA[
import mx.events.SliderEvent;
import mx.controls.sliderClasses.Slider;
<mx:HSlider change="sliderChange(event);"/>
<mx:TextArea id="thumb"/>
</mx:Application>
By default, the liveDragging property of the slider control is set to false, which means that
the control dispatches the change event when the user releases the slider thumb. If you set
liveDragging to true, the control dispatches the change event continuously as the user
moves the thumb, as the following example shows:
<?xml version="1.0"?>
<!-- controls\slider\HSliderEventLiveDrag.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.events.SliderEvent;
import mx.controls.sliderClasses.Slider;
<mx:HSlider
liveDragging="true"
change="sliderChangeLive(event);"/>
<mx:TextArea id="thumbLive"/>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.events.SliderEvent;
import mx.controls.sliderClasses.Slider;
<mx:HSlider thumbCount="2"
change="sliderChangeTwo(event);"/>
<mx:TextArea id="thumbTwoA"/>
<mx:TextArea id="thumbTwoB"/>
<mx:TextArea id="thumbIndex"/>
</mx:Application>
This example also uses the thumbIndex property of the event object. This property has a value
of 0 if the user modified the position of the first thumb, and a value of 1 if the user modified
the position of the second thumb.
<mx:Script>
<![CDATA[
private function myDataTipFunc(val:String):String {
return "Current value: " + String(val);
}
]]>
</mx:Script>
<mx:HSlider
height="80"
dataTipFormatFunction="myDataTipFunc"/>
</mx:Application>
This code produces the following image:
In this example, the data tip function prepends the data tip text with the String
"Current value: ". You can modify this example to insert a dollar sign ($) prefix on the data tip
for a slider that controls the price of an item.
Keyboard navigation
The HSlider and VSlider controls have the following keyboard navigation features when the
slider control has focus:
Key Description
Left Arrow Decrement the value of an HSlider control by 1 snap interval or, if you do not
specify a snap interval, by 1 pixel.
Right Arrow Increment the value of a HSlider control by 1 snap interval or, if you do not
specify a snap interval, by 1 pixel.
Down Arrow Decrement the value of a VSlider control by 1 snap interval or, if you do not
specify a snap interval, by 1 pixel.
Page Down Moves the thumb of a VSlider control to its minimum value.
SWFLoader control
The SWFLoader control lets you load one Flex application into another Flex application. It
has properties that let you scale its contents. It can also resize itself to fit the size of its
contents. By default, content is scaled to fit the size of the SWFLoader control. The
SWFLoader control can also load content on demand programmatically, and monitor the
progress of a load operation.
The SWFLoader control also lets you load the contents of a GIF, JPEG, PNG, SVG, or SWF
file into your application, where the SWF file does not contain a Flex application.
N OTE
Flex also includes the Image control for loading GIF, JPEG, PNG, SVG, or SWF files.
You typically use the Image control for loading static graphic files and SWF files, and use
the SWFLoader control for loading Flex applications as SWF files. The Image control is
also designed to be used in custom cell renderers and item editors.
For more information on the Image control, see “Image control” on page 334. For more
information on using the SWFLoader control to load a Flex application, see “Using the
SWFLoader control to load a LiveCycle Data Services ES application” on page 332.
A SWFLoader control cannot receive focus. However, content loaded into the SWFLoader
control can accept focus and have its own focus interactions.
The SWFLoader control has the following default properties:
Minimum size 0
<mx:Script>
<![CDATA[
[Bindable]
public var varOne:String = "This is a public variable";
</mx:Application>
<mx:Script>
<![CDATA[
import mx.managers.SystemManager;
import mx.controls.Label;
[Bindable]
public var loadedSM:SystemManager;
<mx:Label id="lbl"/>
<mx:SWFLoader id="myLoader" width="300"
source="FlexApp.swf"
creationComplete="initNestedAppProps();"/>
In this example, you specify the value of the source property as "buttonicon.mxml.swf".
Adobe LiveCycle Data Services ES compiles the file buttonicon.mxml, and returns the SWF
file to the main application. If you had specified the value as "buttonicon.swf", LiveCycle
Data Services ES returns the SWF file if it exists, but will not compile buttonicon.mxml if it
does not.
For more information, see Chapter 9, “Using the Flex Compilers,” in Building and Deploying
Flex Applications.
Flex also includes the SWFLoader control for loading Flex applications. You typically
use the Image control for loading static graphic files and SWF files, and use the
SWFLoader control for loading Flex applications. The Image control is also designed to
be used in custom item renderers and item editors. For more information on the
SWFLoader control, see “SWFLoader control” on page 328.
<mx:Image id="image1"
source="http://localhost:8100/flex/assets/logo.jpg"/>
</mx:Application>
N OTE
You can use relative URLs for images hosted on the same web server as the Flex
application, but you must load these images over the Internet rather than access them
locally.
Sizing an image
Flex sets the height and width of an imported image to the height and width settings in the
image file. By default, Flex does not resize the image.
To set an explicit height or width for an imported image, set its height and width properties
of the Image control. Setting the height or width property prevents the parent from resizing
it. The scaleContent property has a default value of true, therefore, Flex scales the image as
it resizes it to fit the specified height and width. The aspect ratio is maintained by default, so
the image may not completely fill the designated space. Set the scaleContent property to
false to disable scaling. Set the maintainAspectRatio property to false to allow an image
to fill all available space regardless of its dimensions. For more information about image aspect
ratios, see “Maintaining aspect ratio when sizing” on page 338.
<mx:Image id="image1"
source="logo.jpg"
width="20" height="20"/>
<mx:Image id="image2"
source="logo.jpg"/>
</mx:Application>
The image increase to four times its original size and fills the entire 200 x 200 pixel area.
The following example sets the height and width of the same image to 150 by 200 pixels, an
aspect ratio of 3:4:
<mx:Image source="myImage.jpg" height="150" width="200"/>
<mx:Image width="120"
source="@Embed('logo.jpg')"
rollOverEffect="{resizeBig}"
rollOutEffect="{resizeSmall}"/>
</mx:Application>
For more information on the Resize effect, see Chapter 19, “Using Behaviors,” on page 719.
If you do not want to preserve the aspect ratio when you resize an image, you can set the
maintainAspectRatio property to false. By default, maintainAspectRatio is set to true
to enable the preservation of the aspect ratio.
The following example resizes the Flex logo to the exact values of the height and width
properties without regard for its aspect ratio:
<?xml version="1.0"?>
<!-- controls\image\ImageResizeMaintainAR.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Image id="image1"
source="@Embed('logo.jpg')"
width="250" height="100"
maintainAspectRatio="false"/>
</mx:Application>
In all other containers, the container controls the positioning of its children and ignores
the x and y properties.
The x and y properties specify the location of the upper-left corner of the image in the Canvas
container. In the following example, you set the position of the image at (40,40), 40 pixels
down and 40 pixels to the right of the upper-left corner of the Canvas container:
<?xml version="1.0"?>
<!-- controls\image\ImageCanvas.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Canvas id="canvas0"
borderStyle="solid"
width="200"
height="200">
<mx:Image id="img0"
source="@Embed('logo.jpg')"
x="40" y="40"/>
</mx:Canvas>
</mx:Application>
This code results in the following application:
<mx:VBox id="vbox0"
borderStyle="solid">
<mx:Image id="img0"
visible="false"
source="@Embed(source='logo.jpg')"/>
</mx:VBox>
</mx:Application>
The VBox container still allocates space for the image when it lays out its children. Thus, the
VBox is the same size as the image file and, if your application contained a Button control
after the <mx:Image> tag, the button would appear in the same location as if the image was
visible.
If you want to make the image invisible, and have its parent container ignore the image when
sizing and positioning its other children, set the includeInLayout property of the Image
control to false. By default, the includeInLayout property to true, so that even when the
image is invisible, the container sizes and positions it as if it were visible.
Often, you use the visible property to mark all images invisible, except one image. For
example, assume that you have an area of your application dedicated to showing one of three
possible images based on some user action. You set the visible property set to true for
only one of the possible images; you set the visible property set to false for all other
images, which makes them invisible.
<mx:Script>
<![CDATA[
private function showImage():void {
image1.visible=true;
}
]]>
</mx:Script>
<mx:VBox id="vbox0"
width="80"
height="80">
<mx:Image id="image1"
visible="false"
source="@Embed(source='logo.jpg')"/>
<mx:Button id="myButton"
label="Show" click="showImage();"/>
</mx:VBox>
</mx:Application>
This following examples shows the results, before and after a user clicks the button:
If you set the visible property, you can control when images are loaded. By allocating space
but making images invisible when a page loads, you ensure that any slower performance
occurs during the initialization stage when users expect it, rather than as they interact with the
application and perform actions that require the image. By setting the visible property, you
can also prevent resizing and relayout within your application at seemingly random intervals.
The load() method of the SWFLoader control only works with GIF, JPEG, PNG, and
SWF files; you cannot use it to load SVG files.
The following example uses the load() method to replace the logo.jpg image with the
logowithtext.gif image when the user clicks a button:
<?xml version="1.0"?>
<!-- controls\image\ImageLoad.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
private function afterImage():void {
image1.load('http://localhost:8100/flex/assets/logowithtext.jpg');
}
]]>
</mx:Script>
<mx:VBox id="vbox0"
width="150" height="100">
<mx:Image id="image1" source="logo.jpg"/>
<mx:Button id="myButton"
label="Show Second Image"
click="afterImage();"/>
</mx:VBox>
</mx:Application>
Notice in this example that the application accesses the images in the local file system; they are
not embedded or accessed by URL. Therefore, you have to compile this application with the
use-network flag set to false.
In this example, the images are stored in the images directory. The complete path to an image
is the directory name, the index number, and the file suffix .jpg.
You register this function as the event listener for a change event in the data grid, as follows:
<mx:DataGrid id="dgrid" height="200" width="350" change="getImage();"/>
When a user changes the currently selected item in the data grid, Flex calls the getImage()
function to update the displayed image.
You could modify this example to use information about the selected item to determine the
image to load, rather than using the selected item’s index. For example, the grid could contain
a list of objects, where each object has a property that contains the image name associated
with it.
In addition to the load() method, you can also access other properties of the SWFLoader
control, including percentLoaded. The percentLoaded property is particularly useful
because it lets you to display a progress bar so users know that the application did not become
unresponsive. For a complete list of the SWFLoader properties and methods, see Adobe Flex
Language Reference.
VideoDisplay control
Flex supports the VideoDisplay control to incorporate streaming media into Flex applications.
Flex supports the Flash Video File (FLV) file format with this control. This section describes
how to use the VideoDisplay control in your application.
The VideoDisplay control does not support scan forward and scan backward
functionality. Also, the VideoDisplay control does not support accessibility or styles.
The user cannot see anything unless some video media is playing.
The playheadTime property of the control holds the current position of the playhead in the
video file, measured in seconds. Most events dispatched by the control include the playhead
position in the associated event object. One use of the playhead position is to dispatch an
event when the video file reaches a specific position. For more information, see “Adding a cue
point” on page 347.
The VideoDisplay control also supports the volume property. This property takes a value
from 0.0 to 1.00; 0.0 is mute and 1.00 is the maximum volume. The default value is 0.75.
When you set maintainAspectRatio to true (the default), the control adjusts the size of the
playing media after the control size has been set. The size of the media is set to maintain its
aspect ratio.
If you omit both width and height properties for the control, Flex makes the control the size
of the playing media. If you specify only one property, and the maintainAspectRatio
property is false, the size of the playing media determines the value of the other property. If
the maintainAspectRatio property is true, the media retains its aspect ratio when resizing.
The following example creates a VideoDisplay control:
<?xml version="1.0"?>
<!-- controls\videodisplay\VideoDisplaySimple.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:VBox>
<mx:VideoDisplay
source="http://localhost:8100/flex/assets/MyVideo.flv"
height="400"
width="400"/>
</mx:VBox>
</mx:Application>
By default, Flex sizes the VideoDisplay control to the size of the media. If you specify the
width or height property of the control, and either is smaller than the media’s dimensions,
Flex does not change the size of the component. Instead, Flex sizes the media to fit within the
component. If the control’s playback area is smaller than the default size of the media, Flex
shrinks the media to fit inside the control.
<mx:VBox>
<mx:VideoDisplay id="myVid"
source="http://localhost:8100/flex/assets/MyVideo.flv"/>
<mx:Button label="Pause" click="myVid.pause();"/>
<mx:Button label="Play" click="myVid.play();"/>
</mx:VBox>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.events.CuePointEvent;
import mx.controls.videoClasses.CuePointManager;
<mx:VBox>
<mx:VideoDisplay
source="http://localhost:8100/flex/assets/MyVideo.flv"
cuePointManagerClass="mx.controls.videoClasses.CuePointManager"
cuePoint="cpHandler(event);">
<mx:cuePoints>
<mx:Object name="first" time="10"/>
<mx:Object name="second" time="20"/>
</mx:cuePoints>
</mx:VideoDisplay>
<mx:TextArea id="cp"/>
</mx:VBox>
</mx:Application>
In this example, the event listener writes a String to the TextArea control when the control
reaches a cue point. The String contains the name and time of the cue point.
<mx:Script>
<![CDATA[
import mx.events.CuePointEvent;
[Bindable]
private var myCuePoints:Array = [
{ name: "first", time: 10},
{ name: "second", time: 20} ];
<mx:VBox>
<mx:VideoDisplay id="myVid"
initialize="initCP();"
cuePointManagerClass="mx.controls.videoClasses.CuePointManager"
source="http://localhost:8100/flex/assets/MyVideo.flv"
cuePoint="cpHandler(event);"/>
<mx:TextArea id="cp" width="200" />
</mx:VBox>
<mx:Script>
<![CDATA[
<mx:VideoDisplay id="myVid"
width="320" height="240"
creationComplete="initCamera();"/>
</mx:Application>
In this example, you create a Camera object in the event handler for the creationComplete
event of the VideoDisplay control, then pass the Camera object as the argument to the
attachCamera() method.
<mx:HBox>
<mx:Label text="RTMP FMS 2.0"/>
<mx:VideoDisplay
autoBandWidthDetection="false"
source="rtmp://localhost/videodisplay/bike.flv"/>
</mx:HBox>
</mx:Application>
In this example, you place the bike.flv file in the directory Flash Media Server
2\applications\videodisplay\streams\_definst_.
Notice that you explicitly set the autoBandWidthDetection property to false, its default
value. When the autoBandWidthDetection property is true, you must create the server-side
file main.asc in the directory Flash Media Server 2\applications\videodisplay\scripts, which
implements the following functions:
application.onConnect = function(p_client, p_autoSenseBW) {}
application.calculateClientBw = function(p_client) {}
Client.prototype.getStreamLength = function(p_streamName) {}
this.acceptConnection(p_client);
if (p_autoSenseBW)
this.calculateClientBw(p_client);
else
p_client.call("onBWDone");
}
Client.prototype.getStreamLength = function(p_streamName) {
return Stream.length(p_streamName);
}
application.calculateClientBw = function(p_client) {
// Add code to set the clients BandWidth.
// Use p_client.getStats() which returns bytes_in
// and bytes_Out and check your bandWidth using
For more information on main.asc, see the Flash Media Server 2 documentation.
ColorPicker control
The ColorPicker control lets users select a color from a drop-down swatch panel (palette). It
initially appears as a preview sample with the selected color. When a user selects the control, a
color swatch panel appears. The panel includes a sample of the selected color and a color
swatch panel. By default, the swatch panel displays the web-safe colors (216 colors, where
each of the three primary colors has a value that is a multiple of 33, such as #CC0066)
For complete reference information, see ColorPicker in Adobe Flex Language Reference.
Collapsed Expanded
Flex populates the color swatch panel and the text box from a data provider. By default, the
control uses a data provider that includes all the web-safe colors. If you use your own data
provider you can specify the following:
The colors to display You must specify the colors if you use your own dataProvider.
Labels to display in the text box for the colors If you do not specify text labels, Flex uses
the hexadecimal color values.
Additional information for each color This information can include any information that is
of use to your application, such as IDs or descriptive comments.
The following image shows an expanded ColorPicker control that uses a custom data provider
that includes color label values. It also uses styles to set the sizes of the display elements.
Minimum size 0 by 0
The ColorPicker control uses a list-based data provider for the colors. For more information
on this type of data provider, see Chapter 8, “Using Data Providers and Collections,” on
page 171. If you omit the data provider, the control uses a default data provider with the web-
safe colors. The data provider can be an array of colors or an array of objects. The following
example populates a ColorPicker with a simple array of colors. For information on using a
more complex dataProvider, see “Using Objects to populate a ColorPicker control”
on page 355.
<?xml version="1.0"?>
<!-- controls\colorpicker\CPSimple.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
[Bindable]
public var simpleDP:Array = ['0x000000', '0xFF0000', '0xFF8800',
'0xFFFF00', '0x88FF00', '0x00FF00', '0x00FF88', '0x00FFFF',
'0x0088FF', '0x0000FF', '0x8800FF', '0xFF00FF', '0xFFFFFF'];
]]>
</mx:Script>
You can also specify the data for the ColorPicker control using a <mx:dataProvider> child
tag; for an example, see “Using custom field names” on page 357.
Some examples in this section use simple Arrays as custom data sources, not
ArrayCollections, because the array contents are static.
<mx:Script>
<![CDATA[
//Import the event classes.
import mx.events.DropdownEvent;
import mx.events.ColorPickerEvent;
[Bindable]
public var simpleDP:Array = ['0x000000', '0xFF0000', '0xFF8800',
'0xFFFF00', '0x88FF00', '0x00FF00', '0x00FF88', '0x00FFFF',
'0x0088FF', '0x0000FF', '0x8800FF', '0xFF00FF', '0xFFFFFF'];
<mx:VBox>
<mx:TextArea id="forChange"
width="150"/>
<mx:ColorPicker id="cp"
dataProvider="{simpleDP}"
open="openEvt(event);"
change="changeEvt(event);"/>
</mx:VBox>
</mx:Application>
The ColorPicker control dispatches open event when the swatch panel opens and Dispatches
a change event when the value of the control changes due to user interaction. The
currentTarget property of the object passed to the event listener contains a reference to the
ColorPicker control. In this example, the event listeners use two properties of the ColorPicker
control, selectedItem and selectedIndex. Every change event updates the TextArea
control with the selected item and the item’s index in the control, and an open event displays
the word Opened.
<mx:Script>
<![CDATA[
import mx.events.ColorPickerEvent;
import mx.events.DropdownEvent;
[Bindable]
public var complexDPArray:Array = [
{label:"Yellow", color:"0xFFFF00",
descript:"A bright, light color."},
{label:"Hot Pink", color:"0xFF66CC",
descript:"It's HOT!"},
{label:"Brick Red", color:"0x990000",
descript:"Goes well with warm colors."},
{label:"Navy Blue", color:"0x000066",
descript:"The conservative favorite."},
{label:"Forest Green", color:"0x006600",
descript:"Great outdoorsy look."},
<mx:VBox>
<mx:TextArea id="descriptBox"
width="150" height="50"/>
<mx:ColorPicker id="cp"
height="50" width="150"
dataProvider="{complexDP}"
change="changeEvt(event);"
open="openEvt(event);"
swatchWidth="25"
swatchHeight="25"
textFieldWidth="95"
editable="false"/>
</mx:VBox>
</mx:Application>
In this example, the selectedItem property contains a reference to the object defining the
selected item. The example uses selectedItem.label to access the object’s label property
(the color name), and selectedItem.descript to access the object’s descript property (the
color description). Every change event updates the TextArea control with the label
property of the selected item and the item’s description. The open event clears the current text
in the TextArea control each time the user opens up the ColorPicker to display the swatch
panel.
This example also uses several of the ColorPicker properties and styles to specify the control’s
behavior and appearance. The editable property prevents users from entering a value in the
color label box (so they can only select the colors from the dataProvider). The swatchWidth
and swatchHeight styles control the size of the color samples in the swatch panel, and the
textFieldWidth style ensures that the text field is long enough to accommodate the longest
color name.
<mx:Script>
<![CDATA[
import mx.events.ColorPickerEvent;
import mx.events.DropdownEvent;
<mx:VBox>
<mx:TextArea id="descriptBox"
width="150" height="50"/>
<mx:ColorPicker id="cp"
height="50" width="150"
labelField="cName"
colorField="cVal"
change="changeEvt(event)"
open="openEvt(event)"
swatchWidth="25"
swatchHeight="25"
textFieldWidth="95"
editable="false">
<mx:dataProvider>
<mx:ArrayCollection>
<mx:source>
<mx:Object cName="Yellow" cVal="0xFFFF00"
cDescript="A bright, light color."/>
<mx:Object cName="Hot Pink" cVal="0xFF66CC"
cDescript="It's HOT!"/>
<mx:Object cName="Brick Red" cVal="0x990000"
cDescript="Goes well with warm colors."/>
<mx:Object cName="Navy Blue" cVal="0x000066"
User interaction
A ColorPicker control can be editable or noneditable. In a noneditable ColorPicker control,
the user must select a color from among the swatch panel options. In an editable ColorPicker
control, a user can select swatch panel items or enter a hexadecimal color value directly into
the label text field at the top of the swatch panel. Users can type numbers and uppercase or
lowercase letters in the ranges a-f and A-F in the text box; it ignores all other non-numeric
characters.
Mouse interaction
You can use the mouse to navigate and select from the control:
■ Click the collapsed control to display or hide the swatch panel.
■ Click any swatch in the swatch panel to select it and close the panel.
■ Click outside the panel area to close the panel without making a selection.
■ Click in the text field to move the text entry cursor.
Keyboard interaction
If the ColorPicker is editable, and the swatch panel has the focus, alphabetic keys in the range
A-F and a-f, numeric keys, and the Backspace and Delete keys enter and remove text in the
color text box. You can also use the following keystrokes to control the ColorPicker:
Key Description
Control+Down Arrow Opens the swatch panel and puts the focus on the selected swatch.
Home Moves the selection to the first color in a row of the swatch panel. Has
no effect if there is a single column.
Page Up Moves the selection to the top color in a column of the swatch panel.
Has no effect if there is a single row.
Page Down Moves the selection to the bottom color in a column of the swatch
panel. Has no effect if there is a single row.
Escape Closes the swatch panel without changing the color in the color
picker.
Most Web browsers do not support using his key.
Enter Selects the current color from the swatch panel and closes the
swatch panel; equivalent to clicking a color swatch. If the focus is on
the text field of an editable ColorPicker, selects the color specified by
the field text.
Arrows When the swatch panel is open, moves the focus to the next color left,
right, up, and down in the swatch grid. On a single-row swatch panel,
Up and Right Arrow keys are equivalent, and Down and Left Arrow
keys are equivalent.
On a multirow swatch panel, the selection wraps to the beginning or
end of the next or previous line. On a single-row swatch panel,
pressing the key past the beginning or end of the row loops around on
the row.
When the swatch panel is closed, but has the focus, the Up and Down
Arrow keys have no effect. The Left and Right Arrow keys change the
color picker selection, moving through the colors as if the panel were
open.
NOT E
When the swatch panel is open, you cannot use the Tab and Shift+Tab keys to move the
focus to another object.
The Alert control closes when you select a button in the control, or press the Escape key.
The Alert.show() method has the following syntax:
public static show(
text:String,
title:String = null,
flags:uint = mx.controls.Alert.OK,
parent:Sprite = null,
clickListener:Function = null,
iconClass:Class = null,
defaultButton:uint = mx.controls.Alert.OK) : Alert
Argument Description
text (Required) Specifies the text message displayed in the dialog box.
title Specifies the dialog box title. If omitted, displays a blank title bar.
flags Specifies the button(s) to display in the dialog box. The options are as follows:
mx.controls.Alert.OK OK button
mx.controls.Alert.YES Yes button
mx.controls.Alert.NO No button
mx.controls.Alert.CANCEL Cancel button
Each option is a bit value and can be combined with other options using the
pipe '|' operator. The buttons will appear in the order listed here regardless of
the order you specify them in your code.The default value is
mx.controls.Alert.OK.
iconClass Specifies an icon to display to the left of the message text in the dialog box.
defaultButton Specifies the default button using one of the valid values for the flags
argument. This is the button that is selected when the user presses the Enter
key. The default value is Alert.OK.
Pressing the Escape key triggers the Cancel or No button just as if you clicked
it.
To use the Alert control, you first import the Alert class into your application. then call the
show() method, as the following example shows:
<?xml version="1.0"?>
<!-- controls\alert\AlertSimple.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
]]>
</mx:Script>
<mx:TextInput id="myInput"
width="150"
text=""/>
<mx:Button id="myButton"
label="Copy Text"
click="myText.text = myInput.text;
Alert.show('Text Copied!', 'Alert Box', mx.controls.Alert.OK);"/>
<mx:TextInput id="myText"/>
</mx:Application>
In this example, selecting the Button control copies text from the TextInput control to the
TextArea control, and displays the Alert control.
<mx:Script>
<![CDATA[
import mx.controls.Alert;
<mx:TextInput id="myInput"
width="150"
text=""/>
<mx:Button id="myButton"
label="Copy Text"
click="alertListener();"/>
<mx:TextInput id="myText"/>
</mx:Application>
NOT E
After the show() method creates the dialog box, Flex continues processing of your
application; it does not wait for the user to close the dialog box.
<mx:Script>
<![CDATA[
import mx.controls.Alert;
<mx:TextInput id="myInput"
width="150"
text=""/>
<mx:Button id="myButton"
label="Copy Text"
click="openAlert();"/>
<mx:TextInput id="myText"/>
</mx:Application>
In this example, you set the height and width properties of the Alert object to explicitly size
the control.
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.CloseEvent;
<mx:TextInput id="myInput"
width="150"
text="" />
<mx:Button id="myButton"
label="Copy Text"
click='Alert.show("Copy Text?", "Alert",
Alert.OK | Alert.CANCEL, this,
alertListener, null, Alert.OK);'/>
<mx:TextInput id="myText"/>
</mx:Application>
In this example, you define an event listener for the Alert control. Within the body of the
event listener, you determine which button was pressed by examining the detail property of
the event object. The event object is an instance of the CloseEvent class. If the user pressed the
OK button, copy the text. If the user pressed any other button, or pressed the Escape key, do
not copy the text.
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.CloseEvent;
[Embed(source="assets/alertIcon.jpg")]
[Bindable]
public var iconSymbol:Class;
<mx:TextInput id="myInput"
width="150"
text=""/>
<mx:Button id="myButton"
label="Copy Text"
click='Alert.show("Copy Text?", "Alert",
Alert.OK | Alert.CANCEL, this,
alertListener, iconSymbol, Alert.OK );'/>
<mx:TextInput id="myText"/>
</mx:Application>
ProgressBar control
The ProgressBar control provides a visual representation of the progress of a task over time.
There are two types of ProgressBar controls: determinate and indeterminate. A determinate
ProgressBar control is a linear representation of the progress of a task over time. You can use
this when the user is required to wait for an extended period of time, and the scope of the task
is known.
Use the ProgressBar control when the user is required to wait for completion of a process over
an extended period of time. You can attach the ProgressBar control to any kind of loading
content. A label can display the extent of loaded contents when enabled.
The ProgressBar control has the following default properties:
Minimum size 0
Maximum size Undefined
<mx:Script>
<![CDATA[
public function initImage():void {
image1.load('http://localhost:8100/flex/assets/DSC00034.JPG');
}
]]>
</mx:Script>
<mx:VBox id="vbox0"
width="600" height="600">
<mx:Canvas>
<mx:ProgressBar width="200" source="image1"/>
</mx:Canvas>
<mx:Button id="myButton"
label="Show"
click="initImage();"/>
<mx:Image id="image1"
height="600" width="600"
autoLoad="false"
visible="true"/>
</mx:VBox>
</mx:Application>
In this mode, the Image control issues progress events during the load, and a complete
event when the load completes.
The <mx:Image> tag exposes the getBytesLoaded() and getBytesTotal() methods, so you
could also use polled mode, as the following example shows:
<mx:ProgressBar width="200" source="image1" mode="polled"/>
In manual mode, mode="manual", you use an indeterminate ProgressBar control with the
maximum and minimum properties and the setProgress() method. The setProgress()
method has the following method signature:
setProgress(Number completed, Number total)
<mx:Script>
<![CDATA[
public function initImage():void {
image1.load('http://localhost:8100/flex/assets/DSC00034.JPG');
}
]]>
</mx:Script>
<mx:VBox id="vbox0"
width="600" height="600">
<mx:Canvas>
<mx:ProgressBar
width="300"
source="image1"
mode="polled"
label="Loading Image %1 out of %2 bytes, %3%%"
labelWidth="400"/>
</mx:Canvas>
<mx:Button id="myButton"
label="Show"
click="initImage();"/>
<mx:Image id="image1"
height="600" width="600"
autoLoad="false"
visible="true"/>
</mx:VBox>
</mx:Application>
HRule control
VRule control
The HRule and VRule controls have the following default properties:
shadowColor 0xEEEEEE
<mx:VBox>
<mx:Label text="Above"/>
<mx:HRule/>
<mx:Label text="Below"/>
</mx:VBox>
<mx:HBox>
<mx:Label text="Left"/>
<mx:VRule/>
<mx:Label text="Right"/>
</mx:HBox>
</mx:Application>
This example creates the output shown in the preceding image.
You can also use properties of the HRule and VRule controls to specify line width, stroke
color, and shadow color, as the following example shows:
<?xml version="1.0"?>
<!-- controls\rule\RuleProps.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:VBox>
<mx:Label text="Above"/>
<mx:HRule shadowColor="0xEEEEEE"/>
<mx:Label text="Below"/>
</mx:VBox>
<mx:HBox>
<mx:Label text="Left"/>
<mx:VRule strokeWidth="10" strokeColor="0xC4CCCC"/>
<mx:Label text="Right"/>
</mx:HBox>
</mx:Application>
If you set the height property of an HRule control to a value greater than the strokeWidth
property, Flex draws the rule within a rectangle of the specified height, and centers the rule
vertically within the rectangle. The height of the rule is the height specified by the
strokeWidth property.
If you set the height property of an HRule control or the width property of a VRule control
to a value smaller than the strokeWidth property, the rule is drawn as if it had a
strokeWidth property equal to the height or width property.
NO TE
If the height and width properties are specified as percentage values, the actual pixel
values are calculated before the height and width properties are compared to the
strokeWidth property.
The strokeColor and shadowColor properties determine the colors of the HRule and VRule
controls. The strokeColor property specifies the color of the line as follows:
■ If you set the strokeWidth property to 1, specifies the color of the entire line.
■ If you set the strokeWidth property to 2, specifies the color of the top line for an HRule
control, or the left line for a VRule control.
■ If you set the strokeWidth property to a value greater than 2, specifies the color of the
top and left edges of the rectangle.
The shadowColor property specifies the shadow color of the line as follows:
■ If you set the strokeWidth property to 1, does nothing.
■ If you set the strokeWidth property to 2, specifies the color of the bottom line for an
HRule control, or the right line for a VRule control.
■ If you set the strokeWidth property to a value greater than 2, specifies the color of the
bottom and right edges of the rectangle.
<mx:Style>
.thickRule {strokeWidth:5}
HRule {strokeColor:#00FF00; shadowColor:#0000FF}
</mx:Style>
<mx:HRule styleName="thickRule"/>
</mx:Application>
This example produces the following image:
ScrollBar control
The VScrollBar (vertical ScrollBar) control and HScrollBar (horizontal ScrollBar) controls let
the user control the portion of data that is displayed when there is too much data to fit in the
display area.
Although you can use the VScrollBar control and HScrollBar control as stand-alone controls,
they are usually combined with other components as part of a custom component to provide
scrolling functionality. For more information, see Creating and Extending Flex Components.
ScrollBar controls consists of four parts: two arrow buttons, a track, and a thumb. The
position of the thumb and display of the buttons depends on the current state of the ScrollBar
control. The width of the control is equal to the largest width of its subcomponents (arrow
buttons, track, and thumb). Every subcomponent is centered in the scroll bar.
The ScrollBar control uses four parameters to calculate its display state:
■ Minimum range value
■ Maximum range value
■ Current position; must be within the minimum and maximum range values
■ Viewport size; represents the number of items in the range that can be displayed at once
and must be equal to or less than the range
<mx:Script>
<![CDATA[
import mx.events.ScrollEvent;
<mx:Label
width="100%"
color="blue"
text="Click on the scroll bar to view its properties."/>
<mx:VScrollBar id="bar"
height="100%"
minScrollPosition="0"
maxScrollPosition="{this.width - 20}"
lineScrollSize="50"
pageScrollSize="100"
repeatDelay="1000"
repeatInterval="500"
scroll="myScroll(event);"/>
<mx:TextArea id="showPosition"
height="100%" width="100%"
color="blue"/>
</mx:Application>
User interaction
Use the mouse to click the various portions of the ScrollBar control, which dispatches events
to listeners. The object listening to the ScrollBar control is responsible for updating the
portion of data displayed. The ScrollBar control updates itself to represent the new state after
the action has taken place.
CHAPTER 11
Contents
About text controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
Using the text property . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
Using the htmlText property. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .384
Selecting and modifying text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
Label control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400
TextInput control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
Text control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
TextArea control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
RichTextEditor control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406
TextInput No Yes
Text Yes No
377
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
All controls except the RichTextEditor control are single components with a simple text
region; for example, the following image shows a TextInput control in a simple form:
The way you specify special characters, including quotation marks, greater than and less than
signs, and apostrophes, depends on whether you use them in MXML tags or in ActionScript.
It also depends on whether you specify the text directly or wrap the text in a CDATA section.
N OTE
If you specify the value of the text property by using a string directly in MXML, Flex
collapses white space characters. If you specify the value of the text property in
ActionScript, Flex does not collapse white space characters.
<mx:Text width="400">
<mx:text>
This string contains a less than, <, greater than,
>, ampersand, &, apostrophe, ', and quotation mark, ".
</mx:text>
</mx:Text>
</mx:Application>
The resulting application contains three almost identical text controls, each with the
following text. The first two controls, however, convert any tabs in the text to spaces.
This string contains a less than, <, greater than, >, ampersand, &,
apostrophe, ', and quotation mark, ".
In a CDATA section If you wrap the text string in the CDATA tag, the following rules apply:
■ You cannot use a CDATA section in a property assignment statement in the text control
opening tag; you must define the property in an <mx:text> child tag.
■ Text inside the CDATA section appears as it is entered, including white space characters.
Use literal characters, such as " or < for special characters, and use standard return and tab
characters. Character entities, such as >, and backslash-style escape characters, such as
\n, appear as literal text.
You do not need to escape double-quotation marks if you’re loading text from an
external file; it is only necessary if you’re assigning a string of text in ActionScript.
■ If you use single-quotation marks for the assignment delimiters, use ' for the
single-quotation mark character (') in your HTML. In ActionScript, you can also use
the escape sequence \’.
■ When you enter HTML-formatted text, you must include attributes of HTML tags in
double- or single-quotation marks. Attribute values without quotation marks can produce
unexpected results, such as improper rendering of text. You must follow the escaping rules
for quotation marks within quotation marks, as described in “Escaping special characters
in HTML text” on page 386.
You can also define a:link, a:hover, and a:active styles for anchor tags by using style
sheets.
The <a> tag does not make the link text blue. You must apply formatting tags to change the
text format. You can also define a:link, a:hover, and a:active styles for anchor tags by
using style sheets.
<mx:Script>
<![CDATA[
import flash.events.TextEvent;
<mx:TextArea id="myTA"/>
</mx:Application>
The Label control must have the selectable property set to true to generate the link event.
When you use the link event, the event is generated and the text following event: in the
hyperlink destination is included in the text property of the event object. However, the
hyperlink is not automatically executed; you must execute the hyperlink from within your
event handler. This allows you to modify the hyperlink, or even prohibit it from occurring, in
your application.
The <img> tag is not fully supported in Flex 2, and might not work in some cases.
The image <img> tag lets you embed external JPEG, GIF, PNG, and SWF files inside text
fields. Text automatically flows around images you embed in text fields. This tag is supported
only in dynamic and input text fields that are multiline and wrap their text.
By default, Flash displays media embedded in a text field at full size. To specify dimensions for
embedded media, use the <img> tag’s height and width attributes.
In general, an image embedded in a text field appears on the line following the <img> tag.
However, when the <img> tag is the first character in the text field, the image appears on the
first line of the text field.
The <img> tag has one required attribute, src, which specifies the path to an image file. All
other attributes are optional.
The <img> tag supports the following attributes:
src Specifies the URL to a GIF, JPEG, PNG, or SWF file. This attribute is required; all
other attributes are optional. External files are not displayed until they have downloaded
completely.
align Specifies the horizontal alignment of the embedded image within the text field. Valid
values are left and right. The default value is left.
height Specifies the height of the image, in pixels.
hspace Specifies the amount of horizontal space that surrounds the image where no text
appears. The default value is 8.
id Specifies the identifier for the imported image. This is useful if you want to control the
embedded content with ActionScript.
vspace Specifies the amount of vertical space that surrounds the image where no text.
width Specifies the width of the image, in pixels.
appears. The default value is 8.
In Flex 2, the <li> tag does not work properly with Label controls. With TextInput
controls, it must be put before the first character in the text.
You cannot use the </u> end tag to override underlining that you set for all text in a control
by using the textDecoration style.
Selecting text
The Flex editable controls provide properties and methods to select text regions and get
selections, as the following sections describe. You can modify the contents of the selection as
described in “Modifying text” on page 396.
Creating a selection
The TextInput and TextArea controls, including the RichTextEditor control’s TextArea
subcontrol, provide the following text selection properties and method:
■ setSelection() method selects a range of text. You specify the zero-based indexes of the
start character and the position immediately after the last character in the text.
■ selectionBeginIndex and selectionEndIndex set or return the zero-based location in
the text of the start and position immediately after the end of a selection.
To select the first 10 characters of the myTextArea TextArea control, for example, use the
following method:
myTextArea.setSelection(0, 10);
To change the last character of this selection to be the twenty-fifth character in the TextArea
control, use the following statement:
myTextArea.endIndex=25;
To select text in a RichTextEditor control, use the control’s TextArea subcontrol, which you
access by using the textArea id. To select the first 10 characters in the myRTE
RichTextEditor control, for example, use the following code:
myRTE.textArea.setSelection(0, 10);
Getting a selection
You get a text control’s selection by getting a TextRange object with the selected text. You can
then use the TextRange object to modify the selected text, as described in “Modifying text”
on page 396. The technique you use to get the selection depends on the control type, as the
following sections describe.
The second parameter, true, tells the constructor to return a TextRange object with the
selected text.
Modifying text
You use the TextRange class to modify the text in a TextArea, TextInput, or RichTextEditor
control. This class lets you affect the following text characteristics:
■ text or htmltext property contents
■ text color, decoration (underlining), and alignment
■ font family, size, style (italics), and weight (bold)
■ URL of an HTML <a> link.
Changing text
After you get a TextRange object, use its properties to modify the text in the range. The
changes you make to the TextRange appear in the text control.
<!-- The text area. When you release the mouse after selecting text,
it calls the func1 function. -->
<mx:RichTextEditor id="rte1" htmlText="{htmlData}" width="100%"
height="100%" mouseUp="changeSelectionText()"/>
<mx:TextArea editable="false" id="t1" fontSize="12" fontWeight="bold"
width="300" height="180"/>
</mx:Application>
Label control
The Label control is a noneditable single-line text label. It has the following characteristics:
■ The user cannot change the text, but the application can modify it.
■ You can specify text formatting by using styles or HTML text.
■ You can control the alignment and sizing.
■ The control is transparent and does not have a backgroundColor property, so the
background of the component’s container shows through.
■ The control has no borders, so the label appears as text written directly on its background.
■ The control cannot take the focus.
For complete reference information, see Label in Adobe Flex Language Reference.
To create a multiline, noneditable text field, use a Text control. For more information, see
“Text control” on page 403. To create user-editable text fields, use TextInput or TextArea
controls. For more information, see “TextInput control” on page 401 and “TextArea control”
on page 405.
The following image shows a Label control:
For the code used to create this sample, see “Creating a Label control”.
Minimum size 0
If you do not specify a width, the Label control automatically resizes when you change the
value of the text or htmlText property.
If you explicitly size a Label control so that it is not large enough to accommodate its text, the
text is truncated and terminated by an ellipses (...). The full text displays as a tooltip when you
move the mouse over the Label control. If you also set a tooltip by using the tooltip
property, the tooltip is displayed rather than the text.
TextInput control
The TextInput control is a single-line text field that is optionally editable. The TextInput
control supports the HTML rendering capabilities of Adobe Flash Player.
For complete reference information, see TextInput in Adobe Flex Language Reference.
To create a multiline, editable text field, use a TextArea control. For more information, see
“TextArea control” on page 405. To create noneditable text fields, use Label and Text
controls. For more information, see “Label control” on page 400 and “Text control”
on page 403.
The TextInput control does not include a label, but you can add one using a Label control or
by nesting the TextInput control in a FormItem container in a Form layout container, as
shown in the example in “About text controls” on page 377. TextInput controls dispatch
change, textInput , and enter events.
If you disable a TextInput control, it displays its contents in a different color, represented by
the disabledColor style. You can set a TextInput control’s editable property to false to
prevent editing of the text. You can set a TextInput control’s displayAsPassword property to
conceal the input text by displaying characters as asterisks.
If you do not specify a width, the TextInput control automatically resizes when you change
the value of the text or htmlText property. It does not resize in response to typed user input.
Text control
The Text control displays multiline, noneditable text. The control has the following
characteristics:
■ The user cannot change the text, but the application can modify it.
■ The control does not support scroll bars. If the text exceeds the control size users can use
keys to scroll the text
■ The control is transparent so that the background of the component’s container shows
through
■ The control has no borders, so the label appears as text written directly on its background.
■ The control supports HTML text and a variety of text and font styles.
■ The text always word-wraps at the control boundaries, and is always aligned to the top of
the control.
Minimum size 0
TextArea control
The TextArea control is a multiline, editable text field with a border and optional scroll bars.
The TextArea control supports the HTML and rich text rendering capabilities of Flash Player.
The TextArea control dispatches change and textInput events.
For complete reference information, see TextArea in Adobe Flex Language Reference.
The following image shows a TextArea control:
To create a single-line, editable text field, use the TextInput control. For more information,
see “TextInput control” on page 401. To create noneditable text fields, use the Label and Text
controls. For more information, see “Label control” on page 400 and “Text control”
on page 403.
If you disable a TextArea control, it displays its contents in a different color, represented by
the disabledColor style. You can set a TextArea control’s editable property to false to
prevent editing of the text. You can set a TextArea control’s displayAsPassword property to
conceal input text by displaying characters as asterisks.
The TextArea control does not resize to fit the text that it contains. If the new text exceeds the
capacity of the TextArea control and the horizontalScrollPolicy is true (the default
value), the control adds a scrollbar.
RichTextEditor control
The RichTextEditor control lets users enter, edit, and format text. Users apply text formatting
and URL links using subcontrols that are located at the bottom of the RichTextEditor
control.
For complete reference information, see RichTextEditor in Adobe Flex Language Reference.
For the source for this example, see “Creating a RichTextEditor control” on page 408.
You use the RichTextEditor interactively as follows:
■ Text that you type is formatted as specified by the control settings.
■ To apply new formatting to existing text, select the text and set the controls to the
required format.
■ To create a link, select a range of text, enter the link target in the text box on the right, and
press Enter. You can only specify the URL; the link always opens in a _blank target. Also,
creating the link does not change the appearance of the link text; you must separately
apply any color and underlining.
creationComplete="rte1.textArea.setStyle('backgroundColor','0xeeffee')"
text="Simple sample text"
/>
</mx:Application>
</mx:Application>
]]>
</mx:Script>
</mx:TitleWindow>
CHAPTER 12
Contents
About menu-based controls. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415
Defining menu structure and data. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416
Handling menu-based control events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .423
Menu control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .435
MenuBar control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439
PopUpMenuButton control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441
415
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Defining menu structure and data
All menu-based controls use data providers with the following characteristics to specify the
structure and contents of the menus:
■ The data providers are often hierarchical, but you can also have a single-level menu.
■ Individual menu items include fields that determine the menu item appearance and
behavior. Menu-based controls support fields that define the label text, an icon, the menu
item type, and item status. For information on meaningful fields, see “Specifying and
using menu entry information” on page 417.
Menu attributes
Menu items can specify several attributes that determine how the item is displayed and
behaves. The following table lists the attributes you can specify, their data types, their
purposes, and how the data provider must represent them if the menu uses the
DefaultDataDescriptor class to parse the data provider:
groupName String (Required, and meaningful, for radio type only) The identifier that
associates radio button items in a radio group. If you use the default
data descriptor, data providers must use a groupName XML attribute or
object field to specify this characteristic.
icon Class Specifies the class identifier of an image asset. This item is not used
for the check, radio, or separator types. You can use the checkIcon
and radioIcon styles to specify the icons used for radio and check
box items that are selected.
The menu’s iconField or iconFunction property determines the name
of the field in the data that specifies the icon, or a function for
determining the icons.
type String Specifies the type of menu item. Meaningful values are separator,
check, or radio. Flex treats all other values, or nodes with no type
entry, as normal menu entries.
If you use the default data descriptor, data providers must use a type
XML attribute or object field to specify this characteristic.
Menu-based controls ignore all other object fields or XML attributes, so you can use them for
application-specific data.
<mx:Script>
<![CDATA[
import mx.controls.Menu;
<?xml version="1.0"?>
<!-- menus/SimpleMenuControl.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" >
<mx:Script>
<![CDATA[
// Import the Menu control.
import mx.controls.Menu;
[Bindable]
[Embed(source="assets/topIcon.jpg")]
public var myTopIcon:Class;
[Bindable]
[Embed(source="assets/radioIcon.jpg")]
public var myRadioIcon:Class;
[Bindable]
[Embed(source="assets/checkIcon.gif")]
public var myCheckIcon:Class;
<mx:VBox>
<!-- Define a Button control to open the menu -->
<mx:Button id="myButton"
label="Open Menu"
click="createAndShow();"/>
</mx:VBox>
</mx:Application>
Property Description
item The item in the data provider for the menu item associated with the event.
index The index of the item in the menu or submenu that contains it.
label The label of the item.
menu A reference to the Menu control where the event occurred.
menuBar The MenuBar control instance that is the parent of the menu, or undefined
when the menu does not belong to a MenuBar. For more information, see
“MenuBar control” on page 439.
To access properties and fields of an object-based menu item, you specify the menu item field
name, as follows:
ta1.text = event.item.label
To access attributes of an E4X XML-based menu item, you specify the menu item attribute
name in E4X syntax, as follows:
ta1.text = event.item.@label
N OTE
If you set an event listener on a submenu of a menu-based control, and the menu data
provider’s structure changes (for example, an element is removed), the event listener
might no longer exist. To ensure that the event listener is available when the data
provider structure changes, either listen on events of the menu-based control, not a
submenu, or add the event listener each time an event occurs that changes the data
provider’s structure.
<mx:Script>
<![CDATA[
import mx.controls.Menu;
import mx.events.MenuEvent;
Menu bar
Pop-up submenu
The MenuBar control does not dispatch the itemClick event when you select an item on
the menu bar; it only dispatches the itemClick event when you select an item on a pop-
up submenu.
For each pop-up submenu, the MenuBar dispatches the change, itemClick, itemRollOut,
itemRollOver, menuShow, and menuHide events in the same way it does for the Menu
control. Handle events triggered by the pop-up menus as you would handle events from
Menu controls. For more information, see “Handling Menu control events” on page 423.
<mx:Script>
<![CDATA[
import mx.events.MenuEvent;
import mx.controls.Alert;
import mx.collections.*;
[Bindable]
public var menuBarCollection:XMLListCollection;
<mx:Label
width="100%"
color="blue"
text="Select a menu item."/>
<mx:MenuBar labelField="@label"
dataProvider="{menuBarCollection}"
change="changeHandler(event);"
itemClick="itemClickHandler(event);"
itemRollOver="rollOverHandler(event);"/>
<mx:TextArea id="rollOverTextArea"
width="200" height="100"/>
<mx:TextArea id="itemClickTextArea"
width="200" height="100"/>
</mx:Panel>
</mx:Application>
<mx:Script>
<![CDATA[
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.events.*;
import mx.controls.*;
// Set the Inbox (fourth) item in the menu as the button item.
private function initData():void {
Menu(p1.popUp).selectedIndex=3;
}
// itemClick event handler, invoked when you select from the menu.
// Shows the event's label, index properties, and the values of the
// label and data fields of the data provider entry specified by
// the event's item property.
public function itemClickHandler(event:MenuEvent):void {
Alert.show("itemClick event label: " + event.label
+ " \nindex: " + event.index
+ " \nitem.label: " + event.item.label
+ " \nitem.data: " + event.item.data);
}
<mx:PopUpMenuButton id="p1"
showRoot="true"
dataProvider="{menuDP}"
Menu control
The Menu control is a pop-up control that contains a menu of individually selectable choices.
You use ActionScript to create a Menu control that pops up in response to a user action,
typically as part of an event listener. Because you create a Menu control in response to an
event, it does not have an MXML tag; you can create Menu controls in ActionScript only.
For complete reference information, see Menu in Adobe Flex Language Reference.
In this example, the MenuItem A and MenuItem D items open submenus. Submenus open
when the user moves the mouse pointer over the parent item or accesses the parent item by
using keyboard keys.
The default location of the Menu control is the upper-left corner of your application, at x, y
coordinates 0,0. You can pass x and y arguments to the show() method to control the
position relative to the application.
After a Menu opens, it remains visible until the user selects an enabled menu item, the user
selects another component in the application, or a script closes the menu.
To create a static menu that stays visible all the time, use the MenuBar control or
PopUpMenuButton control. For more information on the MenuBar control, see “MenuBar
control” on page 439. For more information on the PopUpMenuButton control, see
“PopUpMenuButton control” on page 441.
(The first parameter can optionally specify the parent container of the menu.)
If you do not display the root node of the data provider, for example, if the data provider
is an XML document in E4X format, use a third parameter with the value false. This
parameter sets the menu’s showRoot property. The following example creates a menu that
does not show the data provider root:
var myMenu:Menu = Menu.createMenu(null, myMenuData, false);
NOTE
To hide the root node, you must set the showRoot property in the createMenu method.
Setting the property after you create the menu has no effect.
2. Display the Menu instance by calling the ActionScript Menu.show() method; for example:
myMenu.show(10, 10);
N OTE
The show() method automatically adds the Menu object to the display list, and the hide()
method automatically removes it from the display list. Clicking outside the menu (or
pressing Escape) also hides the Menu object and removes it from the display list.
If you create a Menu object by using the Menu.createMenu() method, the Menu is
removed from the display list automatically when it is closed. To prevent this default
behavior, you can listen for the menuHide event and call preventDefault() on the event
object.
Menus displayed using the Menu.popUpMenu() method are not removed automatically; you
must call the PopUpManager.removePopUp() method on the Menu object.
<mx:Script>
<![CDATA[
// Import the Menu control.
import mx.controls.Menu;
<mx:VBox>
<!-- Define a Button control to open the menu -->
<mx:Button id="myButton"
label="Open Menu"
click="createAndShow();"/>
</mx:VBox>
Because this example uses an E4X XML data source, you must specify the label field using the
E4X @ attribute specifier syntax, and you tell the control not to show the data provider root
node.
Several attributes or fields. such as the type attribute, have meaning to the Menu control. For
information on how Flex interprets and uses the data provider data, see “Specifying and using
menu entry information” on page 417.
Key Description
Down Arrow Moves the selection down and up the rows of the menu. The selection loops at
Up Arrow the top or bottom row.
Right Arrow Opens a submenu, or moves the selection to the next menu in a menu bar.
Left Arrow Closes a submenu and returns focus to the parent menu (if a parent menu
exists), or moves the selection to the previous menu in a menu bar (if the menu
bar exists).
Enter Opens a submenu, has the effect of clicking and releasing the mouse on a row
if a submenu does not exist.
The control shows the labels of the top level of the data provider menu. When a user selects a
top-level menu item, the MenuBar control opens a submenu. The submenu stays open until
the user selects another top-level menu item, selects a submenu item, or clicks outside the
MenuBar area.
The MenuBar control has the following sizing characteristics:
The dataProvider property is the default property of the MenuBar control, so you can define
the XML or XMLList object as a direct child of the <mx:MenuBar> tag, as the following
example shows:
<?xml version="1.0"?>
<!-- menus/MenuBarControl.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" >
PopUpMenuButton control
The PopUpMenuButton is a PopUpButton control whose secondary button pops up a Menu
control. When the user selects an item from the pop-up menu, the main button of the
PopUpButton changes to show the icon and label of the selected menu item. Unlike the
Menu and MenuBar controls, the PopUpMenuButton supports only a single-level menu.
For complete reference information, see PopUpMenuButton in Adobe Flex Language
Reference. For more information on the Menu control, see “Handling Menu control events”
on page 423. For more information on PopUpButton controls, see “PopUpButton control”
on page 281.
Minimum size 0
You must cast the PopUpMenuButton control’s popUp property to a Menu because the
property type is IUIComponent, not Menu.
You can also use the label property of the PopUpMenuButton control to set the main button
label, as described in “Using the label property” on page 445.
When a popped up menu closes, it loses its selection and related properties.
NOT E
You must use the PopUpMenuButton’s creationComplete event, not the initialize
event to set the main button label from the data provider.
<mx:Script>
<![CDATA[
import mx.controls.Menu
<mx:PopUpMenuButton id="pb2"
dataProvider="{dp2}"
labelField="@label"
showRoot="false"
creationComplete="initData();"/>
</mx:Application>
Because this example uses an E4X XML data source, you must specify the label field using the
E4X @ attribute specifier syntax, and you must tell the control not to show the data provider
root node.
<mx:Script>
<![CDATA[
import mx.events.MenuEvent;
[Bindable]
public var menuData:Array = [
{label: "Inbox", data: "inbox"},
{label: "Calendar", data: "calendar"},
{label: "Sent", data: "sent"},
{label: "Deleted Items", data: "deleted"},
{label: "Spam", data: "spam"}
];
]]>
</mx:Script>
<mx:PopUpMenuButton id="p1"
showRoot="true"
dataProvider="{menuData}"
label="Send to: Inbox"
itemClick="itemClickHandler(event);"/>
</mx:Application>
CHAPTER 13
Contents
List control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .448
HorizontalList control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .458
TileList control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .462
ComboBox control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .466
DataGrid control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475
Tree control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487
447
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
List control
The List control displays a vertical list of items. Its functionality is very similar to that of the
SELECT form element in HTML. It often contains a vertical scroll bar that lets users access the
items in the list. An optional horizontal scroll bar lets users view items when the full width of
the list items is unlikely to fit. The user can select one or more items from the list.
N OTE
The HorizontalList, TileList, DataGrid , Menu , and Tree controls are derived from the
List control or its immediate parent, the ListBase class. As a result, much of the
information for the List control applies to these controls.
For complete reference information, see List in Adobe Flex Language Reference.
The following image shows a List control:
If you specify horizontalScrollPolicy="on", the default width of a List control does not
change; it is still large enough to display the widest visible label. If you set
horizontalScrollPolicy="on" , and specify a List control pixel width, you can use the
measureWidthOfItems() method to ensure that the scroll bar rightmost position
corresponds to the right edge of the content, as the following example shows. Notice that the
additional 5 pixels ensures that the rightmost character of the text displays properly.
<mx:List width="200" id="li2" horizontalScrollPolicy="on"
maxHorizontalScrollPosition="{li2.measureWidthOfItems() - li2.width +
5}">
<mx:List>
<mx:dataProvider>
<mx:String>AK</mx:String>
<mx:String>AL</mx:String>
<mx:String>AR</mx:String>
</mx:dataProvider>
</mx:List>
</mx:Application>
The index of items in the List control is zero-based, which means that values are 0, 1, 2, ... ,
n - 1, where n is the total number of items. The value of the item is its label text.
Most subclasses of ListBase also take a labelFunction property with the signature
described above. For the DataGrid and DataGridColumn controls, the method signature
is: labelFunction(item:Object, dataField:DataGridColumn):String
where item contains the DataGrid item object, and dataField specifies the DataGrid
column.
The following example uses a function to combine the values of the label and data fields for
each item for display in the List control:
<?xml version="1.0"?>
<!-- dpcontrols/ListLabelFunction.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" >
<mx:Script><![CDATA[
public function myLabelFunc(item:Object):String {
return item.data + ", " + item.label;
}
]]></mx:Script>
<mx:ArrayCollection id="myDP">
<mx:source>
<mx:Object label="AL" data="Montgomery"/>
<mx:Object label="AK" data="Juneau"/>
<mx:Object label="AR" data="Little Rock"/>
</mx:source>
</mx:ArrayCollection>
This example uses an ArrayCollection object as the data provider. You should use
collections as the data providers if the data can change dynamically. For more
information, see Chapter 8, “Using Data Providers and Collections,” on page 171.
To use DataTips with a DataGrid control, you must set the showDataTips property on the
individual DataGridColumns of the DataGrid.
The default behavior of the showDataTips property is to display the label text. However, you
can use the dataTipField and dataTipFunction properties to determine what is displayed
in the DataTip. The dataTipField property behaves like the labelField property; it
specifies the name of the field in the data provider to use as the DataTip for cells in the
column. The dataTipFunction property behaves like the labelFunction property; it
specifies the DataTip string to display for list items.
The following example sets the showDataTips property for a List control:
<mx:List id="myList" dataProvider="{myDP}" width="220" height="200"
showDataTips="true"/>
Displaying ScrollTips
You use ScrollTips to give users context about where they are in a list as they scroll through
the list. The tips appear only when you scroll; they don’t appear if you only hover the mouse
over the scroll bar. ScrollTips are useful when live scrolling is disabled (the liveScrolling
property is false) so scrolling does not occur until you release the scroll thumb. The default
value of the showScrollTips property is false.
<mx:List iconField="myIcon">
<mx:dataProvider>
<mx:Array>
<mx:Object label="AL" data="Montgomery" myIcon="iconSymbol1"/>
<mx:Object label="AK" data="Juneau" myIcon="iconSymbol2"/>
<mx:Object label="AR" data="Little Rock" myIcon="iconSymbol1"/>
</mx:Array>
</mx:dataProvider>
</mx:List>
</mx:Application>
In this example, you use the iconField property to specify the field of each item containing
the icon. You use the Embed metadata to import the icons, and then reference them in the List
control definition.
You can also use the iconFunction property to specify a function that determines the icon,
similar to the way that you can use the labelFunction property to specify a function that
determines the label text. The icon function must have the following signature:
iconFunction(item:Object):Class
The item parameter passed in by the Label control contains the list item object. The function
must return the icon class to display in the List control.
list1.dataProvider = myDP;
}
<mx:VBox >
<mx:List id="list1" initialize="initList()" labelField="Artist"
iconFunction="myiconfunction" />
</mx:VBox>
</mx:Application>
Key Action
Up Arrow Moves selection up one item.
Down Arrow Moves selection down one item.
Alphanumeric keys Jumps to the next item with a label that begins with the character typed.
Control Toggle key. Allows for multiple (noncontiguous) selection and
deselection. Works with key presses, click selection, and drag selection.
Shift Contiguous selection key. Allows for contiguous selections. Works with
key presses, click selection, and drag selection.
Minimum size 0
Maximum size 5000 by 5000
For complete reference information, see HorizontalList in Adobe Flex Language Reference.
<mx:Script>
<![CDATA[
private function xmlLoaded():void {
catalogAC = srv.lastResult.catalog;
}
]]>
</mx:Script>
<mx:Model id="catalogAC"/>
<mx:HorizontalList dataProvider="{catalogAC.product}"
width="100%" itemRenderer="Thumbnail"/>
</mx:Application>
Keyboard navigation
The HorizontalList control has the following keyboard navigation features:
Key Action
Page Up Moves selection to the left one page.
Control Toggle key. Allows for multiple (noncontiguous) selection and deselection
when the allowMultipleSelection property is set to true. Works with key
presses, click selection, and drag selection.
TileList control
The TileList control displays a tiled list of items. The items are tiled in vertical columns or
horizontal rows. The TileList control is particularly useful in combination with a custom item
renderer for displaying a list of images and other data. The default item renderer for the
TileList control is TileListItemRenderer, which, by default, displays text of the data provider’s
label field and any icon. For more information about custom item renderers, see Chapter 23,
“Using Item Renderers and Item Editors,” on page 939.
For complete reference information, see TileList in Adobe Flex Language Reference.
For complete reference information, see TileList in Adobe Flex Language Reference.
<mx:TileList dataProvider="{TileListdp}"
itemRenderer="mx.controls.Button"/>
</mx:Application>
In this example, you populate the data provider with an ArrayCollection that contains an
Array of strings defining labels and data values. You then use the itemRenderer property to
specify a Button control as the item renderer. The Button controls display the data provider
label values. The TileList control displays nine Button controls with the specified labels.
<mx:TileList dataProvider="{srv.lastResult.catalog.product}"
height="100%" width="100%" itemRenderer="Thumbnail"
rowHeight="130" columnWidth="175"/>
</mx:Application>
The Thumbnail.mxml MXML component that is used as the item renderer in the product
catalog application is identical to the one in “HorizontalList control” on page 458. For more
information about custom item renderers, see Chapter 23, “Using Item Renderers and Item
Editors,” on page 939.
Key Action
Up Arrow Moves selection up one item. If the control direction is vertical, and the
current item is at the top of a column, moves to the last item in the previous
column; motion stops at the first item in the first column.
Down Arrow Moves selection down one item.If the control direction is vertical, and the
current item is at the bottom of a column, moves to the first item in the next
column; motion stops at the last item in the last column.
Right Arrow Moves selection to the right one item. If the control direction is horizontal,
and the current item is at the end of a row, moves to the first item in the next
row; motion stops at the last item in the last column.
Left Arrow Moves selection to the left one item. If the control direction is horizontal,
and the current item is at the beginning of a row, moves to the last item in
the previous row; motion stops at the first item in the first row.
Page Up Moves selection up one page. For a single-page control, moves the
selection to the beginning of the list.
Page Down Moves selection down one page. For a single-page control, moves the
selection to the end of the list.
Home Moves selection to the beginning of the list.
Control Toggle key. Allows for multiple (noncontiguous) selection and deselection
when allowMultipleSelection is set to true. Works with key presses, click
selection, and drag selection.
ComboBox control
The ComboBox control is a drop-down list from which the user can select a single value. Its
functionality it is very similar to that of the SELECT form element in HTML.
For complete reference information, see ComboBox in Adobe Flex Language Reference.
In its editable state, the user can type text directly into the top of the list, or select one of the
preset values from the list. In its noneditable state, as the user types a letter, the drop-down list
opens and scrolls to the value that most closely matches the one being entered; matching is
only performed on the first letter that the user types.
If the drop-down list hits the lower boundary of the application, it opens upward. If a list item
is too long to fit in the horizontal display area, it is truncated to fit. If there are too many
items to display in the drop-down list, a vertical scroll bar appears.
The ComboBox control has the following default sizing properties:
Minimum size 0
■ If the user closes the drop-down list using a mouse click, Enter key, or Control+Up key,
and the selected item is different from the previously selected item.
■ If the drop-down list is currently closed, and the user presses the Up, Down, Page Up, or
Page Down key to select a new item.
■ If the ComboBox control is editable, and the user types into the control, Flex broadcasts a
change event each time the text field of the control changes.
You can also specify the ComboBox labels using a label function, as described in Using a
label function on page 450.
<mx:Script>
<![CDATA[
import mx.collections.*
private var COLOR_ARRAY:Array=
[{label:"Red", data:"#FF0000"},
{label:"Green", data:"#00FF00"},
{label:"Blue", data:"#0000FF"}];
// Declare an ArrayCollection variable for the colors.
// Make it Bindable so it can be used in bind
// expressions ({colorAC}).
[Bindable]
public var colorAC:ArrayCollection;
<mx:ComboBox dataProvider="{colorAC}"/>
<mx:ComboBox dataProvider="{stateAC}"/>
</mx:Application>
This example uses a simple model. However, you can populate the model from an external
data source or define a custom data model class in ActionScript. For more information on
using data models, see Chapter 43, “Storing Data,” on page 1517.
You can use remote data providers to supply data to your ComboBox control. For example,
when a web service operation returns an Array of strings, you can use the following format to
display each string as a row of a ComboBox control:
<mx:ArrayCollection id=”resultAC”
source=”mx.utils.ArrayUtil.toArray(service.operation.lastResult);”
<mx:ComboBox dataProvider="{resultAC}" />
For more information on using remote data providers, see “Using remote data providers”
on page 223.
Key Description
Control+Down Opens the drop-down list and gives it focus.
Page Down Displays the item that would be at the end bottom of the drop-down list.
If the current selection is a multiple of the rowCount value, displays the
item that rowCount -1 down the list, or the last item. If the current
selection is the last item in the data provider, does nothing,.
Page Up Displays the item that would be at the top of the drop-down. If the
current selection is a multiple of the rowCount value, displays the item
that rowCount -1 up the list, or the first item. If the current selection is the
first item in the data provider, does nothing,
Up Moves the selection up one item.
When the drop-down list of a non-editable ComboBox control has focus, alphanumeric
keystrokes move the selection up and down the drop-down list to the next item with the same
first character. You can also use the following keys to control a drop-down list when it is open:
Key Description
Control+Up Closes the drop-down list and returns focus to the ComboBox control.
Enter Closes the drop-down list and returns focus to the ComboBox control.
Escape Closes the drop-down list and returns focus to the ComboBox control.
Page Down Moves to the bottom of the visible list. If the current selection is at the
bottom of the list, moves the current selection to the top of the displayed
list and displays the next rowCount-1 items, if any. If there current selection
is the last item in the data provider, does nothing,.
Shift+Tab Closes the drop-down list and moves the focus to the previous object in the
DisplayList.
Tab Closes the drop-down list and moves the focus to the next object in the
DisplayList.
DataGrid control
The DataGrid control is a list that can display more than one column of data. It is a formatted
table of data that lets you set editable table cells, and is the foundation of many data-driven
applications.
This topic describes how to create and use DataGrid controls, including how to sort the data.
It does not cover information on the following topics, which are often important for creating
advanced data grid controls:
■ How to format the information in each DataGrid cell and control how users enter data in
the cells; for information on these topics, see Chapter 23, “Using Item Renderers and Item
Editors,” on page 939.
■ How to drag objects to and from the data grid; for information on this topic, see Chapter
31, “Using Drag and Drop,” on page 1195.
For complete reference information, see DataGrid in Adobe Flex Language Reference.
Rows are responsible for rendering items. Each row is laid out vertically below the previous
one. Columns are responsible for maintaining the state of each visual column; columns
control width, color, and size.
The DataGrid control has the following default sizing properties:
Minimum size 0
Specifying columns
Each column in a DataGrid control is represented by a DataGridColumn object. You use the
columns property of the DataGrid control and the <mx:DataGridColumn> tag to select the
DataGrid columns, specify the order in which to display them, and set additional properties.
You can also use the DataGridColumn class visible property to hide and redisplay columns,
as described in “Hiding and displaying columns” on page 479.
For complete reference information for the <mx:DataGridColumn> tag, see DataGridColumn
in Adobe Flex Language Reference.
You specify an Array element to the <mx:columns> child tag of the <mx:DataGrid> tag, as the
following example shows:
<?xml version="1.0"?>
<!-- dpcontrols/DataGridSpecifyColumns.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" >
<mx:DataGrid>
<mx:ArrayCollection>
<mx:Object Artist="Pavement" Price="11.99"
Album="Slanted and Enchanted" />
<mx:Object Artist="Pavement"
Album="Brighten the Corners" Price="11.99" />
</mx:ArrayCollection>
<mx:columns>
<mx:DataGridColumn dataField="Album" />
<mx:DataGridColumn dataField="Price" />
</mx:columns>
</mx:DataGrid>
</mx:Application>
In this example, you only display the Album and Price columns in the DataGrid control. You
can reorder the columns as well, as the following example shows:
<mx:columns>
<mx:DataGridColumn dataField="Price" />
<mx:DataGridColumn dataField="Album" />
</mx:columns>
In this example, you specify that the Price column is the first column in the DataGrid control,
and that the Album column is the second.
[Bindable]
public var initDG:ArrayCollection;
//Initialize initDG ArrayCollection variable from the Array.
//You can use this technique to convert an HTTPService,
//WebService, or RemoteObject result to ArrayCollection.
public function initData():void {
initDG=new ArrayCollection(DGArray);
}
]]>
</mx:Script>
</mx:Application>
In this example, you use the event handler to display the column index, row index, and event
type in three TextArea controls.
The index of columns in the DataGrid control is zero-based, meaning values are 0, 1, 2, ... ,
n - 1, where n is the total number of columns. Row items are also indexed starting at 0.
Therefore, if you select the first item in the second row, this example displays 0 in the
TextArea for the column index, and 1 in the TextArea for the row index.
The currentTarget property of the object passed to the event handler contains a reference to
the DataGrid control. You can reference any control property using currentTarget followed
by a period and the property name. The currentTarget.selectedItem field contains the
selected item.
The following example shows how to use the headerRelease event handler to do multi-column
sorting when a user clicks a DataGrid column header.
<mx:Script>
<![CDATA[
import mx.events.DataGridEvent;
import mx.collections.*;
Key Action
Enter When a cell is in editing state, commits change, and moves editing to the cell
Return on the same column, next row down or up, depending on whether Shift is
Shift+Enter pressed.
Tab Moves focus to the next editable cell, traversing the cells in row order. If at the
end of the last row, advances to the next element in the parent container that
can receive focus.
Shift+Tab Moves focus to the previous editable cell. If at the beginning of a row,
advances to the end of the previous row. If at the beginning of the first row,
advances to the previous element in the parent container that can receive
focus.
Up Arrow If editing a cell, shifts the cursor to the beginning of the cell’s text. If the cell is
Home not editable, moves selection up one item.
Page Up
Down Arrow If editing a cell, shifts the cursor to the end of the cell’s text. If the cell is not
End editable, moves selection down one item.
Page Down
Control Toggle key. If you set the DataGrid control allowMultipleSelection property
to true, allows for multiple (noncontiguous) selection and deselection. Works
with key presses, click selection, and drag selection.
Shift Contiguous select key. If you set the DataGrid control allowMultipleSelection
property to true, allows for contiguous selections. Works with key presses,
click selection, and drag selection.
Tree control
The Tree control lets a user view hierarchical data arranged as an expandable tree.
For complete reference information, see Tree in Adobe Flex Language Reference. For
information on hierarchical data providers, see “Using hierarchical data providers”
on page 207.
This topic describes how to create and use Tree controls. It does not cover information on the
following topics, which are often important for using advanced Tree controls:
■ How to format the information in each Tree node and control how users enter data in the
nodes; for information on these topics, see Chapter 23, “Using Item Renderers and Item
Editors,” on page 939.
The Tree control openItems property is an Array containing all expanded tree nodes. The
following line in the example code displays the label of the first (and only) open item in the
tree:
forOpen.text=XMLTree1.openItems[0].@label;
In this example, however, you could also get the openItems box to indicate the initial open
item by setting the expandItem() method to dispatch an itemOpen event. You can do this by
specifying the fourth, optional parameter of the expandItem() method to true. The true
fourth parameter causes the tree to dispatch an open event when the item opens. The
following example shows the use of the fourth parameter:
XMLTree1.expandItem(MailBox.getItemAt(0), true, false, true);
You can programmatically walk down a Tree control’s nodes and open a node without
knowing what depth you are at in the Tree’s data provider. One way to do this is by testing if a
child nodes exist with the children() method of a node’s XML object. If the node exists, you
can use the expandItem() method to open the node.
[Bindable]
private var treeData:XML =
<root>
<node label="Monkeys">
<node label="South America">
<node label="Coastal"/>
<node label="Inland"/>
</node>
<node label="Africa" isBranch="true"/>
<node label="Asia" isBranch="true"/>
</node>
<node label="Sharks">
<node label="South America" isBranch="true"/>
<node label="Africa" isBranch="true"/>
<node label="Asia" >
<node label="Coastal"/>
<node label="Inland"/>
</node>
</node>
</root>;
<mx:Tree id="myTree"
y="88"
width="221"
height="257"
horizontalCenter="0"
dataProvider="{treeData.node}"
labelField="@label"
/>
</mx:Application>
<mx:Script>
<![CDATA[
[Bindable]
[Embed(source="assets/radioIcon.jpg")]
public var iconSymbol1:Class;
[Bindable]
[Embed(source="assets/topIcon.jpg")]
public var iconSymbol2:Class;
]]>
</mx:Script>
<mx:Script>
<![CDATA[
[Bindable]
[Embed(source="assets/radioIcon.jpg")]
public var iconSymbol1:Class;
[Bindable]
[Embed(source="assets/topIcon.jpg")]
public var iconSymbol2:Class;
Event Description
itemEditBegin Dispatched when the editedItemPosition property has been set and the
cell can be edited.
itemEditEnd Dispatched when cell editing session ends for any reason.
itemFocusIn Dispatched when tree node gets the focus: when a user selects the
label or tabs to it.
itemFocusOut Dispatched when a label loses focus.
itemClick Dispatched when a user clicks on an item in the control.
These events are commonly used in custom item editors. For more information see Chapter
23, “Using Item Renderers and Item Editors,” on page 939.
Key Description
Down Arrow Moves the caret to the end of the label.
Page Down
End
Enter Ends editing and moves selection to next visible node, which can then be
edited. At the last node, selects the label.
Shift Enter Ends editing and moves selection to previous visible node, which can
then be edited. At the first node, selects the label.
Escape Cancels the edit, restores the text, and changes the row state from editing
to selected.
TAB When in editing mode, accepts the current changes, selects the row
below, and goes into editing mode with the label text selected. If at the last
element in the tree or not in editing mode, sends focus to the next control.
Shift-TAB When in editing mode, accepts the current changes, selects the row
above, and goes into editing mode. If at the first element in the tree or not
in editing mode, sends focus to the previous control.
Key Description
Down Arrow Moves the selection down one. When the Tree control gets focus, use the
Down arrow to move focus to the first node.
Right Arrow Opens a selected branch node. If a branch is already open, moves to the
first child node.
Left Arrow Closes a selected branch node. If a leaf node or a closed branch node is
currently selected, selects the parent node.
Control + Arrow Move focus, but does not select a node. Use the Spacebar to select a
keys node.
For information on using keys to edit tree labels, see “Using the keyboard to edit labels”
on page 499.
CHAPTER 14
Contents
About the AdvancedDataGrid control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502
Sorting by multiple columns. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504
Styling rows and columns. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 506
Selecting multiple cells and rows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513
Hierarchical and grouped data display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517
Displaying hierarchical data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .525
Displaying grouped data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 529
Creating column groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544
Using item renderers with the AdvancedDataGrid control . . . . . . . . . . . . . . . . . . . 550
Keyboard navigation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 560
501
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
About the AdvancedDataGrid control
The AdvancedDataGrid control extends the capabilities of the standard DataGrid control to
improve data visualization. The following table describes the main data visualization
capabilities of the AdvancedDataGrid control:
Capability Description
Sorting on multiple Sort by multiple columns by holding down the Control key when you
columns click in the column header. For more information, see “Sorting by
multiple columns” on page 504.
Styling rows and Use the styleFunction property to specify a function to apply styles
columns to rows and columns of the control. For more information, see
“Styling rows and columns” on page 506.
Displaying hierarchical Use an expandable navigation tree in the first column of the control
data to control the visible rows of the control. For more information, see
“Hierarchical and grouped data display” on page 517.
Creating column groups Collect multiple columns under a single column heading. For more
information, see “Creating column groups” on page 544.
Using item renderers Span multiple columns with an item renderer and use multiple item
renderers in the same column. For more information, see “Using
item renderers with the AdvancedDataGrid control” on page 550.
The following image shows an AdvancedDataGrid control with a navigation tree in the first
column that controls the visible rows of the control:
Navigation tree
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "SimpleFlatData.as";
]]>
</mx:Script>
<mx:AdvancedDataGrid id="myADG"
dataProvider="{dpFlat}"
width="100%" height="100%">
<mx:groupedColumns>
<mx:AdvancedDataGridColumn dataField="Region"/>
<mx:AdvancedDataGridColumn dataField="Territory"/>
<mx:AdvancedDataGridColumn dataField="Territory_Rep"
headerText="Territory Rep"/>
<mx:AdvancedDataGridColumnGroup headerText="Revenues">
<mx:AdvancedDataGridColumn dataField="Actual"/>
<mx:AdvancedDataGridColumn dataField="Estimate"/>
</mx:AdvancedDataGridColumnGroup>
</mx:groupedColumns>
</mx:AdvancedDataGrid>
</mx:Application>
Column headers
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var dpADG:ArrayCollection = new ArrayCollection([
{Artist:'Pavement', Album:'Slanted and Enchanted', Price:11.99},
{Artist:'Pavement', Album:'Brighten the Corners', Price:11.99},
{Artist:'Saner', Album:'A Child Once', Price:11.99},
{Artist:'Saner', Album:'Helium Wings', Price:12.99},
{Artist:'The Doors', Album:'The Doors', Price:10.99},
{Artist:'The Doors', Album:'Morrison Hotel', Price:12.99},
{Artist:'Grateful Dead', Album:'American Beauty', Price:11.99},
{Artist:'Grateful Dead', Album:'In the Dark', Price:11.99},
{Artist:'Grateful Dead', Album:'Shakedown Street', Price:11.99},
{Artist:'The Doors', Album:'Strange Days', Price:12.99},
{Artist:'The Doors', Album:'The Best of the Doors', Price:10.99}
]);
]]>
</mx:Script>
The function returns either an Object that contains a styleName:value pair to specify a style
setting, or null. The styleName field contains the name of a style property, such as color, and
the value field contains the value for the style property, such as 0x00FF00.
The AdvancedDataGrid control invokes the callback function when it updates its display,
such as when the control is first drawn on application start up, or when you call the
invalidateList() method to refresh the display of all rows in the control.
The examples in this section use callback functions to set the style of an AdvancedDataGrid
control. All of the examples in this section use the following data from the file StyleData.as:
[Bindable]
private var dpADG:ArrayCollection = new ArrayCollection([
{Artist:'Pavement', Album:'Slanted and Enchanted', Price:11.99},
{Artist:'Pavement', Album:'Brighten the Corners', Price:11.99},
{Artist:'Saner', Album:'A Child Once', Price:11.99},
{Artist:'Saner', Album:'Helium Wings', Price:12.99},
{Artist:'The Doors', Album:'The Doors', Price:10.99},
{Artist:'The Doors', Album:'Morrison Hotel', Price:12.99},
{Artist:'Grateful Dead', Album:'American Beauty', Price:11.99},
{Artist:'Grateful Dead', Album:'In the Dark', Price:11.99},
{Artist:'Grateful Dead', Album:'Shakedown Street', Price:11.99},
{Artist:'The Doors', Album:'Strange Days', Price:12.99},
{Artist:'The Doors', Album:'The Best of the Doors', Price:10.99}
]);
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn;
<mx:AdvancedDataGrid id="myADG"
width="100%" height="100%"
dataProvider="{dpADG}"
styleFunction="myStyleFunc">
<mx:columns>
<mx:HBox>
<mx:Button label="Pavement" click="setArtistName(event);"/>
<mx:Button label="Saner" click="setArtistName(event);"/>
<mx:Button label="The Doors" click="setArtistName(event);"/>
</mx:HBox>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn;
return null;
}
]]>
</mx:Script>
<mx:AdvancedDataGrid id="myADG"
width="100%" height="100%"
dataProvider="{dpADG}"
styleFunction="myStyleFunc">
<mx:columns>
<mx:AdvancedDataGridColumn dataField="Artist"/>
<mx:AdvancedDataGridColumn dataField="Album"/>
<mx:AdvancedDataGridColumn dataField="Price"
styleFunction="myColStyleFunc"/>
</mx:columns>
</mx:AdvancedDataGrid>
<mx:HBox>
<mx:Button label="Pavement" click="setArtistName(event);"/>
<mx:Button label="Saner" click="setArtistName(event);"/>
<mx:Button label="The Doors" click="setArtistName(event);"/>
</mx:HBox>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn;
<mx:AdvancedDataGrid id="myADG"
width="100%" height="100%"
dataProvider="{dpADG}"
styleFunction="myStyleFunc">
<mx:columns>
<mx:AdvancedDataGridColumn dataField="Artist"/>
<mx:AdvancedDataGridColumn dataField="Album"/>
<mx:AdvancedDataGridColumn width="75" dataField="Price">
<mx:formatter>
<mx:HBox>
<mx:Button label="Pavement" click="setArtistName(event);"/>
<mx:Button label="Saner" click="setArtistName(event);"/>
<mx:Button label="The Doors" click="setArtistName(event);"/>
</mx:HBox>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import flash.events.KeyboardEvent;
import flash.system.System;
include "StyleData.as"
<mx:TextArea id="myTA"/>
</mx:Application>
The code for this example is in the section “Controlling the navigation tree” on page 521.
The code for this example is in the section “Displaying grouped data” on page 529.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "SimpleHierarchicalData.as";
]]>
</mx:Script>
Notice that the leaf icon for the tree does not show a label. This is because the individual
records for each territory representative do not contain a Region field. The next section
describes how to control the icons displayed by the navigation tree.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "SimpleHierarchicalData.as";
]]>
</mx:Script>
This example does not associate a data field with the column that contains the tree, so the tree
icons appear with no label. This example also sets the folderClosedIcon, folderOpenIcon,
and defaultLeafIcon properties to null, but the disclosure icons do display so that the user
can still open and close tree nodes.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "SimpleHierarchicalData.as";
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "HierarchicalDataCategories.as";
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.collections.HierarchicalData;
import mx.collections.XMLListCollection;
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "SimpleFlatData.as"
]]>
</mx:Script>
<mx:AdvancedDataGrid id="myADG"
width="100%" height="100%"
initialize="gc.refresh();">
<mx:dataProvider>
<mx:GroupingCollection id="gc" source="{dpFlat}">
<mx:grouping>
<mx:Grouping>
<mx:GroupingField name="Region"/>
<mx:GroupingField name="Territory"/>
</mx:Grouping>
</mx:grouping>
</mx:GroupingCollection>
</mx:dataProvider>
<mx:columns>
<mx:AdvancedDataGridColumn dataField="Region"/>
<mx:AdvancedDataGridColumn dataField="Territory"/>
<mx:AdvancedDataGridColumn dataField="Territory_Rep"
headerText="Territory Rep"/>
<mx:AdvancedDataGridColumn dataField="Actual"/>
<mx:AdvancedDataGridColumn dataField="Estimate"/>
</mx:columns>
</mx:AdvancedDataGrid>
</mx:Application>
The previous example specifies two fields used to group the data: Region and Territory.
The AdvancedDataGrid control uses the GroupLabel field to define the labels for the branch
nodes of the navigation tree. The first column of the AdvancedDataGrid control is also
associated with the Region field, so the navigation tree uses the Region field to define the
labels for the leaf nodes of the tree.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "SimpleFlatData.as"
]]>
</mx:Script>
<mx:AdvancedDataGrid id="myADG"
width="100%" height="100%"
initialize="gc.refresh();">
<mx:dataProvider>
<mx:GroupingCollection id="gc" source="{dpFlat}">
<mx:Grouping>
<mx:GroupingField name="Region"/>
<mx:GroupingField name="Territory"/>
</mx:Grouping>
</mx:GroupingCollection>
</mx:dataProvider>
<mx:columns>
<mx:AdvancedDataGridColumn dataField="Region"/>
<mx:AdvancedDataGridColumn dataField="Territory"/>
<mx:AdvancedDataGridColumn dataField="Territory_Rep"
headerText="Territory Rep"/>
<mx:AdvancedDataGridColumn dataField="Actual"/>
<mx:AdvancedDataGridColumn dataField="Estimate"/>
</mx:columns>
</mx:AdvancedDataGrid>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "SimpleFlatData.as";
]]>
</mx:Script>
<mx:AdvancedDataGrid id="myADG"
width="100%" height="100%"
defaultLeafIcon="{null}"
initialize="gc.refresh();">
<mx:dataProvider>
<mx:GroupingCollection id="gc" source="{dpFlat}">
<mx:Grouping>
<mx:GroupingField name="Region"/>
<mx:GroupingField name="Territory"/>
</mx:Grouping>
</mx:GroupingCollection>
</mx:dataProvider>
<mx:columns>
<mx:AdvancedDataGridColumn dataField="GroupLabel"
headerText="Region/Territory"/>
<mx:AdvancedDataGridColumn dataField="Territory_Rep"
headerText="Territory Rep"/>
<mx:AdvancedDataGridColumn dataField="Actual"/>
<mx:AdvancedDataGridColumn dataField="Estimate"/>
</mx:columns>
</mx:AdvancedDataGrid>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.collections.GroupingField;
import mx.collections.Grouping;
import mx.collections.GroupingCollection;
import mx.collections.ArrayCollection;
include "SimpleFlatData.as";
[Bindable]
public var myGColl:GroupingCollection = new GroupingCollection();
<mx:AdvancedDataGrid id="myADG"
width="100%" height="100%"
The Min Actual and Max Actual fields in the top row correspond to summaries for all rows in
the group, and the Min Actual and Max Actual fields for each Territory correspond to
summaries for all rows in the territory subgroup.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "SimpleFlatData.as"
]]>
</mx:Script>
<mx:AdvancedDataGrid id="myADG"
width="100%" height="100%"
initialize="gc.refresh();">
<mx:dataProvider>
<mx:GroupingCollection id="gc" source="{dpFlat}">
<mx:Grouping>
<mx:GroupingField name="Region">
<mx:summaries>
<mx:SummaryRow summaryPlacement="group">
<mx:fields>
<mx:SummaryField dataField="Actual"
label="Min Actual" operation="MIN"/>
<mx:SummaryField dataField="Actual"
label="Max Actual" operation="MAX"/>
</mx:fields>
</mx:SummaryRow>
</mx:summaries>
</mx:GroupingField>
<mx:GroupingField name="Territory">
<mx:summaries>
<mx:SummaryRow summaryPlacement="group">
<mx:fields>
<mx:SummaryField dataField="Actual"
label="Min Actual" operation="MIN"/>
<mx:SummaryField dataField="Actual"
label="Max Actual" operation="MAX"/>
</mx:fields>
</mx:SummaryRow>
</mx:summaries>
</mx:GroupingField>
</mx:Grouping>
</mx:GroupingCollection>
</mx:dataProvider>
<mx:columns>
<mx:AdvancedDataGridColumn dataField="Region"/>
<mx:AdvancedDataGridColumn dataField="Territory_Rep"
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "SimpleFlatData.as"
]]>
</mx:Script>
<mx:AdvancedDataGrid id="myADG"
width="100%" height="100%"
initialize="gc.refresh();">
<mx:dataProvider>
<mx:GroupingCollection id="gc" source="{dpFlat}">
<mx:Grouping>
<mx:GroupingField name="Region">
<mx:SummaryRow summaryPlacement="group">
<mx:SummaryField operation="MIN"
dataField="Actual" label="Min Actual"/>
<mx:SummaryField operation="MAX"
dataField="Actual" label="Max Actual"/>
</mx:SummaryRow>
</mx:GroupingField>
<mx:GroupingField name="Territory">
<mx:SummaryRow summaryPlacement="group">
<mx:SummaryField operation="MIN"
dataField="Actual" label="Min Actual"/>
<mx:SummaryField operation="MAX"
dataField="Actual" label="Max Actual"/>
</mx:SummaryRow>
</mx:GroupingField>
</mx:Grouping>
</mx:GroupingCollection>
</mx:dataProvider>
<mx:columns>
<mx:AdvancedDataGridColumn dataField="Region"/>
<mx:AdvancedDataGridColumn dataField="Territory_Rep"
You can specify multiple values to the summaryPlacement property, separated by a space, for
example, a value of last group specifies to show the summary at the group level and as the
last row of the group.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "SimpleFlatData.as"
]]>
</mx:Script>
<mx:AdvancedDataGrid id="myADG"
width="100%" height="100%"
initialize="gc.refresh();">
<mx:dataProvider>
<mx:GroupingCollection id="gc" source="{dpFlat}">
<mx:Grouping>
<mx:GroupingField name="Region">
<mx:SummaryRow summaryPlacement="group">
<mx:SummaryField operation="MIN"
dataField="Actual" label="Min Actual"/>
<mx:SummaryField operation="MAX"
dataField="Actual" label="Max Actual"/>
</mx:SummaryRow>
<mx:SummaryRow summaryPlacement="group">
<mx:SummaryField operation="MIN"
dataField="Estimate" label="Min Estimate"/>
<mx:SummaryField operation="MAX"
dataField="Estimate" label="Max Estimate"/>
</mx:SummaryRow>
</mx:GroupingField>
<mx:GroupingField name="Territory"/>
</mx:Grouping>
</mx:GroupingCollection>
</mx:dataProvider>
<mx:columns>
<mx:AdvancedDataGridColumn dataField="Region"/>
<mx:AdvancedDataGridColumn dataField="Territory_Rep"
headerText="Territory Rep"/>
<mx:AdvancedDataGridColumn dataField="Actual"/>
<mx:AdvancedDataGridColumn dataField="Estimate"/>
<mx:AdvancedDataGridColumn dataField="Min Actual"/>
In this example, you use flat data to populate the data grid, and group the Actual and
Estimate columns under a single column named Revenues.
To group columns in an AdvancedDataGrid control, you must do the following:
■ Use the AdvancedDataGrid.groupedColumns property, rather than the
AdvancedDataGrid.columns property, to specify the columns.
■ Use the AdvancedDataGridColumnGroup class to specify the column groups.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "SimpleFlatData.as";
]]>
</mx:Script>
<mx:AdvancedDataGrid id="myADG"
dataProvider="{dpFlat}"
width="100%" height="100%">
<mx:groupedColumns>
<mx:AdvancedDataGridColumn dataField="Region"/>
<mx:AdvancedDataGridColumn dataField="Territory"/>
<mx:AdvancedDataGridColumn dataField="Territory_Rep"
headerText="Territory Rep"/>
<mx:AdvancedDataGridColumnGroup headerText="Revenues">
<mx:AdvancedDataGridColumn dataField="Actual"/>
<mx:AdvancedDataGridColumn dataField="Estimate"/>
</mx:AdvancedDataGridColumnGroup>
</mx:groupedColumns>
</mx:AdvancedDataGrid>
</mx:Application>
The groupedColumns property contains instances of the AdvancedDataGridColumn class
and of the AdvancedDataGridColumnGroup class. Instances of the
AdvancedDataGridColumn class appear in the control as stand-alone columns. All the
columns specified in an AdvancedDataGridColumnGroup instance appear together as a
grouped column.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "SimpleFlatData.as";
]]>
</mx:Script>
<mx:AdvancedDataGrid id="myADG"
dataProvider="{dpFlat}"
width="100%" height="100%">
<mx:groupedColumns>
<mx:AdvancedDataGridColumn dataField="Territory_Rep"
headerText="Territory Rep"/>
<mx:AdvancedDataGridColumnGroup headerText="Area">
<mx:AdvancedDataGridColumn dataField="Region"/>
<mx:AdvancedDataGridColumn dataField="Territory"/>
</mx:AdvancedDataGridColumnGroup>
<mx:AdvancedDataGridColumnGroup headerText="Revenues">
<mx:AdvancedDataGridColumn dataField="Actual"/>
<mx:AdvancedDataGridColumn dataField="Estimate"/>
</mx:AdvancedDataGridColumnGroup>
</mx:groupedColumns>
</mx:AdvancedDataGrid>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "SimpleFlatData.as";
]]>
</mx:Script>
<mx:AdvancedDataGrid id="myADG"
dataProvider="{dpFlat}"
width="100%" height="100%">
<mx:groupedColumns>
<mx:AdvancedDataGridColumn dataField="Territory_Rep"
headerText="Territory Rep"/>
<mx:AdvancedDataGridColumnGroup headerText="All Groups">
<mx:AdvancedDataGridColumnGroup headerText="Area">
<mx:AdvancedDataGridColumn dataField="Region"/>
<mx:AdvancedDataGridColumn dataField="Territory"/>
</mx:AdvancedDataGridColumnGroup>
<mx:AdvancedDataGridColumnGroup headerText="Revenues">
<mx:AdvancedDataGridColumn dataField="Actual"/>
<mx:AdvancedDataGridColumn dataField="Estimate"/>
</mx:AdvancedDataGridColumnGroup>
</mx:AdvancedDataGridColumnGroup>
</mx:groupedColumns>
</mx:AdvancedDataGrid>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "SimpleHierarchicalData.as";
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "HierarchicalDataForGroupedColumns.as";
]]>
</mx:Script>
<mx:AdvancedDataGrid id="myADG"
width="100%" height="100%"
defaultLeafIcon="{null}">
<mx:dataProvider>
<mx:HierarchicalData source="{dpHierarchy}"/>
</mx:dataProvider>
<mx:groupedColumns>
<mx:AdvancedDataGridColumn dataField="Region"/>
<mx:AdvancedDataGridColumn dataField="Territory"/>
<mx:AdvancedDataGridColumn dataField="Territory_Rep"
headerText="Territory Rep"/>
<mx:AdvancedDataGridColumnGroup dataField="Revenues">
<mx:AdvancedDataGridColumn dataField="Actual"/>
<mx:AdvancedDataGridColumn dataField="Estimate"/>
</mx:AdvancedDataGridColumnGroup>
</mx:groupedColumns>
</mx:AdvancedDataGrid>
</mx:Application>
These new capabilities support item renderers only; use item editors as you do with the
DataGrid control.
<mx:rendererProviders>
<mx:AdvancedDataGridRendererProvider
columnIndex="3"
columnSpan="1"
renderer="myComponents.EstimateRenderer"/>
</mx:rendererProviders>
</mx:AdvancedDataGrid>
<mx:rendererProviders>
<mx:AdvancedDataGridRendererProvider
column="{estCol}"
columnSpan="1"
renderer="myComponents.EstimateRenderer"/>
</mx:rendererProviders>
</mx:AdvancedDataGrid>
The depth property lets you associate the renderer with a specific level in the hierarchy of the
navigation tree of an AdvancedDataGrid control, where the depth of the top-most node in the
navigation tree is 1. The following example associates the renderer with the third level of a
navigation tree:
<mx:rendererProviders>
<mx:AdvancedDataGridRendererProvider
columnIndex="3"
depth="3"
columnSpan="1"
renderer="myComponents.EstimateRenderer"/>
</mx:rendererProviders>
In the previous example, the AdvancedDataGrid control uses the default renderer for the
column until you expand it to the third level of the navigation tree, and then it uses
EstimateRenderer component. You use the depth property to assign different renderers to the
same column, where the depth property specifies the renderer to use for each level of the tree.
A renderer can span multiple columns. In the following example, you create a renderer that
spans two columns:
<mx:AdvancedDataGrid>
<mx:columns>
<mx:AdvancedDataGridColumn dataField="Region"/>
<mx:AdvancedDataGridColumn dataField="Territory_Rep"
headerText="Territory Rep"/>
<mx:AdvancedDataGridColumn id="actCol" dataField="Actual"/>
<mx:AdvancedDataGridColumn dataField="Estimate"/>
</mx:columns>
<mx:rendererProviders>
<mx:AdvancedDataGridRendererProvider
column="{actCol}"
depth="3"
columnSpan="2"
The previous example uses a single renderer that spans the Actual and Estimate columns to
display a combined view of the data for these columns. For an implementation of the
SummaryRenderer component, see “Using a renderer to generate column data” on page 554.
The following table describes the properties of the AdvancedDataGridRendererProvider class
that you use to configure the renderer:
Property Description
column The ID of the column for which the renderer is used. If you omit this property,
you can use the columnIndex property to specify the column.
columnIndex The column index for which the renderer is used, where the first column has an
index of 0.
columnSpan The number of columns that the renderer spans. Set this property to 0 to span
all columns. The default value is 1.
dataField The data field in the data provider for the renderer. This property is optional.
depth The depth in the tree at which the renderer is used, where the top-most node
of the tree has a depth of 1. Use this property when the renderer should be
used only when the tree is expanded to a certain depth, not for all nodes in the
tree. By default, the control uses the renderer for all levels of the tree.
renderer The renderer.
rowSpan The number of rows that the renderer spans. The default value is 1.
This example defines a column with the id of diffCol that is not associated with a data field in
the data provider. Instead, you use the rendererProvider property to assign an item
renderer to the column. The item renderer calculates the difference between the actual and
estimate values, and then displays a message based on whether the representative exceeded or
missed their estimate.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
include "SimpleHierarchicalData.as";
]]>
</mx:Script>
<mx:rendererProviders>
<mx:AdvancedDataGridRendererProvider column="{diffCol}"
depth="3" renderer="myComponents.SummaryRenderer"/>
</mx:rendererProviders>
</mx:AdvancedDataGrid>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var dpHierarchy:ArrayCollection= new ArrayCollection([
{name:"Barbara Jennings", region: "Arizona", total:70, children:[
{detail:[{amount:5},{amount:10},{amount:20},{amount:45}]}]},
{name:"Dana Binn", region: "Arizona", total:130, children:[
{detail:[{amount:15},{amount:25},{amount:35},{amount:55}]}]},
{name:"Joe Smith", region: "California", total:229, children:[
{detail:[{amount:26},{amount:32},{amount:73},{amount:123}]}]},
{name:"Alice Treu", region: "California", total:230, children:[
{detail:[{amount:159},{amount:235},{amount:135},{amount:155}]}
]}
]);
]]>
</mx:Script>
<mx:AdvancedDataGrid id="myADG"
width="100%" height="100%"
variableRowHeight="true">
<mx:dataProvider>
<mx:HierarchicalData source="{dpHierarchy}"/>
</mx:dataProvider>
<mx:columns>
<mx:AdvancedDataGridColumn dataField="name" headerText="Name"/>
<mx:AdvancedDataGridColumn dataField="total" headerText="Total"/>
</mx:columns>
<mx:rendererProviders>
<mx:AdvancedDataGridRendererProvider
dataField="detail"
renderer="myComponents.ChartRenderer"
columnIndex="0"
columnSpan="0"/>
</mx:rendererProviders>
</mx:AdvancedDataGrid>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var dpHierarchy:ArrayCollection= new ArrayCollection([
{name:"Barbara Jennings", region: "Arizona", total:70, children:[
{detail:[{amount:5},{amount:10},{amount:20},{amount:45}]}]},
{name:"Dana Binn", region: "Arizona", total:130, children:[
{detail:[{amount:15},{amount:25},{amount:35},{amount:55}]}]},
{name:"Joe Smith", region: "California", total:229, children:[
{detail:[{amount:26},{amount:32},{amount:73},{amount:123}]}]},
{name:"Alice Treu", region: "California", total:230, children:[
{detail:[{amount:159},{amount:235},{amount:135},{amount:155}]}
]}
]);
]]>
</mx:Script>
<mx:AdvancedDataGrid id="myADG"
width="100%" height="100%"
variableRowHeight="true">
<mx:dataProvider>
<mx:HierarchicalData source="{dpHierarchy}"/>
</mx:dataProvider>
<mx:columns>
<mx:AdvancedDataGridColumn dataField="name" headerText="Name"/>
<mx:AdvancedDataGridColumn dataField="total" headerText="Total"/>
<mx:AdvancedDataGridColumn dataField="detail" headerText="Detail"/>
</mx:columns>
<mx:rendererProviders>
<mx:AdvancedDataGridRendererProvider
dataField="detail"
renderer="myComponents.ChartRenderer"
columnIndex="2"/>
</mx:rendererProviders>
</mx:AdvancedDataGrid>
</mx:Application>
In editable mode • Use the Tab and Shift+Tab keys to move to the next and
previous cells, and start editing.
• Use the Escape or Control+Period keys to cancel editing.
• Use the Enter key based on the value of the
AdvancedDataGridColumn.editorUsesEnterKey property:
• If editorUsesEnterKey=true, the Enter key is considered to
be part of the input text.
• If editorUsesEnterKey=false, if single-line editor, the Enter
key saves the item and moves down a row.
• If you use the Tab key to move focus to the
AdvancedDataGrid control, focus is placed on the last edited
item position.
• Use the Control+Click keys to select multiple discontiguous
items.
For the expandable tree • Use the Multiply key on the number pad (asterisk) to open or
close all nodes under the current node, with no animation.
• Use the Add key on the number pad or the Space key to open
nodes with animation.
• Use the Subtract key on the number pad to close nodes with
animation.
• Use the Shift+Right Arrow key to open a closed node, or
select the parent node.
• Use the Shift+Left Arrow to close open nodes.
• Use the Up and Down Arrow keys to move up and down one
row.
To scroll vertically and • The first Page Up or Page Down key pressed move to the first
horizontally in pages or last visible row. The next Page Up or Page Down key
pressed scrolls vertically up or down by a page, which
corresponds to the number of visible rows.
• Use the Shift+Page Up and Shift+Page Down keys to move to
first or last visible column.
CHAPTER 15
Introducing Containers 15
Containers provide a hierarchical structure that lets you control the layout characteristics of
child components. You can use containers to control sizing and positioning of all children, or
to control navigation among multiple child containers.
This topic introduces the two types of containers: layout and navigator. This topic contains an
overview of container usage, including layout rules, and examples of how to use and configure
containers.
Contents
About containers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .563
Using containers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .565
Using scroll bars . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 579
Using Flex coordinates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .582
Creating and managing component instances at run time . . . . . . . . . . . . . . . . . . . .588
About containers
A container defines a rectangular region of the drawing surface of Adobe Flash Player. Within
a container, you define the components, both controls and containers, that you want to
appear within the container. Components defined within a container are called children of the
container. Adobe Flex provides a wide variety of containers, ranging from simple boxes
through panels and forms, to elements such as accordions or tabbed navigators that provide
built-in navigation among child containers.
At the root of a Flex application is a single container, called the Application container, that
represents the entire Flash Player drawing surface. This Application container holds all other
containers and components.
563
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
A container has predefined rules to control the layout of its children, including sizing and
positioning. Flex defines layout rules to simplify the design and implementation of rich
Internet applications, while also providing enough flexibility to let you create a diverse set of
applications.
Using containers
The rectangular region of a container encloses its content area, the area that contains its child
components. The size of the region around the content area is defined by the container
padding and the width of the container border. A container has top, bottom, left, and right
padding, each of which you can set to a pixel width. A container also has properties that let
you specify the type and pixel width of the border. The following image shows a container and
its content area, padding, and borders:
Left padding Right padding
Top padding
Container
Content area
Bottom padding
Parent HBox
layout container Child VBox
layout container
Components Components
Child VBox
layout container
In this example, the two VBox (vertical box) layout containers are nested within an HBox
(horizontal box) layout container and are referred to as children of the HBox container.
The HBox container arranges its children in a single horizontal row and oversees the sizing
and positioning characteristics of the VBox containers. For example, you can control the
distance, or gap, between children in a container by using the horizontalGap and
verticalGap properties.
A VBox container arranges its children in a single vertical stack, or column, and oversees the
layout of its own children. The following image shows the preceding example with the
outermost container changed to a VBox layout container:
Parent VBox
layout container
Components
Child VBox
layout container
Components
Child VBox
layout container
In this example, the outer container is a VBox container, so it arranges its children in a vertical
column.
TextInput control
Button control
TextArea control
In this example, a user enters a ZIP code into the TextInput control, and then clicks the
Button control to see the current temperature for the specified ZIP code in the TextArea
control.
Flex supports form-based applications through its Form layout container. In a Form
container, Flex can automatically align labels, uniformly size TextInput controls, and display
input error notifications. The following image shows a Form container:
Form containers can take advantage of the Flex validation mechanism to detect input errors
before the user submits the form. By detecting the error, and letting the user correct it before
submitting the form to a server, you eliminate unnecessary server connections. The Flex
validation mechanism does not preclude you from performing additional validation on the
server. For more information on Form containers, see “Form, FormHeading, and FormItem
layout containers” on page 642. For more information on validators, see Chapter 44,
“Validating Data,” on page 1529.
Accordion buttons
You use the Accordion buttons to move among the different child containers. The Accordion
container defines a sequence of child panels, but displays only one panel at a time. To navigate
a container, the user clicks on the navigation button that corresponds to the child panel that
they want to access.
Accordion containers support the creation of multistep procedures. The preceding image
shows an Accordion container that defines four panels of a complex form. To complete the
form, the user enters data into all four panels. Accordion containers let users enter
information in the first panel, click the Accordion button to move to the second panel, and
then move back to the first if they want to edit the information. For more information, see
“Accordion navigator container” on page 710.
Box (HBox and Layout Displays content in a uniformly “Box, HBox, and VBox
VBox) spaced row or column. An HBox layout containers”
container horizontally aligns its on page 631
children; a VBox container vertically
aligns its children.
Sprite
UIComponent
Container
All Containers
All containers are derived from the ActionScript classes Sprite, UIComponent, and Container,
and therefore inherit the properties, methods, styles, effects, and events of their superclasses.
Some containers are subclasses of other containers; for example, the ApplicationControlBar is
a subclass of the ControlBar container. For a complete reference, see Adobe Flex Language
Reference.
Event overview
The following events are dispatched only by containers:
■ childAdd Dispatched after a child is added to the container.
■ childRemove Dispatched before a child is removed from the container.
■ childIndexChange Dispatched after a child’s index in the container has changed.
■ scroll Dispatched when the user manually scrolls the container.
The first three events are dispatched for each of the container’s children, and the last is
dispatched when the container scrolls. For detailed information on these events, see Container
in Adobe Flex Language Reference.
The following events are dispatched only by Application containers:
■ applicationComplete Dispatched after the application has been initialized, processed
by the LayoutManager, and attached to the display list. This is the last event dispatched
during an application’s startup sequence. It is later than the application’s
creationComplete event, which gets dispatched before the preloader has been removed
and the application has been attached to the display list.
■ error Dispatched when an uncaught error occurs anywhere in the application.
When a container or control dispatches the initialize event, its initial properties have been
set, but its width and height have not yet been calculated, and its position has not been
calculated. The initialize event is useful for configuring a container’s children. For
example, you can use the a container’s initialize event to programmatically add children or
set a container scroll bar’s styles. You can use a container or component’s initialize
initialize event to initialize the data provider for a control.
Flex dispatches the creationComplete event for a container when those children that are
initially required are fully processed and drawn on the screen, including all required children
of the children and so on. Create a listener for the creationComplete event, for example, if
you must have the children’s dimensions and positions in your event handler. Do not use the
creationComplete event for actions that set layout properties, as doing so results in excess
processing time.
To better understand the order in which Flex dispatches events, consider the following
application outline.
Application
OuterVBox
InnerVBox1
InnerVBoxLabel1
InnerVBox2
InnerVBoxLabel2
The preinitialize, initialize, and creationComplete events for the containers and
controls are dispatched in the following order. The indentation corresponds to the
indentation in the previous outline:
Notice that for the terminal controls, such as the Label controls, the controls are preinitialized
and then immediately initialized. For containers, preinitialization starts with the outermost
container and works inward on the first branch, and then initialization works outward on the
same branch. This process continues until all initialization is completed. Then, the
creationComplete event is dispatched first by the leaf components, and then by their
parents, and so on until the application dispatches the creationComplete event.
If you change the OuterVBox container to a ViewStack with a creationPolicy property set
to auto, the events would look as follows:
OuterViewStack preinitialize
InnerVBox1 preinitialize
InnerVBox2 preinitialize
OuterViewStack initialize
InnerBox1Label preinitialize
InnerBox1Label initialize
InnerVBox1 initialize
InnerBox1Label creationComplete
InnerVBox1 creationComplete
OuterViewStack creationComplete
In this case, the second VBox is preinitialized only, because it does not have to be displayed.
Notice that when a navigator container dispatches the initialize event, its children exist
and have dispatched the preinitialize event, but its children have not dispatched the
initialize event because they have not yet created their own children. For more
information on the creationPolicy property, see Chapter 6, “Improving Startup
Performance,” in Building and Deploying Flex Applications.
<mx:Script>
<![CDATA[
import mx.controls.Alert;
Disabling containers
All containers support the enabled property. By default, this property is set to true to enable
user interaction with the container and with the container’s children. If you set enabled to
false, Flex dims the color of the container and of all of its children, and blocks user input to
the container and to all of its children.
Form container
For more information on the Panel container, see “Panel layout container” on page 673.
You can also define a ControlBar control as part of a Panel container. A ControlBar control
defines an area at the lower edge of the Panel container, below any children in the Panel
container.
You can use the ControlBar container to hold components that might be shared by the other
children in the Panel container, or for controls that operate on the content of the Panel
container. For example, you can use the ControlBar container to display the subtotal of a
shopping cart, where the shopping cart is defined in the Panel container. For a product
catalog, the ControlBar container can hold the Flex controls to specify quantity and to add an
item to a shopping cart. For more information on the ControlBar container, see “ControlBar
layout container” on page 634.
<mx:Script>
<![CDATA[
public function submitLogin():void {
text1.text="You just tried to log in";
}
]]>
</mx:Script>
<mx:Form defaultButton="{mySubmitBtn}">
<mx:FormItem label="Username">
<mx:TextInput id="username"
width="100"/>
</mx:FormItem>
<mx:FormItem label="Password">
<mx:TextInput id="password"
width="100"
displayAsPassword="true"/>
</mx:FormItem>
<mx:FormItem>
<mx:Button id="mySubmitBtn"
label="Login"
click="submitLogin();"/>
</mx:FormItem>
</mx:Form>
<mx:Text id="text1" width="150"/>
</mx:Panel>
</mx:Application>
The Enter key has a special purpose in the ComboBox control. When the drop-down list
of a ComboBox control is open, pressing Enter selects the currently highlighted item in
the ComboBox control; it does not activate the default button. Also, when the cursor is in
a TextArea control, pressing Enter adds a newline; it does not activate the default button.
In this example, you use an HBox container to let users scroll an image, rather than rendering
the complete image at its full size:
<?xml version="1.0"?>
<!-- containers\intro\HBoxScroll.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
If the clipContent property is false, a container lets its child extend past its boundaries.
Therefore, no scroll bars are necessary, and Flex never displays them, even if you set
horizontalScrollPolicy and verticalScrollPolicy to on.
<mx:Style>
HScrollBar, VScrollBar {
repeatDelay: 2000;
repeatInterval:1000;
}
</mx:Style>
In this case, hb1 is an HBox control. All containers have horizontalScrollBar and
verticalScrollBar properties that represent the container’s ScrollBar subcontrols, if they
exist. You must cast these properties to the ScrollBar class, because their type is the IScrollBar
interface, not the ScrollBar class.
Coordinate Description
system
global Coordinates are relative to the upper-left corner of the Stage in Adobe Flash
Player, that is, the outermost edge of the application.
The global coordinate system provides a universal set of coordinates that are
independent of the component context. Uses for this coordinate system
include determining distances between objects and as an intermediate point
in converting between coordinates relative to a subcontrol into coordinates
relative to a parent control.
The MouseEvent class includes stageX and stageY properties that are in the
global coordinate system.
content Coordinates are relative to the upper-left corner of the component’s content.
Unlike the local and global coordinates, the content coordinates include all of
the component’s content area, including any regions that are currently clipped
and must be accessed by scrolling the component. Thus, if you scrolled down
a Canvas container by 100 pixels, the upper-left corner of the visible content
is at position 0, 100 in the content coordinates.
You use the content coordinate system to set and get the positions of children
of a container that uses absolute positioning. (For more information on
absolute positioning, see “About component positioning” on page 228.)
The UIComponent contentMouseX and contentMouseY properties report the
mouse pointer location in the content coordinate system.
The following image shows these coordinate systems and how they relate to each other.
contentPane bounds
content 0, 0
global 0, 0
local 0, 0
component bounds
stage bounds
<mx:Script>
<![CDATA[
import mx.controls.Alert;
<mx:Canvas
width="150" height="150"
x="0" y="0"
backgroundColor="red">
<mx:Button label="I'm in Red"/>
</mx:Canvas>
<mx:Canvas
width="150" height="150"
x="150" y="0"
backgroundColor="green">
<mx:Button label="I'm in Green"/>
</mx:Canvas>
<mx:Canvas
width="150" height="150"
x="0" y="150"
backgroundColor="blue">
<mx:Button label="I'm in Blue"/>
</mx:Canvas>
<mx:Canvas
width="150" height="150"
x="150" y="150"
backgroundColor="magenta">
<mx:Button label="I'm in Magenta"/>
</mx:Canvas>
</mx:Canvas>
</mx:Application>
<mx:HBox id="myContainer">
<mx:Button click="clickHandler();"/>
<mx:TextInput/>
</mx:HBox>
The Container class also defines the rawChildren property that contains the full display list
of all of the children of a container. This list includes all the container’s children, plus the
DisplayObjects that implement the container’s chrome (display elements), such as its border
and the background image. For more information see “Accessing display-only children”
on page 591.
<mx:Script>
<![CDATA[
Although the child argument of the method is specified as type DisplayObject, the
argument must implement the IUIComponent interface to be added as a child of a
container. All Flex components implement this interface.
For example, the following application creates an HBox container with a Button control
called myButton:
<?xml version="1.0"?>
<!-- containers\intro\ContainerAddChild.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.controls.Button;
<mx:Script>
<![CDATA[
import mx.controls.Button;
<mx:HBox id="myHBox">
<mx:Button label="Add Button" click="addButton();"/>
</mx:HBox>
</mx:Application>
The following image shows the resulting application after the user presses the original
(leftmost) button three times:
<mx:Script>
<![CDATA[
public function removeButton():void {
myHBox.removeChild(myButton);
}
]]>
</mx:Script>
<mx:HBox id="myHBox">
<mx:Button id="myButton"
label="Remove Me"
click="removeButton();"/>
</mx:HBox>
</mx:Application>
For additional methods that you can use with container children, see the Container class in
Adobe Flex Language Reference.
<mx:Script>
<![CDATA[
<mx:VBox id="myVBox">
<mx:Button label="Add CheckBox"
<mx:Script>
<![CDATA[
<mx:VBox>
<mx:Accordion id="myAcc" height="150" width="150">
<mx:HBox label="Initial HBox"/>
</mx:Accordion>
As with the addChild() method, although the child argument of the addChildAt()
method is specified as type DisplayObject, the argument must implement the
IUIComponent interface to be added as a child of a container. All Flex components
implement this interface.
<mx:Script>
<![CDATA[
<mx:VBox id="myVBox">
<mx:Button label="Add CheckBox" click="addCB();"/>
<mx:Button label="Remove CheckBox" click="delCB();"/>
<mx:Button label="Reorder children" click="reorder();"/>
</mx:VBox>
</mx:Application>
CHAPTER 16
Contents
Using the Application container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
About the Application object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609
Showing the download progress of an application . . . . . . . . . . . . . . . . . . . . . . . . . . . 614
601
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The Application container has the following default layout characteristics:
The advantage of using percentages to specify the size is that Flex can resize your application
as the user resizes the browser window. Flex maintains the Application container size as a
percentage of the browser window as the user resizes it.
backgroundSize 100%. When you set this property at 100%, the background
image takes up the entire Application container.
horizontalAlign Centered.
paddingBottom 24 pixels.
paddingLeft 24 pixels.
paddingRight 24 pixels.
paddingTop 24 pixels.
You can override these default values in your application to define your own default style
properties.
You can specify a gradient background for the application in two ways:
Flex calculates the gradient pattern between the two specified values.
■ Set the backgroundColor property to the desired value, as in the following example:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundColor="red">
Flex calculates the gradient pattern between a color slightly darker than red, and a color
slightly lighter than red.
To set a solid background to the application, specify the same two values to the
backgroundGradientColors property, as the following example shows:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundGradientColors="[#FFFFFF, #FFFFFF]">
If you use the backgroundGradientColors property to set the application background, you
should also set the backgroundColor property to compliment the
backgroundGradientColors property, as the following example shows:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundGradientColors="[0x0000FF, 0xCCCCCC]"
backgroundColor="0x0000FF">
In this example, you use the backgroundGradientColors property to set a gradient pattern
from a dark blue to grey, and the backgroundColor property to set the Stage area in Flash
Player to dark blue, which will be visible during application loading and initialization.
You can override individual values in the plain setting, as the following example shows:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
styleName="plain" horizontalAlign="center"/>
<mx:Button/>
</mx:Application>
You typically deploy your source code not as an MXML file but as a text or HTML file. In
this example, the source code is in the file AppSourceURL.txt. If you use an HTML file to
represent your source code, you can add formatting and coloring to make it easier to read.
<mx:Script>
<![CDATA[
import mx.controls.Alert;
<mx:Script>
<![CDATA[
// To refer to the members of the Application class,
// you must import mx.core.Application.
import mx.core.Application;
]]>
</mx:Script>
<mx:Script>
<![CDATA[
public var userName:String="SMG";
public function getSalutation():String {
return "Hi, " + userName;
}
]]>
</mx:Script>
</mx:Application>
To access the userName and call the getSalutation() method in your MXML components,
you can use the application property, as the following example from the
MyComponent.mxml component shows:
<?xml version="1.0"?>
<!-- containers\application\myComponents\ButtonGetSalutation.mxml -->
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
width="100%" height="100%" >
<mx:Script>
<![CDATA[
// To refer to the members of the Application class,
// you must import mx.core.Application.
import mx.core.Application;
]]>
</mx:Script>
<mx:Label id="myL"/>
<mx:Button
click="myL.text=Application.application.getSalutation();"/>
</mx:VBox>
In this example, clicking the Button control executes the getSalutation() function to
populate the Label control.
</mx:Application>
In this example, the application is the parent document of the AccChildObject.mxml
component. The following code from the AccChildObject.mxml component uses the
parentDocument property to define an Accordion container that is slightly smaller than the
Application container:
<?xml version="1.0"?>
<!-- containers\application\myComponents\AccChildObject.mxml -->
<mx:Accordion xmlns:mx="http://www.adobe.com/2006/mxml"
width="{parentDocument.width*.80}"
height="{parentDocument.height*.50}">
<mx:HBox/>
</mx:Accordion>
You use the parentDocument property in MXML scripts to go up a level in the chain of
parent documents. You can use the parentDocument to walk this chain by using multiple
parentDocument properties, as the following example shows:
parentDocument.parentDocument.doSomething();
The following example shows the download progress bar during the initialization phase:
Event Description
ProgressEvent.PROGRESS Dispatched when the application SWF file is being downloaded.
The first PROGRESS event signifies the beginning of the download
process.
Event.COMPLETE Dispatched when the SWF file has finished downloading. Either
zero or one COMPLETE event is dispatched.
FlexEvent.INIT_COMPLETE Dispatched when the Flex application finishes initialization. This
event is always dispatched once, and is the last event that the
Preloader dispatches.
The download progress bar must dispatch a COMPLETE event
after it has received an INIT_COMPLETE event. The COMPLETE event
informs the Preloader that the download progress bar has
completed all operations and can be dismissed.
The download progress bar can perform additional tasks, such
as playing an animation, after receiving an INIT_COMPLETE event,
and before dispatching the COMPLETE event. Dispatching the
COMPLETE event should be the last action of the download
progress bar.
FlexEvent.INIT_PROGRESS Dispatched when the Flex application completes an initialization
phase, as defined by calls to the measure(), commitProperties(),
or updateDisplayList() methods. This event describes the
progress of the application in the initialization phase.
RslEvent.RSL_ERROR Dispatched when a Runtime Shared Library (RSL) fails to load.
RslEvent.RSL_LOADED Dispatched when an RSL finishes loading. The total bytes and
total loaded bytes are included in the event object. This event is
dispatched for every RSL that is successfully loaded.
RSLEvent.RSL_PROGRESS Dispatched when an RSL is being downloaded. The first
progress event signifies the beginning of the RSL download.
The event object for this event is of type RSLEvent.
The DownloadProgressBar class defines an event listener for all of these events. Within your
override of the DownloadProgressBar class, you can optionally override the default behavior
of the event listener. If you create a custom download progress bar as a subclass of the Sprite
class, you must define an event listener for each of these events.
<mx:Button/>
<mx:TextInput text="sub class min" />
</mx:Application>
import flash.display.*;
import flash.text.*;
import flash.utils.*;
import flash.events.*;
import mx.preloaders.*;
import mx.events.*;
addChild(progressText);
addChild(msgText);
preloader.addEventListener(
FlexEvent.INIT_PROGRESS, myHandleInitProgress);
preloader.addEventListener(
FlexEvent.INIT_COMPLETE, myHandleInitEnd);
}
<mx:Button/>
<mx:TextInput/>
</mx:Application>
preloader.addEventListener(
FlexEvent.INIT_PROGRESS, handleInitProgress);
preloader.addEventListener(
FlexEvent.INIT_COMPLETE, handleInitComplete);
}
// After the SWF file loads, set the size of the Loader control.
private function loader_completeHandler(event:Event):void
{
addChild(dpbImageControl);
dpbImageControl.width = 50;
CHAPTER 17
Contents
About layout containers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .626
Canvas layout container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .626
Box, HBox, and VBox layout containers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 631
ControlBar layout container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .634
ApplicationControlBar layout container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .636
DividedBox, HDividedBox, and VDividedBox layout containers . . . . . . . . . . . . . .639
Form, FormHeading, and FormItem layout containers . . . . . . . . . . . . . . . . . . . . . . .642
Grid layout container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .666
Panel layout container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 673
Tile layout container. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 678
TitleWindow layout container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 681
625
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
About layout containers
A layout container defines a rectangular region of the Adobe Flash Player drawing surface and
controls the sizing and positioning of the child controls and child containers defined within
it. For example, a Form layout container sizes and positions its children in a layout similar to
an HTML form.
To use a layout container, you create the container, and then add the components that define
your application.
Flex provides the following layout containers:
■ Canvas layout container
■ Box, HBox, and VBox layout containers
■ ControlBar layout container
■ ApplicationControlBar layout container
■ DividedBox, HDividedBox, and VDividedBox layout containers
■ Form, FormHeading, and FormItem layout containers
■ Grid layout container
■ Panel layout container
■ Tile layout container
■ TitleWindow layout container
The following sections describe how to use each of the Flex layout containers.
Default padding 0 pixels for the top, bottom, left, and right values
For complete reference information, see Canvas in Adobe Flex Language Reference.
<mx:Canvas id="myCanvas"
height="200" width="200"
borderStyle="solid"
backgroundColor="white">
<mx:LinkButton label="Search"
x="10" y="30"
click="navigateToURL(new URLRequest('http://mycomp.com/search'))"/>
<mx:Image
height="50" width="50"
x="100" y="10"
source="@Embed(source='assets/search.jpg')"
click="navigateToURL(new URLRequest('http://mycomp.com/search'))"/>
<mx:LinkButton label="Help"
x="10" y="100"
click="navigateToURL(new URLRequest('http://mycomp.com/help'))"/>
<mx:Image
height="50" width="50"
x="100" y="75"
source="@Embed(source='assets/help.jpg')"
click="navigateToURL(new URLRequest('http://mycomp.com/help'))"/>
<mx:LinkButton label="Complaints"
x="10" y="170"
click="navigateToURL(
new URLRequest('http://mycomp.com/complain'))"/>
<mx:Image
height="50" width="50"
x="100" y="140"
source="@Embed(source='assets/complaint.jpg')"
click="navigateToURL(
new URLRequest('http://mycomp.com/complaint'))"/>
</mx:Canvas>
</mx:Application>
<mx:Canvas
width="150" height="150"
backgroundColor="#FFFFFF">
<mx:HBox id="hBox2"
left="30"
right="30"
y="50"
height="50"
backgroundColor="#A9C0E7">
</mx:HBox>
</mx:Canvas>
</mx:Application>
The example produces the following image:
<mx:Canvas
width="300" height="300"
backgroundColor="#FFFFFF">
<mx:TextInput id="text1"
text="Move me"
x="50" y="50"/>
<mx:Button id="button1"
label="Move text1"
x="50" y="200"
click="text1.x=110; text1.y=110;"/>
</mx:Canvas>
</mx:Application>
To lay out children in multiple rows or columns, use a Tile or Grid container. For more
information, see “Tile layout container” on page 678 and “Grid layout container”
on page 666.
Default padding 0 pixels for the top, bottom, left, and right values.
For complete reference information, see Box, HBox, and VBox in Adobe Flex Language
Reference.
<mx:Box direction="vertical"
borderStyle="solid"
paddingTop="10"
paddingBottom="10"
paddingLeft="10"
paddingRight="10">
<mx:VBox borderStyle="solid"
paddingTop="10"
paddingBottom="10"
paddingLeft="10"
paddingRight="10">
Panel container
ControlBar container
Default padding 10 pixels for the top, bottom, left, and right values.
For complete reference information, see ControlBar in Adobe Flex Language Reference.
<mx:Script>
<![CDATA[
private function addToCart():void {
// Handle event.
}
]]>
</mx:Script>
<mx:ControlBar width="250">
<mx:Label text="Quantity"/>
<mx:NumericStepper/>
<!-- Use Spacer to push Button control to the right. -->
<mx:Spacer width="100%"/>
<mx:Button label="Add to Cart"
click="addToCart();"/>
</mx:ControlBar>
</mx:Panel>
</mx:Application>
If you dock the ApplicationControlBar container at the top of an application, it does not
scroll with the application contents.
The ApplicationControlBar container has the following default sizing characteristics:
In contrast to the ControlBar container, it is possible to set the backgroundColor style for
an instance of the ApplicationControlBar. The ApplicationControlBar container has two
styles, fillColors and fillAlpha, that are not supported by the ControlBar container.
<mx:Script>
<![CDATA[
import mx.controls.Alert;
]]>
</mx:Script>
<mx:XMLList id="menuXML">
<menuitem label="File">
<menuitem label="New" data="New"/>
<menuitem label="Open" data="Open"/>
<menuitem label="Save" data="Save"/>
<menuitem label="Exit" data="Exit"/>
</menuitem>
<menuitem label="Edit">
<menuitem label="Cut" data="Cut"/>
<menuitem label="Copy" data="Copy"/>
<menuitem label="Paste" data="Paste"/>
</menuitem>
<menuitem label="View"/>
</mx:XMLList>
<mx:Array id="cmbDP">
<mx:String>Item 1</mx:String>
<mx:String>Item 2</mx:String>
<mx:String>Item 3</mx:String>
</mx:Array>
<mx:ApplicationControlBar id="dockedBar"
dock="true">
<mx:MenuBar height="100%"
dataProvider="{menuXML}"
labelField="@label"
showRoot="true"/>
<mx:HBox paddingBottom="5"
paddingTop="5">
<mx:ComboBox dataProvider="{cmbDP}"/>
<mx:Spacer width="100%"/>
<mx:TextInput id="myTI" text=""/>
<mx:Button id="srch1"
label="Search"
click="Alert.show('Searching')"/>
Vertical divider
Horizontal divider
Default 0 pixels for the top, bottom, left, and right values.
padding
<mx:Script>
<![CDATA[
private function myGrid_initialize():void {
myGrid.dataProvider = [
{Artist:'Pavement', Album:'Slanted and Enchanted',
Price:11.99, Comment:'One of their best. 4 Stars.'},
{Artist:'Pavement', Album:'Brighten the Corners',
</mx:HDividedBox>
</mx:Application>
Notice that this example does not implement the logic to change the top area of the
VDividedBox container when you selct a node in the Tree control.
Form container
FormHeading control
FormItem
containers
The following table describes the types of components that you use to create forms in Flex:
.
FormHeading <mx:FormHeading> Defines a heading within your form. You can have multiple
FormHeading controls within a single Form container.
For complete reference information, see Form, FormHeading, and FormItem in Adobe Flex
Language Reference.
</mx:Form>
</mx:Application>
For complete reference information, see Form in Adobe Flex Language Reference.
</mx:Form>
</mx:Application>
For complete reference information, see FormHeading in Adobe Flex Language Reference.
FormItem
FormItem labels containers
In this example, you define three FormItem containers: one with the label First Name, one
with the label Last Name, and one with the label Address. The Address FormItem container
holds two controls to let a user enter two lines of address information. Each of the other two
FormItem containers includes a single control.
For complete reference information, see FormItem in Adobe Flex Language Reference.
<mx:Script>
<![CDATA[
private function setValues():void {
// Handle value setting.
}
]]>
</mx:Script>
<mx:FormItem label="Address">
<mx:TextInput id="addr1" width="100%"/>
<mx:TextInput id="addr2" width="100%"/>
</mx:FormItem>
<mx:FormItem label="Country">
<mx:ComboBox id="cntry"/>
</mx:FormItem>
<mx:FormItem>
<mx:Button label="Submit"
click="setValues();"/>
</mx:FormItem>
</mx:Form>
Form container:
verticalGap = 6
FormItem container:
verticalGap = 6
FormItem container:
verticalGap = 6
<mx:Script>
<![CDATA[
import flash.events.MouseEvent;
import mx.controls.Alert;
<mx:Form defaultButton="{mySubmitButton}">
<mx:FormItem label="Username">
<mx:TextInput id="username"
width="100"/>
</mx:FormItem>
<mx:FormItem label="Password">
<mx:TextInput id="password"
width="100"
displayAsPassword="true"/>
</mx:FormItem>
<mx:FormItem>
<mx:Button id="mySubmitButton"
label="Login"
click="submitLogin(event);"/>
</mx:FormItem>
</mx:Form>
</mx:Application>
NO TE
When the drop-down list of a ComboBox control is open, pressing Enter selects the
currently highlighted item in the ComboBox control; it does not activate the default
button.
<mx:Form>
<mx:FormItem label="ZIP Code">
<mx:TextInput id="zipOptional"
width="100"/>
</mx:FormItem>
<mx:Form>
<mx:FormItem label="Subscribe">
<mx:CheckBox label="Subscribe?"
click="emAddr.required=true"/>
</mx:FormItem>
<mx:Script>
<![CDATA[
private function processValues(zip:String, pn:String):void {
// Validate and process data.
}
]]>
</mx:Script>
<mx:FormItem>
<mx:Button label="Submit" id="mySubmitButton"
click="processValues(zipCode.text, phoneNumber.text);"/>
</mx:FormItem>
</mx:Form>
</mx:Application>
This example form defines two form controls: one for a ZIP code and one for a phone
number. When you submit the form, you call a function that takes the two arguments that
correspond to the data stored in each control. Your submit function can then perform any
data validation on its inputs before processing the form data.
<mx:Script>
<![CDATA[
private function processValues():void {
var inputZip:String = zipCode.text;
var inputPhone:String = phoneNumber.text;
// Check to see if pn is a number.
// Check to see if zip is less than 4 digits.
// Process data.
}
]]>
</mx:Script>
<mx:FormItem>
<mx:Button label="Submit" id="mySubmitButton"
click="processValues();"/>
</mx:FormItem>
</mx:Form>
</mx:Application>
The technique of using the form fields directly, however, has the problem that the function is
specific to the form and cannot easily be used by other forms.
<mx:Script>
<![CDATA[
private function processValues():void {
var inputZip:String = zipCode.text;
var inputPhone:String = phoneNumber.text;
// Perform any additional validation.
// Process data.
}
]]>
</mx:Script>
<mx:ZipCodeValidator id="zcVal"
source="{zipCode}" property="text"
domain="US or Canada"/>
<mx:PhoneNumberValidator id="pnVal"
source="{phoneNumber}" property="text"/>
<mx:FormItem>
<mx:Button label="Submit" id="mySubmitButton"
click="processValues();"/>
</mx:FormItem>
</mx:Form>
</mx:Application>
<!-- Define the submit function that validates and processes the data -
->
<mx:Script>
<![CDATA[
private function processValues():void {
var inputZip:String = myFormModel.zipCodeModel;
var inputPhone:String = myFormModel.phoneNumberModel;
// Process data.
}
]]>
</mx:Script>
For detailed information on using validators, see Chapter 44, “Validating Data,” on
page 1529.
<mx:Form>
<mx:FormItem label="First and Last Names">
<mx:TextInput id="firstName"/>
<mx:TextInput id="lastName"/>
</mx:FormItem>
<mx:FormItem label="Department">
<mx:TextInput id="dept" text="{myFormModel.department}"/>
</mx:FormItem>
</mx:Form>
</mx:Application>
This department data is considered static because the form always shows the same value in the
field. You could also create a dynamic data model that takes the value of the department field
from a web service, or calculates it based on user input.
For more information on data models, see Chapter 43, “Storing Data,” on page 1517.
<mx:Script>
<![CDATA[
private function processValues():void {
// Check to see if ZIP code is valid.
WeatherService.GetWeather.send();
}
]]>
</mx:Script>
<mx:Form>
<mx:FormItem label="Zip Code">
<mx:TextInput id="zipCode"
width="200"
text="Zip code please?"/>
<mx:Button
width="60"
label="Submit"
click="processValues();"/>
</mx:FormItem>
</mx:Form>
<mx:VBox>
<mx:TextArea
text=
"{WeatherService.GetWeather.lastResult.CityShortName}"/>
<mx:TextArea
text=
"{WeatherService.GetWeather.lastResult.CurrentTemp}"/>
<mx:TextArea
text=
<mx:Script>
<![CDATA[
import mx.controls.Alert;
<mx:ViewStack id="vs1">
<mx:Form>
<mx:FormItem label="Zip Code">
<mx:TextInput id="zipCode"
width="200"
text="Zip code please?"/>
<mx:Button width="60"
label="Submit"
click="processValues();"/>
</mx:FormItem>
</mx:Form>
<mx:VBox>
<mx:TextArea
text=
"{WeatherService.GetWeather.lastResult.CityShortName}"/>
<mx:TextArea
text=
"{WeatherService.GetWeather.lastResult.CurrentTemp}"/>
<mx:TextArea
text=
"{WeatherService.GetWeather.lastResult.DayForecast}"/>
</mx:VBox>
</mx:ViewStack>
</mx:Application>
When a call to the web service succeeds, the successfulCall() function switches the
current ViewStack child to the VBox container to show the returned results. An error from
the web service displays an Alert box, but does not change the current child of the ViewStack
container; the form remains visible, which lets the user fix any input errors.
You have many options for handling navigation in your application based on the results of the
submit function. The previous example used a ViewStack container to handle navigation. You
might also choose to use a TabNavigator container or Accordion container for this same
purpose.
You can put zero or one child in each cell of a Grid container. If you include multiple children
in a cell, put a container in the cell, and then add children to the container. The height of all
cells in a row is the same, but each row can have a different height. The width of all cells in a
column is the same, but each column can have a different width.
You can define a different number of cells for each row or each column of the Grid container.
In addition, a cell can span multiple columns and/or multiple rows of the container.
The Grid, GridRow, and GridItem containers have the following default sizing characteristics:
Grid width The sum of the default or explicit width of all columns plus the gaps
between columns.
Width of each The default or explicit width of the widest item in the column. If a GridItem
column and each container not have an explicit width, its default width is the default or
cell explicit width of the child in the cell.
Gap between rows Determined by the horizontalGap and verticalGap properties of the Grid
and columns class. The default value for both gaps is 6 pixels.
Default padding 0 pixels for the top, bottom, left, and right values, for all three container
classes.
If the default or explicit size of the child is larger than the size of an explicitly sized cell, the
child is clipped at the cell boundaries.
If the child’s default width or default height is smaller than the cell, the default horizontal
alignment of the child in the cell is left and the default vertical alignment is top. You can use
the horizontalAlign and verticalAlign properties of the <mx:GridItem> tag to control
positioning of the child.
For complete reference information, see Grid, GridRow, and GridItem in Adobe Flex
Language Reference. For information on the Tile container, which creates a layout where all
cells have the same size, see “Tile layout container” on page 678.
The following image shows a Grid container with three rows and three columns:
On the left, you see how the Grid container appears in Flash Player. On the right, you see the
Grid container with borders overlaying it to illustrate the configuration of the rows and
columns. In this example, the buttons in the first (top) row each occupy a single cell. The
button in the second row spans three columns, and the button in the third row spans the
second and third columns.
You do not have to define the same number of cells for every row of a Grid container, as the
following image shows. The Grid container defines five cells in row one; row two has one item
that spans three cells; and row 3 has one empty cell, followed by an item that spans two cells.
<mx:Grid id="myGrid">
</mx:Grid>
</mx:Application>
<mx:Grid id="myGrid">
</mx:Grid>
</mx:Application>
<mx:Grid id="myGrid">
</mx:Grid>
</mx:Application>
Padding 4 pixels for the top, bottom, left, and right values.
For complete reference information, see Panel in Adobe Flex Language Reference.
<mx:Form width="300">
<mx:FormHeading label="Billing Information"/>
<!-- Form contents goes here -->
</mx:Form>
</mx:Panel>
</mx:Application>
Panel container
ControlBar container
<mx:Script>
<![CDATA[
private function addToCart():void {
// Handle event.
}
]]>
</mx:Script>
<mx:HBox width="100%">
<!-- Area for your catalog. -->
</mx:HBox>
<mx:ControlBar width="100%">
<mx:Label text="Quantity"/>
<mx:NumericStepper id="myNS"/>
<!-- Use Spacer to push Button control to the right. -->
<mx:Spacer width="100%"/>
<mx:Button label="Add to Cart" click="addToCart();"/>
</mx:ControlBar>
</mx:Panel>
</mx:Application>
For more information on the ControlBar container, see “ControlBar layout container”
on page 634.
<mx:Script>
<![CDATA[
import mx.containers.ControlBar;
import mx.controls.*;
import flash.events.MouseEvent;
myCB.percentWidth=100;
myCB.addChild(myLabel);
myCB.addChild(myNS);
myCB.addChild(mySpacer);
myCB.addChild(myButton);
<mx:Panel id="myPanel"
title="My Application"
paddingTop="10" paddingBottom="10"
paddingLeft="10" paddingRight="10"
width="300">
<mx:HBox width="100%">
<!-- Area for your catalog. -->
</mx:HBox>
</mx:Panel>
</mx:Application>
All Tile container cells have the same size, unlike the cells of a Grid layout container (see
“Grid layout container” on page 666). Flex arranges the cells of a Tile container in a square
grid, where each cell holds a single child component. For example, if you define 16 children in
a Tile layout container, Flex lays it out four cells wide and four cells high. If you define 13
children, Flex still lays it out four cells wide and four cells high, but leaves the last three cells in
the fourth row empty.
The following image shows examples of horizontal and vertical Tile containers:
Horizontal (default)
Vertical
Default size of The height is the default or explicit height of the tallest child; width is the
all cells default or explicit width of the widest child. All cells have the same default
size.
Default size of Flex computes the square root of the number of children, and rounds up to
Tile container the nearest integer. For example, if there are 26 children, the square root is
5.1, which is rounded up to 6. Flex then lays out the Tile container in a 6 by 6
grid.
The default height of the Tile container is equal to (tile cell default height) *
(rounded square root of the number of children), plus any gaps between
children and any padding. The default width is equal to (tile cell default
width) * (rounded square root of the number of children), any gaps between
children and any padding.
Minimum size of The default size of a single cell. Flex always allocates enough space to
Tile container display at least one cell.
Default padding 0 pixels for the top, bottom, left, and right values.
For complete reference information, see Tile in Adobe Flex Language Reference.
<mx:Tile id="myFlow"
direction="horizontal"
borderStyle="solid"
paddingTop="10" paddingBottom="10"
paddingRight="10" paddingLeft="10"
verticalGap="15" horizontalGap="10">
<mx:Tile id="myFlow"
direction="horizontal"
borderStyle="solid"
paddingTop="10" paddingBottom="10"
paddingRight="10" paddingLeft="10"
verticalGap="15" horizontalGap="10"
tileWidth="100">
When you set the child’s width and height properties to percentages, the percentage is
based on the size of the tile cell, not on the size of the Tile container itself. Even though it
isn’t an explicitly defined container, the cell acts as the parent of the components in the
Tile container.
For complete reference information, see TitleWindow in Adobe Flex Language Reference.
Argument Description
parent A reference to a window to pop-up over.
class A reference to the class of object you want to create, typically a custom
MXML component that implements a TitleWindow container.
modal (Optional) A Boolean value that indicates whether the window is modal,
and takes all mouse input until it is closed (true), or whether interaction is
allowed with other controls while the window is displayed (false). The
default value is false.
NOTE
Flex continues executing code in the parent even after you create a modal pop-up
window.
You can also create a pop-up window by passing an instance of a TitleWindow class or custom
component to the PopUpManager’s addPopUp() method. For more information, see “Using
the addPopUp() method” on page 696.
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
<mx:Form>
<mx:FormItem label="User Name">
<mx:TextInput id="username" width="100%"/>
</mx:FormItem>
<mx:FormItem label="Password">
<mx:TextInput id="password"
displayAsPassword="true"
width="100%"/>
</mx:FormItem>
</mx:Form>
<mx:HBox>
<mx:Button click="processLogin();" label="OK"/>
<mx:Button
label="Cancel"
click="PopUpManager.removePopUp(this);"/>
</mx:HBox>
</mx:TitleWindow>
This file, named MyLoginForm.mxml, defines a TitleWindow container by using the
<mx:TitleWindow> tag. The TitleWindow container defines two TextInput controls, for user
name and password, and two Button controls, for submitting the form and for closing the
TitleWindow container. This example does not include the code for verifying the user name
and password in the submitForm() event listener.
In this example, you process the form data in an event listener of the MyLoginForm.mxml
component. To make this component more reusable, you can define the event listeners in
your main application. This lets you create a generic form that leaves the data handling to the
application that uses the form. For an example that defines the event listeners in the main
application, see “Using TitleWindow and PopUpManager events” on page 688.
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
import mx.core.IFlexDisplayObject;
import myComponents.MyLoginForm;
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
import mx.core.IFlexDisplayObject;
import myComponents.MyLoginForm;
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
import myComponents.MyLoginForm;
import mx.core.IFlexDisplayObject;
If you need to clean up, before closing the TitleWindow control, create an event listener
function for the close event and close the TitleWindow from within that handler, as the
following example shows:
<?xml version="1.0"?>
<!-- containers\layouts\myComponents\MyLoginFormRemoveMe.mxml -->
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
showCloseButton="true"
close="removeMe();">
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
</mx:TitleWindow>
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
import mx.containers.TitleWindow;
import myComponents.MyLoginForm;
import mx.events.FlexMouseEvent;
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
import myComponents.ArrayEntryForm;
<mx:VBox>
<mx:TextInput id="ti1" text=""/>
</mx:VBox>
<mx:Button id="b1" label="Select File Type" click="displayForm();"/>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.controls.TextInput;
import mx.managers.PopUpManager;
This technique, however, uses a hard-coded value in the pop-up component for both the
target component id in the parent and the property in the component.
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
import flash.events.Event;
import myComponents.ArrayEntryFormEvents;
<mx:VBox>
<mx:TextInput id="ti1" text=""/>
</mx:VBox>
<mx:Button id="b1" label="Select File Type" click="displayForm();"/>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.containers.TitleWindow;
import flash.events.*;
import mx.managers.PopUpManager;
import mx.controls.Button;
import mx.core.IFlexDisplayObject;
// The method to create and add the Button child control to the
// TitleWindow container.
public function populateWindow():void {
var btn1:Button = new Button();
btn1.label="close";
btn1.addEventListener(MouseEvent.CLICK, closeTitleWindow);
myTitleWindow.addChild(btn1);
}
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
import mx.controls.TextArea;
import mx.core.IFlexDisplayObject;
<mx:VBox>
<mx:Button id="b1" label="Create TextArea Popup"
click="openWindow(event);"/>
<mx:Label id="label1"/>
</mx:VBox>
</mx:Application>
CHAPTER 18
Contents
About navigator containers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 699
ViewStack navigator container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .700
TabNavigator container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .706
Accordion navigator container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 710
The direct children of a navigator container must be containers, either layout or navigator
containers. You cannot directly nest a control within a navigator; controls must be
children of a child container of the navigator container.
699
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
ViewStack navigator container
A ViewStack navigator container is made up of a collection of child containers that are stacked
on top of each other, with only one container visible, or active, at a time. The ViewStack
container does not define a built-in mechanism for users to switch the currently active
container; you must use a LinkBar, TabBar, ButtonBar, or ToggleButtonBar control or build
the logic yourself in ActionScript to let users change the currently active child. For example,
you can define a set of Button controls that switch among the child containers.
The following image shows the stacked child containers in a ViewStack container:
On the left, you see a ViewStack container with the first child active. The index of a child in a
ViewStack container is numbered from 0 to n - 1, where n is the number of child containers.
The container on the right is a ViewStack container with the second child container active.
The ViewStack container has the following default sizing characteristics:
Default padding 0 pixels for top, bottom, left, and right values.
For complete reference information, see ViewStack in Adobe Flex Language Reference.
The following example uses ActionScript to set the selectedIndex property so that the
active child container is the second container in the stack:
myViewStack.selectedIndex=1;
■ selectedChild The currently active container if one or more child containers are
defined. The value of this property is null if no child containers are defined. Set this
property in ActionScript to the identifier of the container that you want active.
You can set this property only in an ActionScript statement, not in MXML.
The following example uses ActionScript to set the selectedChild property so that the
active child container is the child container with an identifier of search:
myViewStack.selectedChild=search;
The default creation policy for all containers, except the Application container, is the
policy of the parent container. The default policy for the Application container is auto. In
most cases, therefore, the View Stack control’s children are not created until they are
selected. You cannot set the selectedChild property to a child that is not yet created.
<mx:Button id="cInfoButton"
label="Customer Info Screen"
click="myViewStack.selectedChild=custInfo;"/>
<mx:Button id="aInfoButton"
label="Account Info Screen"
click="myViewStack.selectedChild=accountInfo;"/>
</mx:HBox>
<!-- Define the ViewStack and the three child containers and have it
resize up to the size of the container for the buttons. -->
<mx:ViewStack id="myViewStack"
borderStyle="solid" width="100%">
LinkBar control
The items in the LinkBar control correspond to the values of the label property of each child
of the ViewStack container, as the following example shows:
<?xml version="1.0"?>
<!-- containers\navigators\VSLinkBar.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:VBox>
<!-- Create a LinkBar control to navigate
the ViewStack container. -->
<mx:LinkBar dataProvider="{myViewStack}" borderStyle="solid"/>
<!-- Define the ViewStack and the three child containers. -->
<mx:ViewStack id="myViewStack"
borderStyle="solid"
width="100%">
<mx:VBox>
<mx:LinkBar dataProvider="{myViewStack}"
borderStyle="solid"
backgroundColor="#EEEEFF"/>
<mx:ViewStack id="myViewStack"
borderStyle="solid"
width="100%"
creationCompleteEffect="{myWR}">
<mx:Canvas id="search"
label="Search"
hideEffect="{myWD}"
showEffect="{myWU}">
<mx:Label text="Search Screen"/>
</mx:Canvas>
<mx:Canvas id="custInfo"
label="Customer Info"
hideEffect="{myWD}"
showEffect="{myWU}">
<mx:Label text="Customer Info"/>
</mx:Canvas>
<mx:Canvas id="accountInfo"
label="Account Info"
hideEffect="{myWD}"
showEffect="{myWU}">
<mx:Label text="Account Info"/>
</mx:Canvas>
</mx:ViewStack>
</mx:VBox>
</mx:Application>
Notice that the showEffect property of a container is only triggered when the container’s
visibility changes from false to true. Therefore, you use the creationCompleteEffect
property to trigger the effect when Flex first creates the component.
The TabNavigator container is a child class of the ViewStack container and inherits much of
its functionality. A TabNavigator container has the following default sizing characteristics:
Container By default, TabNavigator containers are only sized once to fit the size of the
resizing rules first child container by default. They do not resize when you navigate to
other child containers by default. To force TabNavigator containers to
resize when you navigate to a different child container, set the
resizeToContent property to true.
Child layout The child is clipped if it is larger than the TabNavigator container. If the child
rules is smaller than the TabNavigator container, it is aligned to the upper-left
corner of the TabNavigator container.
Default padding 0 pixels for the top, bottom, left, and right values.
For complete reference information, see TabNavigator in Adobe Flex Language Reference.
<mx:VBox label="Accounts"
width="300"
height="150">
<!-- Accounts view goes here. -->
</mx:VBox>
<mx:VBox label="Stocks"
width="300"
height="150">
<!-- Stocks view goes here. -->
</mx:VBox>
<mx:VBox label="Futures"
width="300"
height="150">
<!-- Futures view goes here. -->
</mx:VBox>
</mx:TabNavigator>
</mx:Application>
You can also set the currently active child using the selectedChild and selectedIndex
properties inherited from the ViewStack container as follows:
<mx:WipeLeft id="myWL"/>
<mx:TabNavigator>
<mx:VBox label="Accounts"
width="300"
height="150"
showEffect="{myWL}">
<!-- Accounts view goes here. -->
</mx:VBox>
<mx:VBox label="Stocks"
width="300"
height="150"
showEffect="{myWL}">
<!-- Stocks view goes here. -->
</mx:VBox>
<mx:VBox label="Futures"
width="300"
height="150"
showEffect="{myWL}">
<!-- Futures view goes here. -->
</mx:VBox>
</mx:TabNavigator>
</mx:Application>
Key Action
Down Arrow Gives focus to the next tab, wrapping from last to first, without changing the
Right Arrow selected child.
Up Arrow Gives focus to the previous tab, wrapping from first to last, without changing
Left Arrow the selected child.
Page Down Selects the next child, wrapping from last to first.
Enter Selects the child associated with the tab displaying focus.
Spacebar
Accordion container
navigation button
Accordion container
navigation button
To navigate a container, the user clicks the navigation button that corresponds to the child
panel that they want to access. Accordion containers let users access the child panels in any
order to move back and forth through the form. For example, when the user is in the Credit
Card Information panel, they might decide to change the information in the Billing Address
panel. To do so, they navigate to the Billing Address panel, edit the information, and then
navigate back to the Credit Card Information panel.
In HTML, a form that contains shipping address, billing address, and credit card information
is often implemented as three separate pages, which requires the user to submit each page to
the server before moving on to the next. An Accordion container can organize the
information on three child panels with a single Submit button. This architecture minimizes
server traffic and lets the user maintain a better sense of progress and context.
NOTE
Container Accordion containers are only sized once to fit the size of the first child
resizing rules container by default. They do not resize when you navigate to other child
containers by default. To force Accordion containers to resize when you
navigate to a different child container, set the resizeToContent property to
true.
Child sizing Children are sized to their default size. The child is clipped if it is larger than
rules the Accordion container. If the child is smaller than the Accordion
container, it is aligned to the upper-left corner of the Accordion container.
Default padding -1 pixel for the top, bottom, left, and right values.
For complete reference information, see Accordion in Adobe Flex Language Reference.
</mx:Form>
</mx:Accordion>
</mx:Application>
This example defines each child panel by using a Form container. However, you can use any
container to define a child panel.
NOT E
You can use any container to define child panels. However, some containers do not
belong in child panels, such as a TabNavigator container because it has no child
components, or an Accordion container.
Key Action
Down Arrow Gives focus to the next button, wrapping from last to first, without changing
Right Arrow the selected child.
Up Arrow Gives focus to the previous button, wrapping from first to last, without
Left Arrow changing the selected child.
Page Up Moves to the previous child panel, wrapping from first to last.
Page Down Moves to the next child panel, wrapping from last to first.
Enter Selects the child associated with the tab displaying focus.
Spacebar
Property Description
numChildren Contains the total number of child panels defined in an Accordion
container.
selectedIndex The index of the currently active child panel. Child panels are numbered
from 0 to numChildren - 1. Setting the selectedIndex property changes the
currently active panel.
selectedChild The currently active child container if one or more child containers are
defined. This property is null if no child containers are defined. Set this
property to the identifier of the container that you want active. You can
set this property only in an ActionScript statement, not in MXML.
For more information on these properties, see “ViewStack navigator container” on page 700.
</mx:Form>
</mx:Accordion>
</mx:Application>
You can also use relative location with navigation buttons. The following Button controls
move forward and backward through Accordion container panels based on the current panel
number:
<mx:Button id="backButton" label="Back"
click="accordion1.selectedIndex = accordion1.selectedIndex - 1;"/>
<mx:Button id="nextButton" label="Next"
click="accordion1.selectedIndex = accordion1.selectedIndex + 1;"/>
For the Next Button control, you also can use the selectedChild property to move to the
next panel based on the value of the id property of the panel’s container, as the following code
shows:
<mx:Button id="nextButton" label="Next"
click="accordion1.selectedChild=creditCardInfo;"/>
A change event is not dispatched when the child panel changes programmatically; for
example, the change event is not dispatched when you use the buttons in “Using Button
controls to navigate an Accordion container” to change panels. However, the
valueCommit event is dispatched.
You can register an event handler for the change event using the change property of the
<mx:Accordion> tag, or by registering the handler in ActionScript. The following example
logs the change event to flashlog.txt each time the user changes panels:
<mx:Accordion id="accordion1" height="450" change="trace('change');">
<mx:Script>
<![CDATA[
public function setButtonStyles():void {
comp.getHeaderAt(0).setStyle('color', 0xAA0000);
comp.getHeaderAt(1).setStyle('color', 0x00AA00);
}
]]>
</mx:Script>
<mx:Accordion id="comp">
<mx:VBox label="first box">
<mx:TextInput/>
<mx:Button label="Button 1"/>
</mx:VBox>
<mx:VBox label="second box">
<mx:TextInput/>
<mx:Button label="Button 2"/>
</mx:VBox>
</mx:Accordion>
</mx:Application>
You can also control the appearance of the buttons by using the headerStyleName style
property of the Accordion class. For more information, see Accordion in Adobe Flex Language
Reference.
PART 3
717
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
CHAPTER 19
Using Behaviors 19
Behaviors let you add animation and motion to your application in response to user or
programmatic action. For example, you can use behaviors to cause a dialog box to bounce
slightly when it receives focus, or to slowly fade in when it becomes visible.
This topic describes how to build behaviors into your applications using MXML and
ActionScript, and describes the two parts of a behavior: triggers and effects.
Contents
About behaviors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 719
Applying behaviors. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 729
Working with effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .744
About behaviors
A behavior is a combination of a trigger paired with an effect. A trigger is an action, such as a
mouse click on a component, a component getting focus, or a component becoming visible.
An effect is a visible or audible change to the target component that occurs over a period of
time, measured in milliseconds. Examples of effects are fading, resizing, or moving a
component.
You can define multiple effects to play in response to a single trigger. For example, a pet store
application might contain a Button control to select a pet category. When the user clicks the
Button control, a window that contains breed names becomes visible. As the window becomes
visible, it moves to the bottom-left corner of the screen, and it resizes from 100 by 100 pixels
to 300 by 300 pixels (the effects).
719
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
By default, Adobe Flex components do not play an effect when a trigger occurs. To configure
a component to use an effect, you associate an effect with a trigger.
N OTE
Triggers are not the same as events. For example, a Button control has both a mouseDown
event and a mouseDownEffect trigger. The event initiates the corresponding effect trigger
when a user clicks on a component. You use the mouseDown event property to specify the
event listener that executes when the user clicks on the component. You use the
mouseDownEffect trigger property to associate an effect with the trigger.
</mx:Application>
In this example, the effect is a WipeLeft effect with a duration of 1000 milliseconds (ms).
That means it takes 1000 ms for the effect to play from start to finish.
You use data binding to assign the effect to the mouseDownEffect property of each Button
control. The mouseDownEffect property is the effect trigger that specifies to play the effect
when the user clicks the control using the mouse pointer. In the previous example, the effect
makes the Button control appear as if it is being wiped onto the screen from right to left.
</mx:Application>
This example still uses an event to invoke the effect. To play an effect programmatically, you
call the effect’s play() method. For information on using ActionScript to configure and
invoke effects, and for more information on using MXML, see “Applying behaviors”
on page 729.
By convention, the name of a factory class is the name of the effect, such as Zoom or Fade.
Instance class The instance class implements the effect logic. When an effect trigger
occurs, or when you call the play() method to invoke an effect, the factory class creates an
object of the instance class to perform the effect on the target. When the effect ends, Flex
destroys the instance object. If the effect has multiple target components, the factory class
creates multiple instance objects, one per target.
By convention, the name of an instance class is the name of the effect with the suffix Instance,
such as ZoomInstance or FadeInstance.
Effect
Factory classes
EffectInstance
Instance classes
As you can see in this diagram, there is a corresponding instance class for each factory class.
When you use effects, you perform the following steps:
1. Create a factory class object.
2. Configure the factory class object.
When Flex plays an effect, Flex performs the following actions:
1. Creates one object of the instance class for each target component of the effect.
2. Copies configuration information from the factory object to the instance object.
3. Plays the effect on the target using the instance object.
4. Deletes the instance object when the effect completes.
Any changes that you make to the factory object are not propagated to a currently playing
instance object. However, the next time the effect plays, the instance object uses your new
settings.
Available effects
The following table lists the effects that Flex supports:
Effect Description
AnimateProperty Animates a numeric property of a component, such as height, width,
scaleX, or scaleY. You specify the property name, start value, and end
value of the property to animate. The effect first sets the property to the
start value, and then updates the property value over the duration of the
effect until it reaches the end value.
For example, if you want to change the width of a Button control, you can
specify width as the property to animate, and starting and ending width
values to the effect.
Blur Applies a blur visual effect to a component. A Blur effect softens the
details of an image. You can produce blurs that range from a softly
unfocused look to a Gaussian blur, a hazy appearance like viewing an
image through semi-opaque glass.
The Blur effect uses the Flash BlurFilter class as part of its
implementation. For more information, see flash.filters.BlurFilter in Adobe
Flex Language Reference.
If you apply a Blur effect to a component, you cannot apply a BlurFilter or a
second Blur effect to the component.
Glow Applies a glow visual effect to a component. The Glow effect uses the
Flash GlowFilter class as part of its implementation. For more information,
see the flash.filters.GlowFilter class in the Adobe Flex Language
Reference.
If you apply a Glow effect to a component, you cannot apply a GlowFilter
or a second Glow effect to the component.
Move Changes the position of a component over a specified time interval. You
typically apply this effect to a target in a container that uses absolute
positioning, such as Canvas, or one with "layout=absolute", such as
Application or Panel. If you apply it to a target in a container that performs
automatic layout, such as a VBox or Grid container, the move occurs, but
the next time the container updates its layout, it moves the target back to
its original position. You can set the container's autoLayout property to
false to disable the move back, but that disables layout for all controls in
the container.
The Move effect has the following properties:
• xFrom and yFrom Specifies the initial position of the component. If
omitted, Flex uses the current position.
• xTo and yTo Specifies the destination position.
• xBy and yBy Specifies the number of pixels to move the component in
the x and y directions. Values can be positive or negative.
For the xFrom, xTo, and xBy properties, you can specify any two of the three
values; Flex calculates the third. If you specify all three properties, Flex
ignores the xBy property. The same is true for the yFrom, yTo, and yBy
properties.
If you specify a Move effect for a trigger, and if you do not set the six From,
To, and By properties, Flex sets them to create a smooth transition
between the object’s old position and its new position.
When the Move effect runs, the layout around the component that is
moving does not readjust. Setting a container’s autoLayout property to
true has no effect on this behavior.
Pause Does nothing for a specified period of time. This effect is useful when you
need to composite effects. For more information, see “Creating composite
effects” on page 745.
Rotate Rotates a component around a specified point. You can specify the
coordinates of the center of the rotation, and the starting and ending
angles of rotation. You can specify positive or negative values for the
angles.
The Resize effect has the following properties:
• angleFrom and angleTo Specifies the initial rotation and final rotation
angles.
• originX and originY Specifies coordinate of the center point of the
rotation.
Note: To use the Rotate effect with text, you must use an embedded font,
not a device font. For more information, see Chapter 20, “Using Styles
and Themes,” on page 767.
SoundEffect Plays an MP3 audio file. For example, you could play a sound when a user
clicks a Button control. This effect lets you repeat the sound, select the
source file, and control the volume and pan.
You specify the MP3 file using the source property. If you have already
embedded the MP3 file, using the Embed keyword, then you can pass the
Class object of the MP3 file to the source property. Otherwise, specify the
full URL to the MP3 file.
For more information, see “Using a sound effect” on page 750.
Available triggers
You use a trigger name to assign an effect to a target component. You can reference a trigger
name as a property of an MXML tag, in the <mx:Style> tag, or in an ActionScript
setStyle() and getStyle() function. Trigger names use the following naming convention:
triggerEventEffect
where triggerEvent is the event that invokes the effect. For example, the focusIn event
occurs when a component gains focus; you use the focusInEffect trigger property to specify
the effect to invoke for the focusIn event. The focusOut event occurs when a component
loses focus; the corresponding trigger property is focusOutEffect.
The following table lists the effect name that corresponds to each trigger:
Applying behaviors
This section describes how to apply behaviors using both MXML and ActionScript.
</mx:Application>
<mx:Resize id="myResizeUp"
widthBy="50" heightBy="50"
duration="200"/>
<mx:Resize id="myResizeDown"
widthBy="-50" heightBy="-50"
duration="200"/>
<mx:Button id="myButton"
mouseDownEffect="{myResizeUp}"
mouseUpEffect="{myResizeDown}"/>
</mx:Application>
<mx:Zoom id="mZoom"
zoomHeightTo="{Number(zoomHeightInput.text)}"
zoomWidthTo="{Number(zoomWidthInput.text)}"/>
<mx:Button rollOverEffect="{mZoom}"/>
</mx:Application>
By default, the text property of the TextInput controls is set to 1.0. The user can edit the
TextInput controls to specify a different zoom value.
<mx:Style>
TextArea { mouseDownEffect: slowWipe; }
</mx:Style>
</mx:Application>
Setting the mouseDownEffect property in a component tag overrides any settings that you
make in an <mx:Style> tag. If you want to remove the associated effect defined in a type
selector, you can explicitly set the value of any trigger to none, as the following example
shows:
<mx:TextArea id="myTA" mouseDownEffect="none"/>
You can also use a class selector to apply effects, as the following example shows:
<?xml version="1.0"?>
<!-- behaviors\ButtonWLClassSel.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" >
<mx:Style>
<!-- Define a class selector for a TextArea control -->
.textAreaStyle{ mouseDownEffect: WipeLeft; }
</mx:Style>
</mx:Application>
trigger_name String indicating the name of the trigger property; for example,
mouseDownEffect or focusInEffect.
effect The effect associated with the trigger. The data type of effect is an Effect object, or
an object of a subclass of the Effect class.
The getStyle() method has the following signature:
getStyle("trigger_name"):return_type
</mx:Application>
For more information on working with styles, see Chapter 20, “Using Styles and Themes,” on
page 767.
<mx:Script>
<![CDATA[
<mx:VBox borderStyle="solid">
<mx:Button label="Start"
click="resizeLarge.end();resizeLarge.play();"/>
<mx:TextArea id="myTA" text="Here is some text."/>
</mx:VBox>
</mx:Application>
In this example, use the application’s creationComplete event to configure the effect, and
then invoke it by calling the play() method in response to a user clicking the Button control.
Because you invoke the effect programmatically, you do not need an event trigger to invoke it.
Calling the end() method is only necessary when you invoke an effect using the play()
method. If you invoke an effect using an effect trigger, such as the mouseDownEffect
trigger, Flex makes sure to end the effect before starting a new one.
This example also defines the effect using ActionScript. You are not required to define the
effect in ActionScript. You could rewrite this code using MXML to define the effect, as the
following example shows:
<?xml version="1.0"?>
<!-- behaviors\MxmlPlay.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" >
This example invokes the Zoom effect on three components. Notice that the end() method
does not take an effect target as an argument but an effect instance. Therefore, you end this
effect by calling the end() method on the effect itself, as the following example shows:
resizeLarge.end();
When you call the play() method, you essentially replace the effect trigger with the method
call. You use the Effect.target or Effect.targets properties to specify the target
components of an effect when you invoke them using the play() method. This example uses
the target property of the effect to specify the single target component. If you want to play
the effect on multiple components, you can use the Effects.targets property to specify an
array of target components. For more information, see “Applying behaviors using the
Effect.target and Effect.targets properties” on page 742.
Rather than using the target property to specify the target component of the effect, you can
also pass the target component to the constructor, as the following example shows:
In this example, you specify true as the second argument to play the effect backward. The
default value is false.
You can also use the Effect.pause() method to pause an effect, the Effect.resume()
method to resume a paused effect, and the Effect.reverse() method to play an effect
backward.
<mx:Script>
<![CDATA[
<mx:Script>
<![CDATA[
import flash.events.Event;
import mx.effects.Effect;
import mx.effects.Move;
<mx:Script>
<![CDATA[
import flash.events.Event;
import mx.effects.Zoom;
<mx:Button id="myB"/>
</mx:Application>
<mx:Script>
<![CDATA[
import flash.events.Event;
<mx:Button id="myB"/>
</mx:Application>
<mx:Script>
<![CDATA[
<mx:Button id="myButton"
label="My Button"
click="changeEffect();"
mouseUpEffect="{myWL}"/>
</mx:Application>
<mx:Zoom id="myZoom"
zoomHeightFrom="0.10" zoomWidthFrom="0.10"
zoomHeightTo="1.00" zoomWidthTo="1.00"
target="{myButton}"/>
<mx:Button id="myButton"
label="Zoom target"
click="myZoom.end();myZoom.play();"/>
</mx:Application>
In this example, you use data binding to the target property to specify that the Button
control is the target of the Zoom effect. However, you do not associate the effect with a
trigger, so you must call the effect’s play() method to invoke it.
In the next example, you apply a Zoom effect to multiple Button controls by using data
binding with the effect’s targets property:
<?xml version="1.0"?>
<!-- behaviors\TargetProp3Buttons.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Zoom id="myZoom"
zoomHeightFrom="0.10" zoomWidthFrom="0.10"
zoomHeightTo="1.00" zoomWidthTo="1.00"
targets="{[myButton1, myButton2, myButton3]}"/>
<mx:Button id="myButton1"/>
<mx:Button id="myButton2"/>
<mx:Button id="myButton3"/>
<mx:Script>
<![CDATA[
import mx.effects.Fade;
import flash.events.Event;
Then you can pass the array to the end() method to end the effect on all targets, as the
following example shows:
myFade.end(myFadeArray);
<mx:Style>
@font-face {
src:url("../assets/MyriadWebPro.ttf");
font-family: myMyriadWebPro;
}
</mx:Style>
<mx:VBox>
<mx:Label fontFamily="myMyriadWebPro"
mouseDownEffect="{fadeOut}" mouseUpEffect="{fadeIn}"
text="This Label control uses the MyriadWebPro embedded font
and the text will fade."/>
<mx:Label
mouseDownEffect="{fadeOut}" mouseUpEffect="{fadeIn}"
text="This Label control uses the system font
and the text will not fade."/>
</mx:VBox>
</mx:Application>
<mx:Parallel id="ZoomRotateShow">
<mx:Zoom id="myZoomShow"
zoomHeightFrom="0.0" zoomWidthFrom="0.0"
zoomHeightTo="1.0" zoomWidthTo="1.0"/>
<mx:Rotate id="myRotateShow" />
</mx:Parallel>
<mx:Sequence id="ZoomRotateHide">
<mx:Rotate id="myRotateHide"/>
<mx:Zoom id="myZoomHide"
zoomHeightFrom="1.0" zoomWidthFrom="1.0"
zoomHeightTo="0.0" zoomWidthTo="0.0"/>
</mx:Sequence>
<mx:Button id="myButton1"
label="Show!"
click="aTextArea.visible=true;"/>
<mx:Button id="myButton2"
label="Hide!"
click="aTextArea.visible=false;"/>
</mx:Application>
The event listenr for the click event for the Button control alternates making the VBox
container visible and invisible. When the VBox container becomes invisible, it uses the
ZoomRotateShow effect as its hide effect, and when it becomes invisible, it uses the
ZoomRotateHide effect.
Notice that the VBox container sets the autoLayout property to false. This setting prevents
Flex from updating the layout of the container while the effect is playing. For more
information, see “Disabling container layout for effects” on page 762.
You can nest <mx:Parallel> and <mx:Sequence> tags inside each other. For example, two
effects can run in parallel, followed by a third effect running in sequence.
<mx:Script>
<![CDATA[
<mx:Button id="myButton1"
label="Show!"
click="aTextArea.visible=true; ZRShow.end(); ZRShow.play();"/>
</mx:Application>
<mx:Rotate id="myRotate"
repeatCount="0"/>
<mx:Image
source="@Embed(source='../assets/myImage.jpg')"
mouseDownEffect="{myRotate}"/>
</mx:Application>
All effects dispatch an effectEnd event when the effect completes. If you repeat the effect,
the effect dispatches the effectEnd event after the final repetition.
If the effect is a tween effect, such as a Fade or Move effect, the effect dispatches both the
tweenEnd effect and the endEffect when the effect completes. If you configure the tween
effect to repeat, the tweenEnd effect occurs at the end of every repetition of the effect, and the
endEffect event occurs after the final repetition.
<mx:Script>
<![CDATA[
<mx:SoundEffect id="soundEmbed"
useDuration="false"
loops="0"
source="{soundClass}"/>
<mx:Button id="myButton2"
label="Sound Embed"
mouseDownEffect="{soundEmbed}"/>
</mx:Application>
In this example, you embed the sound1.mp3 file in your application. That means the file is
compiled into the SWF file.
The SoundEffect class has several properties that you can use to control the playback of the
MP3 file, including useDuration and loops. The useDuration property specifies whether
to use the duration property to control the play time of the MP3 file. If the useDuration
property is true, the MP3 file will play for as long as the time specified by the duration
property, which defaults to 500 ms. If you set useDuration to false, the MP3 file plays to
completion.
The loops property specified the number of times to repeat the MP3 file, where a value of 0
means play the effect once, a value of 1 means play the effect twice, and so on. If you repeat
the MP3 file, it still uses the setting of the useDuration property to determine the playback
time.
The duration property takes precedence over the loops property. If the effect duration is not
long enough to play the sound at least once, then the sound will not loop.
The SoundEffect class also defines the following events:
complete Dispatched when the sound file completes loading.
id3 Dispatched when ID3 data is available for an MP3 sound file.
ioError Dispatched when an error occurs during the loading of the sound file.
Often, you use these effects with the showEffect and hideEffect triggers The showEffect
trigger occurs when a component becomes visible by changing its visible property from
false to true. The hideEffect trigger occurs when the component becomes invisible by
changing its visible property from true to false. When using a mask effect with the
showEffect or hideEffect triggers, you can ignore the showTarget property; Flex sets it for
you automatically.
As the mask effect executes, the effect either covers the target component or uncovers it, based
on the setting of the showTarget property. The following diagram shows the action of the
WipeLeft effect for the two different settings of the showTarget property:
showTarget=false showTarget=true
initial mask
mask
effect completed
mask
mask direction
return myMask;
}
Your custom mask function takes an argument that corresponds to the target component of
the effect, and a second argument that defines the dimensions of the target so that you can
correctly size the mask. The function returns a single Shape object that defines the mask.
<mx:Script>
<![CDATA[
<mx:WipeLeft id="customWL"
createMaskFunction="createLargeMask"
showTarget="false"/>
<mx:WipeLeft id="standardWL"
showTarget="false"/>
<mx:HBox borderStyle="solid"
paddingLeft="10" paddingRight="10"
paddingTop="10" paddingBottom="10">
</mx:HBox>
</mx:Application>
The event object passed to the event listener for these event is of type EffectEvent. The
EffectEvent class is a subclass of the Event class, and contains all of the properties inherited
from Event, including target, and type, and defines a new property named
effectInstance, where:
target Contains a reference to the Effect object that dispatched the event. This is the factory
class of the effect.
type Either EffectEvent.EFFECT_END or EffectEvent.EFFECT_START, depending on the
event.
effectInstance Contains a reference to the EffectInstance object. This is the object defined
by the instance class for the effect. Flex creates one object of the instance class for each target
of the effect. You access the target component of the effect using the
effectInstance.target property.
<mx:Script>
<![CDATA[
import mx.effects.*;
import mx.events.EffectEvent;
import mx.core.UIComponent;
myTA.text = effectTarget.id;
myTA.text = myTA.text + " " + eventObj.type;
}
]]>
</mx:Script>
<?xml version="1.0"?>
<!-- behaviors\EventEffects.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" >
<mx:Script>
<![CDATA[
import mx.effects.*;
import mx.events.EffectEvent;
import mx.core.UIComponent;
private function
endSlowFadeEffectListener(eventObj:EffectEvent):void
{
// Access the effect object.
var effectObj:Effect = Effect(eventObj.target);
<mx:Fade id="slowFade"
duration="2000"
effectEnd="endSlowFadeEffectListener(event);"/>
An easing function takes four arguments, following the function signature popularized by
Robert Penner. For more information, see www.ericd.net/chapter7.pdf.
<mx:Script>
import mx.effects.easing.*;
</mx:Script>
<mx:Accordion
openEasingFunction="{Bounce.easeOut}"
openDuration="2000">
<mx:VBox label="Pane 1" width="400" height="400"/>
<mx:VBox label="Pane 2" width="400" height="400"/>
</mx:Accordion>
</mx:Application>
<mx:Script>
<![CDATA[
private function myEasingFunction(t:Number, b:Number,
c:Number, d:Number):Number {
if ((t /= d) < (1 / 2.75)) {
return c * (7.5625 * t * t) + b;
}
else if (t < (2 / 2.75)) {
return c * (7.5625 * (t-=(1.5/2.75)) * t + .75) + b;
}
else if (t < (2.5 / 2.75)) {
return c * (7.5625 * (t-=(2.25/2.75)) * t + .9375) + b;
}
else {
return c * (7.5625 * (t-=(2.625/2.75)) * t + .984375) + b;
}
};
]]>
</mx:Script>
<mx:Move id="moveLeftShow"
xFrom="600" xTo="0" yTo="0"
duration="3000"
easingFunction="myEasingFunction"/>
<mx:Move id="moveRightHide"
xFrom="0" xTo="600"
duration="3000"
easingFunction="myEasingFunction"/>
<mx:LinkBar dataProvider="myVS"/>
<mx:ViewStack id="myVS" borderStyle="solid">
<mx:Canvas id="Canvas0" label="Canvas0"
creationCompleteEffect="{moveLeftShow}"
showEffect="{moveLeftShow}"
hideEffect="{moveRightHide}" >
<mx:Box height="300" width="600" backgroundColor="#00FF00">
<mx:Label text="Screen 0" color="#FFFFFF" fontSize="40"/>
</mx:Box>
</mx:Canvas>
<mx:Canvas id="Canvas1" label="Canvas1"
showEffect="{moveLeftShow}" hideEffect="{moveRightHide}" >
In the next example, the image is centered in the HBox container. If you apply a Zoom effect
to the image, as it resizes, it remains centered in the HBox container.
<mx:HBox horizontalAlign="center" verticalAlign="middle">
<mx:Image source="myImage.jpg"/>
</mx:HBox>
By default, the size of the HBox container is big enough to hold the image at it original size. If
you disable layout updates, and use the Zoom effect to enlarge the image, or use the Move
effect to reposition the image, the image might extend past the boundaries of the HBox
container, as the following example shows:
<mx:HBox autoLayout="false">
<mx:Image source="myImage.jpg"/>
</mx:HBox>
You set the autoLayout property to false, so the HBox container does not resize as the
image resizes. If the image grows to a size so that it extends beyond the boundaries of the
HBox container, the container adds scroll bars and clips the image at its boundaries.
To prevent the scroll bars from appearing, you can use the height and width properties to
explicitly size the HBox container so that it is large enough to hold the modified image.
Alternatively, you can set the clipContent property of the container to false so that the
image can extend past its boundaries.
<mx:HBox>
<mx:Panel id="panelOne" mouseDownEffect="{myResize}">
<mx:Button/>
<mx:Button/>
<mx:Button/>
<mx:Button/>
<mx:Button/>
</mx:Panel>
<mx:Panel id="panelTwo" mouseDownEffect="{myResize}">
<mx:Button/>
<mx:Button/>
<mx:Button/>
<mx:Button/>
<mx:Button/>
</mx:Panel>
<mx:Panel id="panelThree" mouseDownEffect="{myResize}">
<mx:Button/>
<mx:Button/>
<mx:Button/>
<mx:Button/>
<mx:Button/>
</mx:Panel>
</mx:HBox>
</mx:Application>
CHAPTER 20
Contents
About styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 767
Using external style sheets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 796
Using local style definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 797
Using the StyleManager class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 800
Using the setStyle() and getStyle() methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 807
Using inline styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 812
Loading style sheets at run time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 814
Using filters in Flex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .823
About themes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .828
About styles
You modify the appearance of Flex components through style properties. These properties can
define the size of a font used in a Label control, or the background color used in the Tree
control. In Flex, some styles are inherited from parent containers to their children, and across
style types and classes. This means that you can define a style once, and then have that style
apply to all controls of a single type or to a set of controls. In addition, you can override
individual properties for each control at a local, component, or global level, giving you great
flexibility in controlling the appearance of your applications.
767
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
This section introduces you to applying styles to controls. It also provides a primer for using
Cascading Style Sheets (CSS), an overview of the style value formats (Length, Color, and
Time), and describes style inheritance. Subsequent sections provide detailed information
about different ways of applying styles in Flex.
Flex does not support controlling all aspects of component layout with CSS. Properties such
as x, y, width, and height are properties, not styles, of the UIComponent class and,
therefore, cannot be set in CSS. Other properties, such as left, right, top, and bottom are
style properties and are used to manipulate a component’s location in a container.
For more information on using external style sheets, see “Using external style sheets”
on page 796.
Flex includes a global style sheet, defaults.css, inside the framework.swc file. This file contains
style definitions for the global class selector, and type selectors for most Flex components. For
more information about defaults.css, see “About the default style sheet” on page 797.
Flex also includes several other style sheets that each have a unique look and feel. For more
information, see “About the included theme files” on page 830.
<mx:Script><![CDATA[
public function initApp():void {
StyleManager.getStyleDeclaration("Button").setStyle("fontSize",15);
StyleManager.getStyleDeclaration("Button").setStyle("color",0x9933FF);
}
]]></mx:Script>
<mx:Script><![CDATA[
public function initApp():void {
myButton.setStyle("fontSize",15);
myButton.setStyle("color",0x9933FF);
}
]]></mx:Script>
Inline styles
Use attributes of MXML tags to apply style properties. These properties apply only to the
instance of the control. This is the most efficient method of applying instance properties
because no ActionScript code blocks or method calls are required.
The following example sets the fontSize to 15 and the color to 0x9933FF on the myButton
instance:
<?xml version="1.0"?>
<!-- styles/InlineExample.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Button id="myButton" color="0x9933FF" fontSize="15" label="Click
Here"/>
</mx:Application>
In an MXML tag, you must use the camel-case version of the style property. For example, you
must use “fontSize” rather than “font-size” (the CSS convention) in the previous
example. For more information on style property names, see “About property and selector
names” on page 782.
As with other style properties, you can bind inline style properties to variables.
For more information on using inline styles, see “Using inline styles” on page 812.
Length format
The Length format applies to any style property that takes a size value, such as the size of a
font (or fontSize). Length is of type Number.
The Length type has the following syntax:
length[length_unit]
Spaces are not allowed between the length value and the unit.
in Absolute Inches.
cm Absolute Centimeters.
mm Absolute Millimeters.
pt Absolute Points.
pc Absolute Picas.
</mx:Application>
<mx:Script><![CDATA[
public function initApp():void {
myTree.setStyle("selectionDuration", 100);
}
]]></mx:Script>
<mx:XMLList id="treeData">
<node label="Mail Box">
<node label="Inbox">
<node label="Marketing"/>
<node label="Product Management"/>
<node label="Personal"/>
</node>
<node label="Outbox">
<node label="Professional"/>
<node label="Personal"/>
</node>
<node label="Spam"/>
<node label="Sent"/>
</node>
</mx:XMLList>
Format Description
hexadecimal Hexadecimal colors are represented by a six-digit code preceded by either a
zero and small x (0x) or a pound sign (#). The range of valid values is 0x000000
to 0xFFFFFF (or #000000 to #FFFFFF).
You use the 0x prefix when defining colors in calls to the setStyle() method
and in MXML tags. You use the # prefix in CSS style sheets and in <mx:Style>
tag blocks.
RGB RGB colors are a mixture of the colors red, green, and blue, and are
represented in percentages of the color’s saturation. The format for setting
RGB colors is color:rgb(x%, y%, z%), where the first value is the percentage
of red saturation, the second value is the percentage of green saturation, and
the third value is the percentage of blue saturation.
You can use the RGB format only in style sheet definitions.
VGA color VGA color names are a set of 16 basic colors supported by all browsers that
names support CSS. The available color names are Aqua, Black, Blue, Fuchsia, Gray,
Green, Lime, Maroon, Navy, Olive, Purple, Red, Silver, Teal, White, Yellow.
You can use the VGA color names format in style sheet definitions and inline
style declarations.
VGA color names are not case-sensitive.
Color formats are of type Number. When you specify a format such as a VGA color name,
Flex converts that String to a Number.
<mx:XMLList id="treeData">
<node label="Mail Box">
<node label="Inbox">
<node label="Marketing"/>
<node label="Product Management"/>
<node label="Personal"/>
</node>
<node label="Outbox">
<node label="Professional"/>
<node label="Personal"/>
</node>
<node label="Spam"/>
<node label="Sent"/>
</node>
</mx:XMLList>
<mx:Tree id="myOtherTree"
width="100%"
labelField="@label"
dataProvider="{treeData}"
depthColors="[0xFFCC33, 0xFFCC99, 0xCC9900]"
alternatingItemColors="['red', 'green']"
/>
</mx:Panel>
</mx:Application>
This example also shows that you can set the properties that use Arrays inline.
<mx:Array id="myDepthColors">
<mx:Object>0xFFCC33</mx:Object>
<mx:Object>0xFFCC99</mx:Object>
<mx:Object>0xCC9900</mx:Object>
</mx:Array>
<mx:Array id="myAlternatingRowColors">
<mx:Object>red</mx:Object>
<mx:Object>green</mx:Object>
</mx:Array>
<mx:XMLList id="treeData">
<node label="Mail Box">
<node label="Inbox">
<node label="Marketing"/>
<node label="Product Management"/>
<node label="Personal"/>
</node>
<node label="Outbox">
<node label="Professional"/>
<node label="Personal"/>
</node>
<node label="Spam"/>
<node label="Sent"/>
</node>
</mx:XMLList>
The names of class selectors cannot include hyphens in Flex. If you use a hyphenated
class selector name, such as my-class-selector, Flex ignores the style.
You can programmatically define new class and type selectors using the StyleManager class.
For more information, see “Using the StyleManager class” on page 800.
<mx:Script><![CDATA[
public function changeStyles(e:Event):void {
StyleManager.getStyleDeclaration('.myFontStyle').setStyle('color',0x3399CC)
;
}
]]></mx:Script>
</mx:Application>
You do not precede the class selector with a period when you use the styleName property for
inline styles.
<mx:Style source="../assets/SimpleTypeSelector.css"/>
<mx:Style>
Button {
fontSize: 15;
}
</mx:Style>
<mx:Button id="myButton" label="Click Here"/>
</mx:Application>
<mx:Style>
Label {
fontSize: 10pt;
}
.myLabel {
color: Blue;
}
</mx:Style>
</mx:Application>
If you later remove one of the selectors (for example, call the StyleManager’s
clearStyleDeclaration() method on the type or class selector), the other selector’s style
settings remain.
<mx:Style>
VBox {
color:blue
}
</mx:Style>
<mx:Style>
Container {
color:red
}
Box {
color:green
}
</mx:Style>
Flex also supports properties that you can define by using CSS syntax and inheritance rules,
but the properties are not part of the CSS property library. For a list of style properties for
each control, view that control’s entry in Adobe Flex Language Reference.
If you did not assign the styleName property to a style declaration, Flex looks for the
property on type selector style declarations. If there are no type selector declarations, Flex
checks the global selector. If all of these checks fail, the property is undefined, and Flex
applies the default style.
<mx:RichTextEditor/>
<mx:ComboBox>
<mx:dataProvider>
<mx:String>2005</mx:String>
<mx:String>2006</mx:String>
<mx:String>2007</mx:String>
</mx:dataProvider>
</mx:ComboBox>
<mx:NumericStepper/>
</mx:Application>
Inheritance exceptions
Not all styles are inheritable, and not all styles are supported by all components and themes.
In general, color and text styles are inheritable, regardless of how they are set (using CSS or
style properties). All other styles are not inheritable unless otherwise noted.
A style is inherited only if it meets the following conditions:
■ The style is supported by the theme. For a list of styles supported by the default Flex
theme, see “About supported styles” on page 794.
</mx:Application>
You should try to limit the number of style sheets used in an application, and set the style
sheet only at the top-level document in the application (the document that contains the
<mx:Application> tag). If you set a style sheet in a child document, unexpected results
can occur.
<mx:Style source="../assets/SimpleTypeSelector.css"/>
Button {
fontStyle: italic;
}
</mx:Style>
<mx:Button id="myButton" styleName="myFontStyle" label="Click Here"/>
</mx:Application>
<mx:Script><![CDATA[
import mx.styles.StyleManager;
public function initApp(e:Event):void {
// Type selector; applies to all Buttons and subclasses
// of Button.
StyleManager.getStyleDeclaration("Button").
setStyle("fontSize",24);
<mx:Button id="myButton"
label="Click Here"
styleName="myStyle"
/>
<mx:Label id="myLabel"
text="This is a label"
styleName="myStyle"
/>
</mx:Application>
N OTE
If you set either an inheritable or noninheritable style to the global style, Flex applies it to
all controls, regardless of their location in the hierarchy.
myDynStyle.setStyle('color', 'blue');
myDynStyle.setStyle('fontFamily', 'georgia');
myDynStyle.setStyle('themeColor', 'green');
myDynStyle.setStyle('fontSize', 24);
</mx:Application>
When you set a new CSSStyleDeclaration on a type selector, you are replacing the entire
existing type selector with your own selector. All style properties that you do not explicitly
define in the new CSSStyleDeclaration are set to null. This can remove skins, margins, and
other properties that are defined in the defaults.css file or other style sheet that you may have
applied already.
myDynStyle.setStyle('color', 'blue');
myDynStyle.setStyle('fontFamily', 'georgia');
myDynStyle.setStyle('themeColor', 'green');
myDynStyle.setStyle('fontSize', 24);
}
]]></mx:Script>
<mx:Button id="myButton"
label="Click Me"
styleName="myButtonStyle"
/>
</mx:Application>
myDynStyle.setStyle('color', 'blue');
myDynStyle.setStyle('fontFamily', 'georgia');
myDynStyle.setStyle('themeColor', 'green');
myDynStyle.setStyle('fontSize', 24);
StyleManager.setStyleDeclaration(".myButtonStyle",
myDynStyle, true);
]]></mx:Script>
<mx:Button id="myButton"
label="Click Me"
styleName="myButtonStyle"
click="resetStyles()"
/>
</mx:Application>
Using the clearStyleDeclaration() method removes only the specified selector’s styles. If
you apply a class selector to a component, and then call the method on that component’s class
selector, the component’s type selector styles remain.
The setStyleDeclaration() and clearStyleDeclaration() methods are
computationally expensive. You can prevent Adobe Flash Player from applying or clearing the
new styles immediately by setting the update parameter to false.
</mx:Application>
When you pass false for the update parameter, Flash Player stores the selector but does not
apply the style. When you pass true for the update parameter, Flash Player recomputes the
styles for every visual component in the application.
Setting styles
The getStyle() method has the following signature:
return_type componentInstance.getStyle(property_name)
The return_type depends on the style that you access. Styles can be of type String, Number,
Boolean, or, in the case of skins, Class. The property_name is a String that indicates the
name of the style property; for example, fontSize, or borderStyle.
The setStyle() method has the following signature:
componentInstance.setStyle(property_name, property_value)
The property_value sets the new value of the specified property. To determine valid values
for properties, see Adobe Flex Language Reference.
<mx:Style>
Button {
color: #66CCFF;
}
</mx:Style>
<mx:Script><![CDATA[
[Bindable]
private var n:Number;
</mx:Application>
<mx:Style>
Button {
color: red;
fontSize: 25;
}
</mx:Style>
<mx:CheckBox id="cb1"
label="Set Style/Unset Style"
click="toggleStyle()"
selected="false"
/>
</mx:Application>
</mx:Application>
You can remove an inline style definition by using the clearStyle() method.
Label {
fontSize: 24;
color: #FF9933;
}
.noMargins {
margin-right: 0;
margin-left: 0;
margin-top: 0;
margin-bottom: 0;
horizontal-gap: 0;
vertical-gap: 0;
}
You cannot load an uncompiled CSS file into your Flex application at run time. You must
compile it into a SWF file before loading it.
To compile the SWF file with Flex Builder, right click the CSS file and select Compile CSS to
SWF. Flex Builder saves the SWF file in the project’s bin directory.
<mx:Script>
<![CDATA[
import mx.styles.StyleManager;
</mx:Application>
The first parameter of the loadStyleDeclarations() method is the location of the style
sheet to load. The location can be local or remote.
If the style sheet is local (from the same domain as the loading application), you can load it
without any additional settings. If the location of the style sheet is remote (in any domain that
is not an exact match of the loading application’s domain), you must set the third parameter
of the loadStyleDeclarations() method, trustContent, to true. Loading remote style
sheets does not require a crossdomain.xml file that gives the loading application permission to
load the SWF file.
Also, to use remote style sheets, you must compile the loading application with network access
(have the use-network compiler property set to true, the default). If you compile and run
the application on a local file system, you might not be able to load a remotely accessible SWF
file.
The loadStyleDeclarations() method returns an instance of the IEventDispatcher class.
You can use this object to trigger events based on the success of the style sheet’s loading. You
have access to the StyleEvent.PROGRESS, StyleEvent.COMPLETE, and StyleEvent.ERROR
events of the loading process.
<mx:Script>
<![CDATA[
import mx.styles.StyleManager;
import mx.events.StyleEvent;
</mx:Application>
The second parameter of the loadStyleDeclarations() method is update. Set the update
parameter to true to force an immediate update of the styles. Set it to false to avoid an
immediate update of the styles in the application. The styles are updated the next time you
call this method or the unloadStyleDeclarations() method with the update property set
to true.
Each time you call the loadStyleDeclarations() method with the update parameter set to
true, Adobe Flash Player reapplies all styles to the display list, which can degrade
performance. If you load multiple CSS-based SWF files at the same time, you should set the
update parameter to false for all but the last call to this method. As a result, Flash Player
only applies the styles once for all new style SWF files rather than once for each new style
SWF.
<mx:Script>
<![CDATA[
import mx.styles.StyleManager;
import mx.events.StyleEvent;
</mx:Application>
<mx:CheckBox id="cb1"
label="Load style sheet"
click="toggleStyleSheet()"
selected="false"
/>
</mx:Application>
import mx.controls.Button;
import mx.events.*;
import mx.styles.StyleManager;
3. Compile the style SWF file. Add the theme SWC file to the style SWF file by using the
include-libraries option, as the following example shows:
$ mxmlc -include-libraries=haloclassic.swc haloclassic.css
If you have multiple CSS files inside a theme SWC file, you must extract all of them before
compiling the style SWF file.
Filters are in the flash.filters.* package, and include the DropShadowFilter, GlowFilter, and
BlurFilter classes. To apply a filter to a component with MXML, you add the flash.filters
package to the local namespace. You then set the value of the Flex component’s filters
property to the filter class. The filters property is a property inherited from the
DisplayObject class.
The following example applies a drop shadow to a Label control by using expanded MXML
syntax and inline syntax:
<?xml version="1.0"?>
<!-- styles/ApplyFilterInline.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:flash="flash.filters.*">
<!-- Apply filter using MXML syntax to set properties. -->
<mx:Label text="DropShadowFilter" fontSize="20">
<mx:filters>
<flash:DropShadowFilter distance="10" angle="45"/>
</mx:filters>
</mx:Label>
applyFilters();
}
<mx:RichTextEditor id="rte1"/>
<mx:DateChooser id="dc1"/>
<mx:HSlider id="hs1"/>
<mx:Script>
<![CDATA[
private function getBitmapFilter():DropShadowFilter {
var distance:Number = 3;
var angle:Number = 90;
var color:Number = 0x000000;
var alpha:Number = 1;
var blurX:Number = 8;
var blurY:Number = 8;
var strength:Number = 0.65;
var quality:Number = BitmapFilterQuality.LOW;
var inner:Boolean = false;
var knockout:Boolean = false;
About themes
A theme defines the look and feel of a Flex application. A theme can define something as
simple as the color scheme or common font for an application, or it can be a complete
reskinning of all the components used by the application.
Themes usually take the form of a SWC file. However, themes can also be a CSS file and
embedded graphical resources, such as symbols from a SWF file. Theme SWC files can also be
compiled into style SWF files so that they can be loaded at run time. For more information,
see “Using theme SWC files as run-time style sheets” on page 822.
To apply the contents of that SWC file to your Flex application, use the instructions in “Using
themes” on page 828. To create your own theme, use the instructions in “Creating a theme
SWC file” on page 830. You can affect the theme of a Flex application without creating a new
theme. You do this with the themeColor property. For more information, see “Creating
themes” on page 890.
The default theme, Halo, is a combination of graphical and programmatic skins in a SWC
file. It is defined by the defaults.css file in the framework.swc file. This file sets many
properties of the Flex components. In some cases it uses classes in the mx.skins.halo package.
Flex also includes several predefined themes that you can apply to your applications. For more
information, see “About the included theme files” on page 830.
Using themes
Themes generally take the form of a theme SWC file. These SWC files contain style sheets
and skinning assets. You use the assets inside theme SWC files for programmatic skins or
graphical assets, such as SWF, GIF, or JPEG files. Themes can also contain just stand-alone
CSS files.
Packaging a theme as a SWC file rather than as a loose collection of files has the following
benefits:
■ SWC files are easier to distribute.
■ SWC files cannot be modified and reapplied to the application without recompiling.
When you add a SWC file to the list of themes, the compiler adds the classes in the SWC file
to the application’s library-path, and applies any CSS files contained in the SWC file to
your application. The converse is not true, however. If you add a SWC file to the library-
path, but do not specify that SWC file with the theme option, the compiler does not apply
CSS files in that SWC file to the application.
For more information on using Flex compilers, see Chapter 9, “Using the Flex Compilers,” in
Building and Deploying Flex Applications.
You can specify more than one theme file to be applied to the application. If there are no
overlapping styles, both themes are applied completely. The ordering of the theme files is
important, though. If you specify the same style property in more than one theme file, Flex
uses the property from the last theme in the list. In the following example, style properties in
the Wooden.css file take precedence, but unique properties in the first two theme files are also
applied:
<compiler>
<theme>
<filename>../themes/Institutional.css</filename>
<filename>../themes/Ice.css</filename>
<filename>../themes/Wooden.css</filename>
</theme>
</compiler>
Theme Description
Aeon Graphical Contains the AeonGraphical.css file and the AeonGraphical.swf file. This
is the graphical version of the default Halo theme, which is defined by
the defaults.css file and graphical assets inside the framework.swc file.
The source FLA file for the graphical assets is in the AeonGraphical
Source directory. You change the graphical assets in this file by using
the Flash IDE. You must ensure that you export the SWF file, which is
used by the theme in Flex.
This theme is provided as a starting point for graphically reskinning your
application. While it might be more efficient, you lose some ability to
apply run-time styles if you use it.
Halo Provides the default Flex look and feel. The Halo theme uses the
defaults.css file in the framework.swc file and the classes in the
mx.skins.halo package.
This is the default theme.
For more information about the default theme assets, see “About the
default style sheet” on page 797.
HaloClassic Provides the look and feel of previous versions of Flex. This theme
comprises the haloclassic.swc file. Included in this file are the CSS file
and SWF file that provide graphical assets.
The name you provide for the Embed keyword is the same name that you use for the skin asset
when compiling the SWC file.
To add programmatic skin classes to the theme’s CSS file, you use the ClassReference
statement to specify the class name (not the file name), as the following example shows:
Button {
upSkin:ClassReference('myskins.ButtonSkin');
downSkin:ClassReference('myskins.ButtonSkin');
overSkin:ClassReference('myskins.ButtonSkin');
}
In the preceding example, all skins are defined by a single programmatic skin class file. For
more information on creating programmatic skins, see “Creating programmatic skins”
on page 903.
The CSS file can include any number of class selectors, as well as type selectors. Style
definitions for your theme do not have to use skins. You can simply set style properties in the
style sheet, as the following example shows:
ControlBar {
borderStyle: "controlBar";
paddingBottom: 10;
paddingLeft: 10;
paddingRight: 10;
paddingTop: 10;
verticalAlign: "middle";
}
This type selector for ControlBar components is taken from the default style sheet,
defaults.css, inside the framework.swc file. It can be a good place to start when designing a
theme. For more information about defaults.css, see “About the default style sheet”
on page 797.
You also specify the CSS file as a resource to include in the theme SWC file. You must include
the .css extension when you provide the name of the CSS file, otherwise Flex does not
recognize it as a style sheet and does not apply it to your application.
You use the component compiler to compile theme assets, such as a style sheet and graphical
skins, into a SWC file. The following example compiles a theme by using the compc
command-line compiler:
compc -include-file mycss.css c:/myfiles/themes/mycss.css
-include-file upIcon.jpg c:/myfiles/themes/assets/upIcon.jpg
-include-file downIcon.jpg c:/myfiles/themes/assets/downIcon.jpg
-include-file overIcon.jpg c:/myfiles/themes/assets/overIcon.jpg
-o c:/myfiles/themes/MyTheme.swc
You can pass a list of classes to the include-classes option by space-delimiting each class, as
the following example shows:
-include-classes MyButtonSkin MyControlBarSkin MyAccordionHeaderSkin
For more information about creating skin classes, see Chapter 22, “Creating Skins,” on
page 879.
You can use the configuration file with compc by using the load-config option, as the
following example shows:
compc -load-config myconfig.xml
You can also pass a configuration file to the Flex Builder component compiler. For more
information on using the component compilers, see Chapter 9, “Using the Flex Compilers,”
in Building and Deploying Flex Applications.
CHAPTER 21
Using Fonts 21
You can include fonts in your Adobe Flex applications. Although it is easier to use the default
device fonts, you can embed other fonts so that you can apply special effects to text-based
controls, such as rotating and fading. This topic describes the differences between device fonts
and embedded fonts. It describes how to efficiently embed double-byte fonts. It also shows
multiple ways that you can embed fonts in your Adobe Flex applications, from using
Cascading Style Sheets (CSS) syntax to using fonts embedded inside external SWF files.
Contents
About fonts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .835
Using device fonts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 837
Using embedded fonts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .838
Using multiple typefaces. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .853
About the font managers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .858
Setting character ranges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .858
Embedding double-byte fonts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .862
Embedding fonts from SWF files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .862
Troubleshooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 874
About fonts
When you compile a Flex application, the application stores the names of the fonts that you
used to create the text. Adobe Flash Player 9 uses the font names to locate identical or similar
fonts on the user’s system when the Flex application runs. You can also embed fonts in the
Flex application so that the exact font is used, regardless of whether the client’s system has that
font.
You define the font that appears in each of your components by using the fontFamily style
property. You can set this property in an external style sheet, a <mx:Style> block, or inline.
This property can take a list of fonts, as the following example shows:
835
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
.myClass {
fontFamily: Arial, Helvetica;
color: Red;
fontSize: 22;
fontWeight: bold;
}
If the client’s system does not have the first font in the list, Flash Player attempts to find the
second, and so on, until it finds a font that matches. If no fonts match, Flash Player makes a
best guess to determine which font the client uses.
Fonts are inheritable style properties. So, if you set a font style on a container, all controls
inside that container inherit that style, as the following example shows:
<?xml version="1.0"?>
<!-- fonts/InheritableExample.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Style>
VBox {
fontFamily: Helvetica;
fontSize: 18pt;
}
HBox {
fontFamily: Times;
fontSize: 18pt;
}
</mx:Style>
You must surround device font names with quotation marks when defining them with
style declarations.
Using device fonts does not impact the size of the SWF file because the fonts reside on the
client. However, using device fonts can impact performance of the application because it
requires that Flash Player interact with the local operating system. Also, if you use only device
fonts, your selection is limited to three fonts.
Check your font licenses before embedding any font files in your Flex applications. Fonts
might have licensing restrictions that preclude them from being stored as vector
information.
If you attempt to embed a font that the Flex compiler cannot find, Flex throws an error and
your application does not compile.
The src property specifies how the compiler should look for the font, and the name of the
font to look for. You can either load a font by its filename (by using src:url) or by its system
font name (by using src:local). This property is required. For more information, see
“Locating embedded fonts” on page 842.
The following example embeds that same font, but by using its system font name:
@font-face {
src:local("Myriad Web Pro");
fontFamily: myFontFamily;
advancedAntiAliasing: true;
}
VBox {
fontFamily: myFontFamily;
}
</mx:Style>
Attribute Description
url Embeds a TrueType font by location by specifying a valid URI to the font. The
URI can be relative (for example, ../fontfolder/akbar.ttf) or absolute (for
example, c:/myfonts/akbar.ttf).
You must specify the url or local function of the src descriptor in the @font-face
declaration. All other descriptors are optional. In general, you should use url rather than
local, because pointing to a file is more reliable than using a reference controlled by the
operating system.
Do not mix embedded and nonembedded fonts in the same fontFamily descriptor.
<mx:Script>
/*
* Embed a font by location.
*/
[Embed(source='../assets/MyriadWebPro.ttf',
fontName='myMyriadFont',
mimeType='application/x-font'
)]
// You do not use this variable directly. It exists so that
// the compiler will link in the font.
private var font1:Class;
/*
* Embed a font with bold typeface by location.
*/
[Embed(source='../assets/MyriadWebPro-Bold.ttf',
fontWeight='bold',
fontName='myBoldMyriadFont',
mimeType='application/x-font',
flashType='true'
)]
private var font2:Class;
</mx:Script>
<mx:Script>
/*
* Embed a font by name.
*/
[Embed(systemFont='Myriad Web Pro',
fontName='myPlainFont',
mimeType='application/x-font'
)]
// You do not use this variable directly. It exists so that
// the compiler will link in the font.
private var font1:Class;
/*
* Embed a font with italic typeface by name.
*/
[Embed(systemFont='Myriad Web Pro',
fontStyle='italic',
fontName='myItalicFont',
mimeType='application/x-font',
flashType='true'
)]
private var font2:Class;
</mx:Script>
To get the system font name in Windows, install the Font properties extension. Then
right-click on the font’s file in Windows Explorer and select the Names tab. Use the value
under Font Family Name as the systemFont value.
You can specify a subset of the font’s character range by specifying the unicodeRange
parameter in the [Embed] metadata tag or the @font-face declaration. Embedding a range of
characters rather than using the default of all characters can reduce the size of the embedded
font and, therefore, reduce the final output size of your SWF file. For more information, see
“Setting character ranges” on page 858.
fontSharpness Sets the sharpness property of internal TextFields. The valid values
are numbers from -400 to 400. The default value is 0.
This property has the same effect as the fontSharpness style property
on the TextField control for system fonts, only it applies when you
embed fonts with advanced anti-aliasing.
Changing the value of this property has no effect unless the
fontAntiAliasType property is set to advanced.
fontThickness Sets the thickness property of internal TextFields. The valid values
are numbers from -200 to 200. The default value is 0.
This property has the same effect as the fontThickness style property
on the TextField control for system fonts, only it applies when you
embed fonts with advanced anti-aliasing.
Changing the value of this property has no effect unless the
fontAntiAliasType property is set to advanced.
.myStyle1 {
fontFamily: myPlainFont;
fontSize:12pt
}
</mx:Style>
<mx:Script><![CDATA[
import mx.managers.SystemManager;
import flash.text.TextFormat;
<mx:Form>
@font-face {
src:url("../assets/MyriadWebPro-Bold.ttf");
fontFamily: myFont;
fontWeight: bold;
flashType: true;
}
@font-face {
src:url("../assets/MyriadWebPro-Italic.ttf");
fontFamily: myFont;
fontStyle: italic;
flashType: true;
}
.myPlainStyle {
fontSize: 32;
fontFamily: myFont;
}
.myBoldStyle {
fontSize: 32;
fontFamily: myFont;
fontWeight: bold;
}
.myItalicStyle {
fontSize: 32;
fontFamily: myFont;
fontStyle: italic;
}
</mx:Style>
<mx:Script><![CDATA[
private function listFonts():void {
var fontArray:Array = Font.enumerateFonts(false);
for(var i:int = 0; i < fontArray.length; i++) {
<mx:VBox>
<mx:Label text="Plain Label" styleName="myPlainStyle"/>
<mx:Label text="Italic Label" styleName="myBoldStyle"/>
<mx:Label text="Bold Label" styleName="myItalicStyle"/>
</mx:VBox>
</mx:Application>
The following list shows the output:
name: myFont; typeface: regular; type: embedded
name: myFont; typeface: bold; type: embedded
name: myFont; typeface: italic; type: embedded
@font-face {
/* Note the different filename for boldface. */
src:url("../assets/MyriadWebPro-Bold.ttf");
fontFamily: myFont; /* Notice that this is the same alias. */
fontWeight: bold;
flashType: true;
}
@font-face {
/* Note the different filename for italic face. */
src:url("../assets/MyriadWebPro-Italic.ttf");
fontFamily: myFont; /* Notice that this is the same alias. */
fontStyle: italic;
flashType: true;
}
.myPlainStyle {
fontSize: 32;
fontFamily: myFont;
}
.myBoldStyle {
fontSize: 32;
fontFamily: myFont;
fontWeight: bold;
}
.myItalicStyle {
fontSize: 32;
fontFamily: myFont;
fontStyle: italic;
}
</mx:Style>
<mx:VBox>
<mx:Label text="Plain Label" styleName="myPlainStyle"/>
<mx:Label text="Italic Label" styleName="myItalicStyle"/>
<mx:Label text="Bold Label" styleName="myBoldStyle"/>
</mx:VBox>
</mx:Application>
Optionally, you can apply the boldface or oblique type to controls inline, as the following
example shows:
<?xml version="1.0"?>
<!-- fonts/MultipleFacesAppliedInline.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Style>
@font-face {
src:url("../assets/MyriadWebPro.ttf");
fontFamily: myFont;
flashType: true;
}
@font-face {
src:url("../assets/MyriadWebPro-Bold.ttf");
fontFamily: myFont;
fontWeight: bold;
flashType: true;
}
@font-face {
src:url("../assets/MyriadWebPro-Italic.ttf");
fontFamily: myFont;
fontStyle: italic;
flashType: true;
}
.myStyle1 {
fontSize: 32;
fontFamily: myFont;
}
</mx:Style>
<mx:VBox styleName="myStyle1">
<mx:Label text="Plain Label"/>
<mx:Label text="Italic Label" fontStyle="italic"/>
<mx:Label text="Bold Label" fontWeight="bold"/>
</mx:VBox>
</mx:Application>
@font-face {
src:local("Myriad Web Pro");
fontFamily: myItalicFont;
fontStyle: italic;
flashType: true;
}
.mystyle1 {
fontFamily:myPlainFont;
fontSize: 32pt;
}
.mystyle2 {
fontFamily:myItalicFont;
fontSize: 32pt;
fontStyle: italic;
}
</mx:Style>
In the @font-face definition, you can specify whether the font is boldface or italic font by
using the fontWeight and fontStyle descriptors. For a bold font, you can set fontWeight
to bold or an integer greater than or equal to 700. You can specify the fontWeight as plain
or normal for a nonboldface font. For an italic font, you can set fontStyle to italic or
oblique. You can specify the fontStyle as plain or normal for a nonitalic face. If you do
not specify a fontWeight or fontStyle, Flex assumes you embedded the plain or regular font
face.
You can also add any other descriptors for the embedded font, such as fontSize, to the
selector, as you would with any class or type selector.
By default, Flex includes the entire font definition for each embedded font in the application,
so you should limit the number of fonts that you use to reduce the size of the application. You
can limit the size of the font definition by defining the character range of the font. For more
information, see “Setting character ranges” on page 858.
The preference of <manager> elements is in reverse order. This means that by default the
Batik font manager is the preferred font manager. However, the Batik font manager does not
support system fonts, therefore, the JRE font manager is also available to handle these cases.
If you experience compilation errors errors related to fonts, you should first try reversing the
order of the font managers in the flex-config.xml file or by using the command-line compiler
arguments.
TextArea {
fontFamily: myFontFamily;
fontSize: 32;
}
</mx:Style>
In your MXML file, you point to the defined ranges by using the unicodeRange attribute of
the @font-face declaration, as the following example shows:
@font-face {
fontFamily: myPlainFont;
src: url("../assets/MyriadWebPro.ttf");
advancedAntiAliasing: true;
unicodeRange: "englishRange";
}
Flex includes a file that lists convenient mappings of the Flash UnicodeTable.xml character
ranges for use in the Flex configuration file. For Adobe LiveCycle Data Services ES, the file is
located at flex_app_root/WEB-INF/flex/flash-unicode-table.xml; for Adobe Flex SDK, the file
is located at flex_install_dir/frameworks/flash-unicode-table.xml.
The following example shows the predefined range Latin 1:
<language-range>
<lang>Latin I</lang>
<range>U+0020,U+00A1-U+00FF,U+2000-U+206F,U+20A0-U+20CF,U+2100-U+2183
</range>
</language-range>
To make ranges listed in the flash-unicode-table.xml file available in your Flex applications,
copy the ranges from this file and add them to the flex-config.xml files.
The following example embeds the same font twice, restricting each to a different character
ranges. The first font only includes support for the letters A and B. The second font family
includes all 128 glyphs in the Basic Latin block.
<?xml version="1.0"?>
<!-- charts/CharacterRangeDetection.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="checkCharacterSupport();">
<mx:Style>
@font-face{
font-family: myABFont;
flashType: true;
src:url("../assets/MyriadWebPro.ttf");
/* Limit range to the letters A and B. */
unicodeRange: U+0041-U+0042;
}
@font-face{
font-family: myWideRangeFont;
flashType: true;
src:url("../assets/MyriadWebPro.ttf");
/* Set range to the 128 characters in
the Basic Latin block. */
unicodeRange: U+0041-U+007F;
}
</mx:Style>
<mx:Script><![CDATA[
public function checkCharacterSupport():void {
var fontArray:Array = Font.enumerateFonts(false);
for(var i:int = 0; i < fontArray.length; i++) {
var thisFont:Font = fontArray[i];
if (thisFont.hasGlyphs("DHARMA")) {
trace(thisFont.fontName +
" supports these glyphs");
} else {
trace(thisFont.fontName +
" does not support these glyphs");
}
}
}
]]></mx:Script>
</mx:Application>
To use this language in your Flex application, copy the character range to the flex-config.xml
file or pass it on the command line by using the fonts.languages.language-range option.
Add the full definition as a child tag to the <languages> tag, as the following example shows:
<flex-config>
<fonts>
<languages>
<language-range>
<lang>thai</lang>
<range>U+0E01-U+0E5B</range>
</language-range>
</languages>
</fonts>
...
</flex-config>
You can change the value of the <lang> element to anything you want. When you embed the
font by using CSS, you refer to the language by using this value in the unicodeRange
property of the @font-face declaration, as the following example shows:
@font-face {
fontFamily:"Thai_font";
src: url("../assets/THAN.TTF"); /* Embed from file */
advancedAntiAliasing: true;
unicodeRange:"thai"
}
5. In the Properties panel, select Dynamic Text drop-down list to make this text dynamic.
6. If you use advanced anti-aliasing in your fonts, ensure that either the Anti-Alias for
Readability or Custom Anti-Alias option is the selected anti-aliasing mode. If you select any
other option, Flash does not include advanced anti-aliasing information with your fonts’
SWF file. For more information about using advanced anti-aliasing, see “Using advanced
anti-aliasing” on page 847.
7. In the Properties panel, click the Embed button.
The Character Embedding dialog box appears:
8. Select one or more ranges to use. Select only the ranges that are necessary.
To embed fonts from a Flash 8 SWF file into your Flex application:
1. Embed each typeface with an @font-face declaration, as the following example shows:
<mx:Style source="../assets/FlashTypeStyles.css"/>
<!-- Rotate the Text controls. If the text disappears when the control is
rotated, then the font is not properly embedded. -->
<mx:Button label="Rotate +1" click="++text1.rotation;++text2.rotation;
++text3.rotation;"/>
<mx:Script><![CDATA[
[Embed(source='../assets/MyriadWebProEmbed.swf',
fontName='Myriad Web Pro'
)]
private static var plainFont:Class;
[Embed(source='../assets/MyriadWebProEmbedWithFontSymbols.swf',
fontName='Myriad Web Pro',
fontStyle='italic'
)]
private static var italicFont:Class;
[Embed(source='../assets/MyriadWebProEmbedWithFontSymbols.swf',
fontName='Myriad Web Pro',
fontWeight='bold'
]]></mx:Script>
<!-- Rotate the Text controls. If the text disappears when the control is
rotated, then the font is not properly embedded. -->
<mx:Button
label="Rotate +1"
click="++text1.rotation;++text2.rotation;++text3.rotation;"
/>
<mx:Button
label="Rotate -1"
click="--text1.rotation;--text2.rotation;--text3.rotation;"
/>
</mx:Application>
You must define a variable of type Class so that the compiler links the fonts into the final Flex
application SWF file. This example sets the value of the static fontPlain, fontBold, and
fontItalic variables, but they are not used in the rest of the application.
When you use the [Embed] statement to embed fonts in your Flex application, you must still
define styles for those fonts so that those styles can be applied to Flex components, as you
would if you embedded the fonts with the @font-face declarations.
You can also access fonts from SWF files as a Font Symbol.
<mx:Script><![CDATA[
[Embed(source='../assets/MyriadWebProEmbedWithFontSymbols.swf',
symbol='MyriadPlain'
)]
private var font1:Class;
[Embed(source='../assets/MyriadWebProEmbedWithFontSymbols.swf',
symbol='MyriadBold'
)]
private var font2:Class;
[Embed(source='../assets/MyriadWebProEmbedWithFontSymbols.swf',
symbol='MyriadItalic'
)]
private var font3:Class;
]]></mx:Script>
<!-- Rotate the Text controls. If the text disappears when the control is
rotated, then the font is not properly embedded. -->
<mx:Button
label="Rotate +1"
click="++text1.rotation;++text2.rotation;++text3.rotation;"
/>
<mx:Button
label="Rotate -1"
click="--text1.rotation;--text2.rotation;--text3.rotation;"
/>
</mx:Application>
Troubleshooting
There are some techniques that you can use to successfully embed fonts into your Flex
applications.
In many cases, you can resolve the error by changing the font manager. This is set in the
configuration file; for example:
<fonts>
<managers>
<manager-class>flash.fonts.JREFontManager</manager-class>
<manager-class>flash.fonts.BatikFontManager</manager-class>
</managers>
</fonts>
You can try changing the order of font managers, as the following example shows:
<fonts>
<managers>
<manager-class>flash.fonts.BatikFontManager</manager-class>
<manager-class>flash.fonts.JREFontManager</manager-class>
</managers>
</fonts>
Error Solution
Unable to resolve ‘swf_file_name’ Indicates that the font was not found by the compiler.
for transcoding Ensure that the path to the font is correct in the @font-face
declaration or the [Embed] tag, and that the path is
accessible by the compiler.
If you are using the local property to specify the location of
the font in the @font-face declaration, ensure that the font
is locally accessible. Check that it is an entry in the
fonts.properties file or that the font is in the system font
search path. For more information, see “Embedded font
syntax” on page 839.
Font ‘font_name’ with Indicates that the fontName parameter used in the [Embed]
style_description not found statement might not match the name of the font.
For fonts in SWF files, ensure that the spelling and word
spacing of the font name in the list of available fonts in
Flash is the same as the fontName attribute in your [Embed]
statement and the fontFamily property that you use in your
style definitions.
This error can also mean that the font’s style was not
properly embedded in Flash. Open the FLA file and ensure
that there is a text area with the font and style described,
that the text is dynamic, and that you selected a character
range for that text.
Troubleshooting 875
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
@font-face {
src: url(../assets/MyriadWebProEmbed.ttf);
fontFamily: "Myriad Web Pro";
fontWeight: bold;
}
You also must set the fontWeight style property in your style definition:
.myStyle2 {
fontFamily:"Myriad Web Pro";
fontWeight:bold;
fontSize:12pt;
}
If you use the [Embed] statement, you must set the fontWeight property to bold as the
following example shows:
[Embed(source="MyriadWebProEmbed.ttf", fontName="Myriad Web Pro",
fontWeight="bold")]
Troubleshooting 877
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
CHAPTER 22
Creating Skins 22
This topic describes how to add skins to Adobe Flex components by using ActionScript
classes, MXML components, and image files. Image files can contain JPEG, GIF, and PNG
images or SWF files.
Contents
About skinning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 879
Applying skins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 891
Creating graphical skins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 899
Creating programmatic skins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 903
Creating stateful skins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 921
Creating advanced programmatic skins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 930
About skinning
Skinning is the process of changing the appearance of a component by modifying or replacing
its visual elements. These elements can be made up of bitmap images, SWF files, or class files
that contain drawing methods that define vector images.
Skins can define the entire appearance, or only a part of the appearance, of a component in
various states. For example, a Button control has eight possible states, and eight associated
skin properties, as the following example shows:
up upSkin mx.skins.halo.ButtonSkin
879
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
State Skin property Default skin class
selectedDown selectedDownSkin mx.skins.halo.ButtonSkin
The default skins for the up, over, and down states appear as follows:
up over down
Other controls have similar states with associated skins. For example, the RadioButton and
RadioButton controls, which are subclasses of Button, also have an up, down, and over skins.
The ComboBox control has skins the define the appearance of the control when it is in the
disabled, down, and over states.
You create a skin by using a bitmap image, a SWF file, or a class defined in ActionScript or in
MXML. All Flex components have a default skin class that ships with Flex, where a skin class
can represent more than one state of the component. As you can see in the previous table, the
eight states of the Button control use the same default skin class, mx.skins.halo.ButtonSkin, to
draw the skin. Logic within the class determines the appearance of the Button control based
on its current state.
You assign a skin to a component by using style properties. You can set a style property by
using MXML tag properties, the StyleManager class, <mx:Style> blocks, or style sheets. Most
Flex application use style sheets to organize and apply skins. Style sheets can be loaded at
compile time or at run time. For information on loading style sheets at run time, see “Loading
style sheets at run time” on page 814.
Types of skins
You typically define a skin as a bitmap graphic or as a vector graphic. Bitmap graphics, called
graphical skins in Flex, are made up of individual pixels that together form an image. The
downside of a bitmap graphic is that it is typically defined for a specific resolution and, if you
modify the image by scaling or transforming it, you might notice a degradation in image
quality.
Programmatic skins ActionScript or MXML classes that define a skin. To change the
appearance of controls that use programmatic skins, you edit an
ActionScript or MXML file. You can use a single class to define multiple
skins.
For more information, see “Creating programmatic skins” on page 903.
Stateful skins A type of programmatic skin that uses view states, where each view
state corresponds to a state of the component. The definition of the
view state controls the look of the skin. Since you can have multiple
view states in a component, you can use a single component to define
multiple skins.
For more information, see “Creating stateful skins” on page 921.
Creating skins
This section describes the basic steps that you use to create graphical, programmatic, and
stateful skins. Later sections describe this process in more detail.
<mx:Style>
Button {
upSkin: Embed("../assets/orb_up_skin.gif");
}
</mx:Style>
<mx:Style>
Button {
upSkin: Embed("../assets/orb_up_skin.gif");
overSkin: Embed("../assets/orb_up_skin.gif");
}
</mx:Style>
import mx.skins.ProgrammaticSkin;
// Constructor.
public function ButtonUpSkinAS() {
super();
}
<mx:Style>
Button {
upSkin: ClassReference("ButtonUpSkinAS");
}
</mx:Style>
<mx:Script>
<![CDATA[
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void
{
graphics.lineStyle(1, 0x0066FF);
graphics.beginFill(0x00FF00, 0.50);
graphics.drawRoundRect(0, 0, unscaledWidth, unscaledHeight, 10, 10);
}
]]>
</mx:Script>
</skins:ProgrammaticSkin>
Notice that you have to include the xmlns:skins="mx.skins.*" namespace declaration in
MXML. This is necessary because by default you cannot use the ProgrammaticSkin class as
the base class of an MXML component.
import mx.skins.ProgrammaticSkin;
// Constructor.
public function ButtonUpAndOverSkinAS() {
super();
}
case "overSkin": {
graphics.lineStyle(1, 0x0066FF);
graphics.beginFill(0x00CCFF, 0.50);
graphics.drawRoundRect(0, 0, unscaledWidth, unscaledHeight, 10, 10);
}
}
}
}
}
<mx:Style>
Button {
upSkin: ClassReference("ButtonUpAndOverSkinAS");
overSkin: ClassReference("ButtonUpAndOverSkinAS");
}
</mx:Style>
<mx:Script>
<![CDATA[
<mx:states>
<mx:State name="up"/>
<mx:State name="over">
<mx:SetProperty target="{this}"
name="rectFill" value="0x00CCFF"/>
</mx:State>
</mx:states>
</mx:UIComponent>
You typically define a stateful skin as a subclass of UIComponent, in ActionScript or in
MXML, because the view state mechanism is built into the UIComponent class. For more
information, see “Creating stateful skins” on page 921.
<mx:Style>
Button {
skin: ClassReference("ButtonUpStatefulSkin");
downSkin: ClassReference("mx.skins.halo.ButtonSkin");
disabledSkin: ClassReference("mx.skins.halo.ButtonSkin");
selectedUpSkin: ClassReference("mx.skins.halo.ButtonSkin");
selectedOverSkin: ClassReference("mx.skins.halo.ButtonSkin");
selectedDownSkin: ClassReference("mx.skins.halo.ButtonSkin");
selectedDisabledSkin: ClassReference("mx.skins.halo.ButtonSkin");
}
</mx:Style>
Sizing skins
Before a component applies a skin, it first determines its size without the skin. The
component then examines the skin to determine if the skin defines a specific size. If not, the
component scales the skin to fit. If the skin defines a size, the component sizes itself to the
skin.
Most skins do not define any size constraints, which allows the component to scale the skin as
necessary. For more information on writing skins that contain size information, see
“Implementing measuredWidth and measuredHeight getters” on page 917.
<mx:Style>
.myScrollStyle {
upArrowUpSkin: Embed("../assets/uparrow_up_skin.gif");
downArrowUpSkin: Embed("../assets/downarrow_up_skin.gif");
}
</mx:Style>
<mx:TextArea id="ta1"
width="400"
height="50"
verticalScrollPolicy="on"
verticalScrollBarStyleName="myScrollStyle"
text="{theText}"
/>
</mx:Application>
By setting the value of the verticalScrollBarStyleName property in List type selector, all
vertical ScrollBar controls in List components have a custom skin. The ScrollBar controls in
other parts of the application do not have the custom skin.
As with all style sheets, you can define the skins in a separate CSS file and use the source
attribute of the <mx:Style> tag to point to that file; for example:
<mx:Style source="../stylesheets/MySkins.css"/>
Skin resources
Flex includes the following graphical and programmatic source files for skins:
Base skin classes in the mx.skins package These abstract skin classes define the basic
functionality of skin classes in Flex. For more information, see “Creating programmatic skins”
on page 903.
Programmatic Halo skins in the mx.skins.halo package These concrete skin classes
extend the base skin classes in the mx.skins package. You can extend or edit these skins to
create new programmatic skins based on the default Flex look and feel. For more information,
see “Creating programmatic skins” on page 903.
HaloClassic skins These skins were used in Flex 1.x. You can retain the look of Flex 1.x
applications by using these skins. The HaloClassic.swc file is located in the framework/themes
directory. For more information, see “About themes” on page 828.
Graphical Aeon theme The Aeon theme includes the AeonGraphical.css file and the
AeonGraphical.swf file that defines the skin symbols. These are in the framework/themes
directory. In addition, Flex includes the FLA source file for the AeonGraphical.swf file. For
more information, see “About themes” on page 828.
You can use these files to create skins based on the Flex look and feel, or you can create your
own by following the instructions in this topic.
Applying skins
You apply skins by using cascading style sheets (CSS), by specifying them inline in MXML,
by calling the setStyle() method, or by using the StyleManager. The following sections
describe the different ways to apply skins:
■ “Applying skins inline” on page 891
■ “Applying skins by using CSS” on page 893
■ “Applying skins by using the setStyle() method” on page 895
■ “Applying skins by using the Style Manager” on page 899
<mx:Button id="b1"
label="Click Me"
overSkin="@Embed(source='../assets/orb_over_skin.gif')"
upSkin="@Embed(source='../assets/orb_up_skin.gif')"
downSkin="@Embed(source='../assets/orb_down_skin.gif')"/>
</mx:Application>
The location of the skin asset is relative to the location of the MXML file that embeds it.
When embedding inline, you use @Embed (with an at (@) sign prefix) rather than Embed,
which you use in CSS files.
<mx:Button id="b1"
label="Click Me"
overSkin="{ButtonStatesSkin}"
upSkin="{ButtonStatesSkin}"
downSkin="{ButtonStatesSkin}"
disabledSkin="{ButtonStatesSkin}"/>
</mx:Application>
In this example, the SampleButtonSkin.mxml file is in the same directory as the application.
If the skin class is in another directory, you must import the class into the application so that
the compiler can resolve the class name, as the following example shows:
<?xml version="1.0"?>
<!-- skins/ApplyProgrammaticSkinsInlinePackage.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
import myComponents.*;
</mx:Script>
<mx:Button id="b1"
label="Click Me"
overSkin="{myComponents.ButtonStatesSkin}"
upSkin="{myComponents.ButtonStatesSkin}"
downSkin="{myComponents.ButtonStatesSkin}"
disabledSkin="{myComponents.ButtonStatesSkin}"/>
</mx:Application>
When you define stateful skin, you set the skin style property of the control to the class name
of your skin component, as the following example shows:
<?xml version="1.0"?>
<!-- skins/ApplyButtonStatefulSkinInlineAll.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
import myComponents.*;
</mx:Script>
<mx:Button id="b"
label="Hello"
skin="{myComponents.MyButtonStatefulSkinAll}"/>
</mx:Application>
</mx:Application>
You can apply skins to a single instance of a component by defining a class selector. The
following example applies the custom style to the second button only:
<?xml version="1.0"?>
<!-- skins/EmbedImagesClassSelector.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Style>
.myButtonStyle {
overSkin: Embed("../assets/orb_over_skin.gif");
upSkin: Embed("../assets/orb_up_skin.gif");
downSkin: Embed("../assets/orb_down_skin.gif");
}
</mx:Style>
<mx:Script>
<![CDATA[
import mx.styles.StyleManager;
</mx:Application>
For more information, see “Loading style sheets at run time” on page 814.
<mx:Style>
Button {
upSkin: ClassReference("myComponents.MyButtonSkin");
}
</mx:Style>
<mx:Style>
Button {
skin: ClassReference("myComponents.MyButtonStatefulSkinAll");
}
</mx:Style>
<mx:Script>
<![CDATA[
[Embed("../assets/orb_over_skin.gif")]
public var os:Class;
[Embed("../assets/orb_down_skin.gif")]
public var ds:Class;
[Embed("../assets/orb_up_skin.gif")]
public var us:Class;
<mx:Script>
<![CDATA[
public function changeSkins():void {
b1.setStyle("upSkin", ButtonStatesSkin);
b1.setStyle("downSkin", ButtonStatesSkin);
b1.setStyle("overSkin", ButtonStatesSkin);
b1.setStyle("disabledSkin", ButtonStatesSkin);
}
]]>
</mx:Script>
</mx:Application>
The reference to the ButtonStatesSkin.as class in the setStyle() method causes the compiler
to link in the entire ButtonStatesSkin class at compile time. The resulting SWF file will be
larger than if there were no reference to this class, even if the changeSkins() method is never
called.
<mx:Script>
<![CDATA[
import myComponents.*;
</mx:Application>
When you define stateful skin, you use the setStyle() method to set the skin style property
of the control to the class name of your skin component. For more infomrationon applying
stateful skins, see “Creating stateful skins” on page 921.
<mx:Script>
<![CDATA[
import mx.styles.StyleManager;
[Embed("../assets/orb_over_skin.gif")]
public var os:Class;
[Embed("../assets/orb_down_skin.gif")]
public var ds:Class;
[Embed("../assets/orb_up_skin.gif")]
public var us:Class;
</mx:Application>
For more information on using the StyleManager, see “Using the StyleManager class”
on page 800.
The following example uses graphical skins for the up, over, and down states of the Button
control:
<?xml version="1.0"?>
<!-- skins/EmbedImagesTypeSelector.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Style>
Button {
overSkin: Embed("../assets/orb_over_skin.gif");
upSkin: Embed("../assets/orb_up_skin.gif");
downSkin: Embed("../assets/orb_down_skin.gif");
}
</mx:Style>
<mx:Button id="b1" label="Click Me"/>
</mx:Application>
The reason that you must embed the file is that in order to determine a component’s
minimum and preferred sizes, skin assets must be present as soon as the component is created.
If you reference external assets at run time, Flex does not have the sizing information and,
therefore, cannot render the skins properly.
Because skins are embedded, if you change the graphics files that comprise one or more skins,
you must recompile your Flex application for the changes to take effect. For more information
on embedding assets, see Chapter 32, “Embedding Assets,” on page 1237.
<mx:Button id="b1"/>
</mx:Application>
The linkage name is the name used by Flex. Symbol names are ignored.
■ The FLA files cannot contain any ActionScript.
■ The symbol must have an upper-left registration point that you select in the Convert to
Symbol dialog box. The following example shows an upper-left registration point:
■ You can use 9-slice scaling with image files (a grid with nine regions) so that the skin scales
well when the component’s size changes. You define the attributes for 9-slice scaling of
images when you apply the skin in CSS, as the following example shows:
Button {
overSkin: Embed(
"../assets/orb_over_skin.gif",
// Extend ProgrammaticSkin.
public class MySkinOutline extends ProgrammaticSkin {
// Constructor.
public function MySkinOutline() {
// Set default values here.
}
// Override updateDisplayList().
override protected function updateDisplayList(w:Number,
h:Number):void {
// Add styleable properties here.
// Add logic to detect components state and set properties here.
// Add drawing methods here.
}
}
} // Close unnamed package.
In your Flex application, you can apply a programmatic skin using the ClassReference
statement in CSS:
<?xml version="1.0"?>
<!-- skins/ApplyMySkinOutline.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Style>
Button {
overSkin: ClassReference("MySkinOutline");
upSkin: ClassReference("MySkinOutline");
downSkin: ClassReference("MySkinOutline");
}
</mx:Style>
<mx:Button id="b1" label="Click Me"/>
</mx:Application>
For more information, see “Implementing a getter for the borderMetrics property”
on page 919.
6. (Optional) Make properties styleable.
If you create a skin that has properties that you want users to be able to set with CSS or
with calls to the setStyle() method, you must add code to your skin class. For more
information, see “Making properties styleable” on page 934.
If the programmatic skins are not in a package, you must add them to the unnamed package
to make them externally visible. Otherwise, mxmlc throws a compiler error. To do this, you
surround the class with a package statement, as the following example shows:
package { // Open unnamed package.
import flash.display.*;
import mx.skins.ProgrammaticSkin;
To use the methods of the Graphics package, you must import the flash.display.Graphics class,
and any other classes in the flash.display package that you use, such as GradientType or Font.
The following example imports all classes in the flash.display package:
import flash.display.*;
The following example draws a rectangle as a border around the component with the
drawRect() method:
g.drawRect(0, 0, width, height);
// Constructor.
public function CheckboxSkin() {
// Set default values here.
}
// Constructor.
public function ButtonStatesSkin() {
// Set default values.
backgroundFillColor = 0xFFFFFF;
lineThickness = 4;
}
Drawing programmatically
You use the drawing methods of the Graphics class to draw the parts of a programmatic skin.
These methods let you describe fills or gradient fills, define line sizes and shapes, and draw
lines. By combining these very simple drawing methods, you can create complex shapes that
make up your component skins.
Method Summary
beginFill() Begins drawing a fill; for example:
beginFill(0xCCCCFF,1);
If an open path exists (that is, if the current drawing position does not
equal the previous position that you specified in a moveTo() method)
and it has a fill associated with it, that path is closed with a line, and
then filled.
beginGradientFill() Begins drawing a gradient fill. If an open path exists (that is, if the
current drawing position does not equal the previous position that
you specified in a moveTo() method), and it has a fill associated with it,
that path is closed with a line, and then filled.
clear() Removes all the drawing output associated with the current object.
The clear() method takes no arguments.
curveTo() Draws a curve using the current line style; for example:
moveTo(500, 500);
curveTo(600, 500, 600, 400);
curveTo(600, 300, 500, 300);
curveTo(400, 300, 400, 400);
curveTo(400, 500, 500, 500);
drawCircle() Draws a circle after you set the line style and fill. You pass the
method the x and y position of the circle, as well as the radius, as the
following example shows:
drawCircle(10,10,50);
drawRect() Draws a rectangle once you set the line style and fill. You pass the
method the x and y positions of the rectangle, as well as the length
and width of the rectangle, as the following example shows:
drawRect(10,10,100,20);
drawRoundRect() Draws a rectangle with rounded corners, after you set the line and fill.
You pass the method the x and y position of the rectangle, length and
height of the rectangle, and the width and height of the ellipse that is
used to draw the rounded corners, as the following example shows:
drawRoundRect(10,10,100,20,9,5)
// Constructor.
public function CheckBoxAsArrowSkin() {
// Set default values.
}
var arrowColor:Number;
switch (name) {
case "upIcon":
case "selectedUpIcon": {
arrowColor = 0x666666;
break;
}
case "overIcon":
case "downIcon":
case "selectedOverIcon":
case "selectedDownIcon": {
arrowColor = 0xCCCCCC;
break;
}
}
// Draw an arrow.
graphics.lineStyle(1, 1, 1);
graphics.beginFill(arrowColor);
graphics.moveTo(unscaledWidth, unscaledHeight-20);
graphics.lineTo(unscaledWidth-30, unscaledHeight+20);
graphics.lineTo(unscaledWidth+30, unscaledHeight+20);
graphics.lineTo(unscaledWidth, unscaledHeight-20);
graphics.endFill();
// Constructor.
public function CustomContainerBorderSkin() {
}
super.updateDisplayList(unscaledWidth, unscaledHeight);
// Background
drawRoundRect(0, 0, unscaledWidth, unscaledHeight,
{tl: 0, tr:cornerRadius, bl: cornerRadius, br: 0},
backgroundColor, backgroundAlpha);
// Shadow
if (!dropShadow)
dropShadow = new RectangularDropShadow();
dropShadow.distance = 8;
dropShadow.angle = 45;
dropShadow.color = 0;
dropShadow.alpha = 0.4;
dropShadow.tlRadius = 0;
dropShadow.trRadius = cornerRadius;
dropShadow.blRadius = cornerRadius;
dropShadow.brRadius = 0;
dropShadow.drawShadow(graphics, 0, 0, unscaledWidth, unscaledHeight);
}
}
}
</mx:Application>
The “unscaled” width and height properties in the previous examples refer to the
measurements of the skin as the skin itself understands them. These measurements ignore the
fact that external components might have changed the dimensions of the skin. When working
inside the component, it is best to use the unscaled measurements.
// Constructor.
public function ButtonStatesWithMeasuredSizesSkin() {
// Set default values.
backgroundFillColor = 0xFFFFFF;
lineThickness = 4;
_measuredHeight = 100;
_measuredWidth = 150;
}
// Constructor.
public function ButtonStatesWithBorderMetricsSkin() {
// Set default values.
backgroundFillColor = 0xFFFFFF;
lineThickness = 4;
}
<mx:State name="over">
</mx:State>
...
<mx:State name="selectedUp">
</mx:State>
</mx:states>
<mx:Script>
<![CDATA[
<!-- Define the skin by using the Flash drawing API. -->
]]>
</mx:Script>
</mx:UIComponent>
NO TE
You can create a state skin in either ActionScript or MXML. The examples in this section
use MXML because it requires fewer lines of code to define view states.
After defining your stateful skin, you assign it to the skin style property of the control. You
can assign the stateful control by using CSS, the setStyle() method, by using inline styles,
or by using the StyleManager. The following example sets it by using CSS:
<?xml version="1.0"?>
<!-- skins/ApplyButtonStatefulSkinAll.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Style>
Button {
skin: ClassReference("myComponents.MyButtonStatefulSkinAll");
}
</mx:Style>
<mx:State name="over">
</mx:State>
</mx:states>
...
</mx:UIComponent>
You then specify this component as the value of the skin style property, and specify the default
skins for the remaining six properties, as the following example shows:
<?xml version="1.0"?>
<!-- skins/SimpleButtonStatefulSkin.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Style>
Button {
skin: ClassReference("ButtonUpStatefulSkin");
downSkin: ClassReference("mx.skins.halo.ButtonSkin");
disabledSkin: ClassReference("mx.skins.halo.ButtonSkin");
selectedUpSkin: ClassReference("mx.skins.halo.ButtonSkin");
selectedOverSkin: ClassReference("mx.skins.halo.ButtonSkin");
selectedDownSkin: ClassReference("mx.skins.halo.ButtonSkin");
selectedDisabledSkin: ClassReference("mx.skins.halo.ButtonSkin");
}
</mx:Style>
<mx:Script>
<![CDATA[
import flash.filters.DropShadowFilter;
<mx:states>
<mx:State name="up">
</mx:State>
<mx:State name="over">
<mx:SetProperty target="{this}"
name="rectFill" value="0x00CC33"/>
<mx:SetProperty target="{myFilter}"
name="distance" value="4"/>
</mx:State>
<mx:State name="down">
<mx:SetProperty target="{this}"
name="rectFill" value="0x00CC33"/>
<mx:SetProperty target="{myFilter}"
name="inner" value="true"/>
<mx:SetProperty target="{myFilter}"
name="distance" value="2"/>
</mx:State>
</mx:states>
</mx:UIComponent>
This examples defines skins the for following states:
up Does not define any changes; therefore, the base view state defines the skin for the up
state.
over Changes the fill color to 0x00CC33, sets the line width to 2 pixels, and creates a 2-
pixel wide drop shadow.
down Changes the fill color to 0x00CC33, sets the drop shadow type to inner, and creates a
2-pixel wide drop shadow.
<mx:Style>
Button {
skin: ClassReference("myComponents.MyButtonStatefulSkin");
disabledSkin: ClassReference("mx.skins.halo.ButtonSkin");
selectedUpSkin: ClassReference("mx.skins.halo.ButtonSkin");
selectedOverSkin: ClassReference("mx.skins.halo.ButtonSkin");
selectedDownSkin: ClassReference("mx.skins.halo.ButtonSkin");
selectedDisabledSkin: ClassReference("mx.skins.halo.ButtonSkin");
}
</mx:Style>
<mx:Script>
<![CDATA[
// Embed the skin images.
[Bindable]
[Embed(source="../../assets/orb_up_skin.gif")]
private var buttonUp:Class;
[Bindable]
[Embed(source="../../assets/orb_over_skin.gif")]
private var buttonOver:Class;
[Bindable]
[Embed(source="../../assets/orb_down_skin.gif")]
private var buttonDown:Class;
[Bindable]
[Embed(source="../../assets/orb_disabled_skin.gif")]
private var buttonDisabled:Class;
]]>
</mx:Script>
<mx:states>
<mx:State name="up"/>
<mx:State name="notBase">
<mx:RemoveChild target="{baseButton}"/>
</mx:State>
<mx:State name="over" basedOn="notBase">
<mx:AddChild creationPolicy="all">
<mx:Image source="{buttonOver}"
maintainAspectRatio="false"
width="100%" height="100%"/>
</mx:AddChild>
</mx:State>
<mx:State name="down" basedOn="notBase">
<mx:AddChild creationPolicy="all">
<mx:Image source="{buttonDown}"
maintainAspectRatio="false"
width="100%" height="100%"/>
</mx:AddChild>
</mx:State>
<mx:State name="disabled" basedOn="notBase">
<mx:AddChild creationPolicy="all">
<mx:Image source="{buttonDisabled}"
<mx:Image id="baseButton"
width="100%" height="100%"
source="{buttonUp}"
maintainAspectRatio="false"/>
</mx:Canvas>
In this example the skin performs the following actions:
■ Defines no changes from the base view state to create the up view state.
■ Defines the notBase view state to remove the image defined by the base view state. All
other view states, except for the up view state, are based on the notBase view state.
■ Sets the creationPolicy property to all for each AddChild tag. This property specifies
to create the child instance at application startup, rather than on the first change to the
view state. This prevent flickering when viewing a view state for the first time. For more
information, see Chapter 29, “Using View States,” on page 1115.
■ Sets the width and height properties to 100% for the Image tags because the Canvas
container is what is being resized by the skin parent, not the individual Image controls.
This setting configures the Image control to size itself to its parent.
■ Sets the maintainAspectRatio property to false on each Image tag so that the image
stretches to fill the full size of the Canvas container.
<mx:Script>
<![CDATA[
import flash.filters.DropShadowFilter;
<mx:states>
<mx:State name="up">
</mx:State>
<mx:State name="over">
<mx:SetProperty target="{this}"
name="rectFill" value="0x00CC33"/>
<mx:SetProperty target="{myFilter}"
name="distance" value="4"/>
</mx:State>
<mx:State name="down">
<mx:SetProperty target="{this}"
name="rectFill" value="0x00CC33"/>
<mx:SetProperty target="{myFilter}"
name="inner" value="true"/>
<mx:SetProperty target="{myFilter}"
name="distance" value="2"/>
</mx:State>
</mx:states>
<mx:transitions>
<mx:Transition>
<mx:AnimateProperty target="{this}"
property="rectFill" duration="100"/>
</mx:Transition>
</mx:transitions>
</mx:UIComponent>
import flash.display.GradientType;
import flash.display.Graphics;
import mx.skins.Border;
import mx.styles.StyleManager;
import mx.utils.ColorUtil;
import mx.skins.halo.HaloColors;
import mx.core.UIComponent;
// User-defined styles
var borderColor:uint = getStyle("borderColor");
var fillAlphas:Array = getStyle("fillAlphas");
var fillColors:Array = getStyle("fillColors");
StyleManager.getColorNames(fillColors);
var highlightAlphas:Array = getStyle("highlightAlphas");
var themeColor:uint = getStyle("themeColor");
var upFillColors:Array;
var upFillAlphas:Array;
var disFillColors:Array;
var disFillAlphas:Array;
var myParent:String;
switch (name) {
case "upIcon": {
upFillColors = [ fillColors[0], fillColors[1] ];
upFillAlphas = [ fillAlphas[0], fillAlphas[1] ];
if (parent is UIComponent) {
myParent = String(UIComponent(parent).className);
}
if (myParent=="RadioButton") {
// RadioButton border
g.beginGradientFill(GradientType.LINEAR,
[ borderColor, 0x000000 ],
[100,100], [0,0xFF],
verticalGradientMatrix(0,0,w,h));
g.drawCircle(r,r,r);
g.drawCircle(r,r,(r-1));
g.endFill();
// RadioButton fill
g.beginGradientFill(GradientType.LINEAR,
upFillColors,
upFillAlphas,
[0,0xFF],
verticalGradientMatrix(1,1,w-2,h-2));
g.drawCircle(r,r,(r-1));
g.endFill();
} else if (myParent=="CheckBox") {
// CheckBox border
drawRoundRect(0,0,w,h,0,
[borderColor, 0x000000], 1,
verticalGradientMatrix(0,0,w,h),
GradientType.LINEAR,
null, {x: 1,y:1,w:w-2,h:h-2,r:0});
// CheckBox fill
drawRoundRect(1, 1, w-2, h-2, 0,
upFillColors, upFillAlphas,
verticalGradientMatrix(1,1,w-2,h-2));
}
// top highlight
drawRoundRect(1, 1, w-2,
(h-2)/2, {tl:r,tr:r,bl:0,br:0},
[0xFFFFFF, 0xFFFFFF],
highlightAlphas,
verticalGradientMatrix(0,0,w-2,(h-2)/2));
}
}
}
}
You must define a default value for the skin’s styleable properties. You usually do this in the
skin’s constructor function. If you do not define a default value, the style property is set to NaN
or undefined if the Flex application does not define that style. This can cause a run-time
error.
// Constructor.
public function ButtonStylesSkin() {
// Set default values.
_backgroundFillColor = 0xFFFFFF;
_lineThickness=2;
}
The following example sets the value of a styleable properties on all Button controls with a
CSS:
<?xml version="1.0"?>
<!-- skins/ApplyButtonStylesSkin.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" width="600"
height="600">
<mx:Style>
Button {
upSkin:ClassReference('ButtonStylesSkin');
downSkin:ClassReference('ButtonStylesSkin');
overSkin:ClassReference('ButtonStylesSkin');
disabledSkin:ClassReference('ButtonStylesSkin');
lineThickness:4;
backgroundFillColor:#CCCCCC;
}
</mx:Style>
<mx:Script><![CDATA[
public function changeLineThickness(e:Event):void {
var t:int = Number(b1.getStyle("lineThickness"));
if (t == 4) {
b1.setStyle("lineThickness",1);
} else {
b1.setStyle("lineThickness",4);
}
}
]]></mx:Script>
<mx:Button id="b2"/>
</mx:Application>
<mx:Script><![CDATA[
public function changeLineThickness(e:Event):void {
var t:int = Number(b1.getStyle("lineThickness"));
if (t == 4) {
StyleManager.getStyleDeclaration("Button").setStyle("lineThickness", 1);
} else {
StyleManager.getStyleDeclaration("Button").setStyle("lineThickness", 4);
}
}
]]></mx:Script>
</mx:Application>
If you do not set the values of these properties using either CSS or the setStyle() method,
Flex uses the default values of the properties that you set in the skin’s constructor.
To get the value of an existing style property, such as color or fontSize, you do not have to
wrap the call to the getStyle() method in a check for the property’s existence. This is
because Flex creates a CSSStyleDeclaration that defines the default values of all of a
component’s styles. Pre-existing style properties are never undefined. Style properties that you
add to a custom skin are not added to this CSSStyleDeclaration because the component does
not know that the property is a style property.
CHAPTER 23
Contents
About item renderers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 939
Creating an item renderer and item editor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 948
Creating drop-in item renderers and item editors . . . . . . . . . . . . . . . . . . . . . . . . . . . 959
Creating inline item renderers and editors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 964
Creating item renderers and item editor components . . . . . . . . . . . . . . . . . . . . . . . . 972
Working with item renderers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 980
939
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
■ Tree
A list control gets its data from a data provider, which is a collection of objects. For example, a
Tree control reads data from a data provider to define the structure of the tree and any
associated data that is assigned to each tree node.
The data provider creates a level of abstraction between Flex components and the data that
you use to populate them. You can populate multiple components from the same data
provider, switch data providers for a component at run time, and modify the data provider so
that changes are reflected by all components that use the data provider.
You can think of the data provider as the model, and the Flex components as the view of the
model. By separating the model from the view, you can change one without changing the
other.
Each list control has a default mechanism for controlling the display of data, or view, and lets
you override that default. To override the default view, you create a custom item renderer.
In addition to controlling the display of data using an item renderer, the DataGrid, List, and
Tree controls let users edit the data. For example, you could let users update the Quantity
column of a DataGrid control if you are using it for a shopping cart. As with the display of
data, the list controls have a default mechanism for letting users edit data that you can
override by creating a custom item editor.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{Artist:'Pavement', Album:'Slanted and Enchanted', Price:11.99},
{Artist:'Pavement', Album:'Brighten the Corners', Price:11.99}
]);
]]>
</mx:Script>
TextInput control
In this image, you use the default item editor to edit the price of the first album in the
DataGrid control.
For more information on item editors, see Chapter 24, “Working with Item Editors,” on
page 993.
For the code for this example, see “Example: Using an item renderer with a List control”
on page 986.
In the next image, you use a default item renderer for the first and third columns of the
DataGrid control. You use a custom item renderer for the second column to display the
album cover along with the album title in the DataGrid control.
Custom
item
editor
For the code for this example, see “Creating a simple item editor component” on page 976.
Using an item renderer does not imply that the control also has an item editor. Often, you do
not allow your controls to be edited; that is, they are for display only.
You can also use an item editor without a corresponding item renderer. For example, you
could display information such as a male/female or true/false as text using the default item
renderer. But, you could then use a custom item editor with a ComboBox control that
provides the user only a limited set of options to enter into the cell when changing the value.
data property
item renderer
list control
Item editor
To pass information to an item renderer or item editor, Flex sets the data property of the item
renderer or item editor to the cell data. In the previous image, you can see the data property
that is used to pass the data to the item renderer or item editor.
By default, an item editor can pass back a single value to the list control that becomes the new
value of the edited cell. To return more than one value, you must write additional code to
return the data back to the List control. For more information, see “Example: Passing
multiple values back from an item editor” on page 1015.
Any Flex component that you want to use in an item renderer or item editor, and that requires
access to the cell data of the list control, must implement the IDataRenderer interface to
support the data property. You can use additional components in an item renderer that do
not support the data property, if those components do not need to access data passed from
the list control.
The contents of the data property depend on the type of control, as the following table
shows:
Tree Contains the data provider element for the node of the List or Tree control.
List
MenuBar Contains the data provider element for the menu bar item.
For more information on item editors, see Chapter 24, “Working with Item Editors,” on
page 993.
Interface Use
IDataRenderer Defines the data property used to pass information to an item
renderer or item editor. All item renderers and item editors must
implement this interface.
Many Flex components implement this interface, such as the chart
renderer classes, and many Flex controls.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var myDP:ArrayCollection = new ArrayCollection([
{label1:"Order #2314", quant:3, Sent:true},
{label1:"Order #2315", quant:3, Sent:false}
]);
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var myDP:ArrayCollection = new ArrayCollection([
{label1:"Order #2314", quant:3, Sent:true},
{label1:"Order #2315", quant:3, Sent:false}
]);
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var myDP:ArrayCollection = new ArrayCollection([
{label1:"Order #2314", quant:3, Sent:true},
{label1:"Order #2315", quant:3, Sent:false}
]);
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.core.ClassFactory;
<mx:HBox >
<!-- Use Label controls to display state and capital names. -->
<mx:Label id="State" text="State: {data.label}"/>
<mx:Label id="Statecapital" text="Capital: {data.data}" />
</mx:HBox>
Property Description
owner A reference to the list control that uses the item renderer or item editor.
rowIndex The index of the row of the DataGrid, List, or Tree control relative to the
currently visible rows of the control, where the first row is at an index of 1.
label The text representation of the item data based on the List class’s
itemToLabel() method.
The BaseListData class has three subclasses: DataGridListData, ListData, TreeListData that
define additional properties. For example, the DataGridListData class adds the columnIndex
and dataField properties that you can access from an item renderer or item editor.
The data type of the value of the listData property depends on the control that uses the item
renderer or item editor. For a DataGrid control, the value is of type DataGridListData; for a
List control, the value is of type ListData; and for a Tree control, the value is of type
TreeListData.
<mx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridListData;
import flash.events.Event;
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var initDG:ArrayCollection = new ArrayCollection([
{ Company: 'Acme', Contact: 'Bob Jones',
Phone: '413-555-1212', Date: '5/5/05'},
{ Company: 'Allied', Contact: 'Jane Smith',
Phone: '617-555-3434', Date: '5/6/05'}
]);
]]>
</mx:Script>
DateField selectedDate Requires that the data provider of the list control has a
field of type Date.
Label text
NumericStepper value
Text text
TextArea text
TextInput text
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var myDP:ArrayCollection = new ArrayCollection([
{label1:"Order #2314", contact:"John Doe",
quant:3, solddate:new Date(2005, 0, 1), Sent:true},
{label1:"Order #2315", contact:"Jane Doe",
quant:3, solddate:new Date(2005, 0, 5), Sent:false}
]);
]]>
</mx:Script>
<mx:DataGrid id="myDG"
dataProvider="{myDP}"
variableRowHeight="true"
width="500" height="250"
editable="true">
<mx:columns>
<mx:DataGridColumn dataField="label1"
headerText="Order #"
editable="false"/>
<mx:DataGridColumn dataField="quant"
headerText="Quantity"
itemEditor="mx.controls.NumericStepper"
editorDataField="value"/>
<mx:DataGridColumn dataField="solddate"
headerText="Date"
itemRenderer="mx.controls.DateField"
rendererIsEditor="true"
editorDataField="selectedDate"/>
<mx:DataGridColumn dataField="Sent"
itemRenderer="mx.controls.CheckBox"
rendererIsEditor="true"
editorDataField="selected"/>
</mx:columns >
</mx:DataGrid>
</mx:Application>
To determine the field of the data provider used to populate the drop-in item renderer, Flex
uses the value of the dataField property for the <mx:DataGridColumn> tag. In this example,
you do the following:
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{ Artist:'Pavement', Album:'Slanted and Enchanted',
Price:11.99, Cover: 'slanted.jpg' },
{ Artist:'Pavement', Album:'Brighten the Corners',
Price:11.99, Cover: 'brighten.jpg'}
]);
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{Artist:'Pavement', Album:'Slanted and Enchanted',
Price:11.99, Cover: 'slanted.jpg'},
{Artist:'Pavement', Album:'Brighten the Corners',
Price:11.99, Cover: 'brighten.jpg'}
]);
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var myDP:ArrayCollection = new ArrayCollection([
{label1:"Order #2314", quant:3, Sent:true},
{label1:"Order #2315", quant:3, Sent:false}
]);
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
In the preceding example, you make the Image control a child of a VBox container so that
you can align the image in the cell. The Image control is now a child of the VBox container,
so you must initialize it by using the data property.
You can define multiple controls in a complex inline item editor, which lets you edit multiple
values of the data provider for the list control. Alternatively, you can define a complex inline
item editor so it returns a value other than a String. For more information, see Chapter 24,
“Working with Item Editors,” on page 993.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
<mx:Text id="albumName"
width="100%"
selectable="false"
text="{data.Album}"/>
<mx:Image id="albumImage"
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var initDG:ArrayCollection = new ArrayCollection([
{Company: 'Acme', Contact: 'Bob Jones',
Phone: '413-555-1212', City: 'Boston', State: 'MA'},
{Company: 'Allied', Contact: 'Jane Smith',
Phone: '617-555-3434', City: 'SanFrancisco', State: 'CA'}
]);
]]>
</mx:Script>
<mx:Component id="inlineEditor">
<mx:ComboBox>
<mx:dataProvider>
<mx:String>AL</mx:String>
<mx:String>AK</mx:String>
<mx:String>AR</mx:String>
</mx:dataProvider>
</mx:ComboBox>
</mx:Component>
<mx:DataGrid id="myGrid"
variableRowHeight="true"
dataProvider="{initDG}"
editable="true" >
<mx:columns>
<mx:DataGridColumn dataField="Company" editable="false"/>
<mx:DataGridColumn dataField="Contact"/>
<mx:DataGridColumn dataField="Phone"/>
<mx:DataGridColumn dataField="City"/>
<mx:DataGridColumn dataField="State"
width="150"
editorDataField="selectedItem"
itemEditor="{inlineEditor}"/>
</mx:columns>
</mx:DataGrid>
<mx:DataGrid id="myGrid2"
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{Artist:'Pavement', Album:'Slanted and Enchanted',
Price:11.99, Cover: 'slanted.jpg'},
{Artist:'Pavement', Album:'Brighten the Corners',
Price:11.99, Cover: 'brighten.jpg'}
]);
]]>
</mx:Script>
<mx:DataGrid id="myGrid"
dataProvider="{initDG}"
variableRowHeight="true">
<mx:columns>
<mx:DataGridColumn dataField="Artist"/>
<mx:DataGridColumn dataField="Album"/>
<mx:DataGridColumn dataField="Cover"
itemRenderer="myComponents.RendererDGImage"/>
<mx:DataGridColumn dataField="Price"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
The DataGrid control contains a column for the album cover that uses the itemRenderer
property to specify the name of the MXML file that contains the item renderer for that
column. Now, when you run this example, the DataGrid control uses your custom item
renderer for the Cover column to display an image of the Album cover.
<mx:Text id="albumName"
width="100%"
selectable="false"
text="{data.Album}"/>
<mx:Image id="albumImage"
source="{data.Cover}"/>
</mx:VBox>
You save this item renderer to the RendererDGTitleImage.mxml file. The DataGrid control
in the main application references the item renderer, as the following example shows:
<?xml version="1.0"?>
<!-- itemRenderers\component\MainDGTitleRenderer.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{Artist:'Pavement', Album:'Slanted and Enchanted',
Price:11.99, Cover: 'slanted.jpg'},
{Artist:'Pavement', Album:'Brighten the Corners',
Price:11.99, Cover: 'brighten.jpg'}
]);
]]>
</mx:Script>
<mx:DataGrid id="myGrid"
dataProvider="{initDG}"
variableRowHeight="true">
<mx:columns>
<mx:DataGridColumn dataField="Artist" />
<mx:DataGridColumn dataField="Album"
itemRenderer="myComponents.RendererDGTitleImage" />
<mx:DataGridColumn dataField="Price" />
</mx:columns>
</mx:DataGrid>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.events.FlexEvent;
[Embed(source="saleIcon.jpg")]
[Bindable]
public var sale:Class;
[Embed(source="noSaleIcon.jpg")]
[Bindable]
public var noSale:Class;
// myComponents/CellField.as
import mx.controls.*;
import mx.core.*;
import mx.controls.dataGridClasses.DataGridListData;
if (value != null)
{
text = value[DataGridListData(listData).dataField];
if(Number(text) > 100)
{
setStyle("backgroundColor", 0xFF0000);
}
}
super.invalidateDisplayList();
}
}
}
In the preceding example, you create a subclass of the TextInput control as your item renderer.
The class must be public to be used as an item renderer or editor. This item renderer displays
a red background if the value of the DataGrid cell is greater than 100.
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
width="600" height="600">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{Monday: 12, Tuesday: 22, Wednesday: 452, Thursday: 90},
{Monday: 258, Tuesday: 22, Wednesday: 45, Thursday: 46},
{Monday: 4, Tuesday: 123, Wednesday: 50, Thursday: 95},
{Monday: 12, Tuesday: 52, Wednesday: 111, Thursday: 20},
{Monday: 22, Tuesday: 78, Wednesday: 4, Thursday: 51}
]);
]]>
</mx:Script>
<mx:DataGrid id="myDataGrid"
dataProvider="{initDG}"
variableRowHeight="true">
<mx:columns>
<mx:DataGridColumn dataField="Monday"
itemRenderer="myComponents.CellField" />
<mx:DataGridColumn dataField="Tuesday"
itemRenderer="myComponents.CellField" />
<mx:DataGridColumn dataField="Wednesday"
itemRenderer="myComponents.CellField" />
<mx:DataGridColumn dataField="Thursday"
itemRenderer="myComponents.CellField" />
</mx:columns>
</mx:DataGrid>
</mx:Application>
Each item in the HorizontalList control contains an image, a descriptive text string, and a
price. The following code shows the application that displays the catalog. The item renderer
for the HorizontalList control is an MXML component named Thumbnail.
<?xml version="1.0"?>
<!-- itemRenderers\htlistMainlistThumbnailRenderer.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:HorizontalList id="myList"
columnWidth="125"
rowHeight="125"
columnCount="4"
dataProvider="{catalog.product}"
itemRenderer="myComponents.Thumbnail"/>
[Embed(source="saleIcon.jpg")]
[Bindable]
public var sale:Class;
]]>
</mx:Script>
</mx:HBox>
This item renderer uses a Label control to insert the text “Sale Price!” and an Image control to
insert an icon in the column header.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{Artist:'Pavement', Album:'Slanted and Enchanted',
Price:11.99, SalePrice: true },
{Artist:'Pavement', Album:'Brighten the Corners',
Price:11.99, SalePrice: false }
]);
]]>
</mx:Script>
<mx:DataGrid id="myGrid"
dataProvider="{initDG}"
variableRowHeight="true">
<mx:columns>
<mx:DataGridColumn dataField="Artist"/>
<mx:DataGridColumn dataField="Album"/>
<mx:DataGridColumn dataField="Price"/>
<mx:DataGridColumn width="150" dataField="SalePrice"
headerRenderer="myComponents.RendererDGHeader"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
In this example, the DataGrid control displays the String true or false in the column to
indicate that the price is a sale price. You can also define an item renderer for that column to
display a more compelling icon rather than text. For an example that uses an item renderer
with a DataGrid control, see “Using custom item renderers and item editors” on page 943.
<mx:List id="myList"
height="180" width="250"
variableRowHeight="true"
itemRenderer="myComponents.RendererState"
backgroundColor="white" >
<mx:dataProvider>
<mx:Object label="Alaska"
data="Juneau"
webPage="http://www.state.ak.us/"/>
<mx:Object label="Alabama"
data="Montgomery"
webPage="http://www.alabama.gov/" />
<mx:Object label="Arkansas"
data="Little Rock"
webPage="http://www.state.ar.us/"/>
</mx:dataProvider>
</mx:List>
</mx:Application>
The previous example sets the rowHeight property to 75 pixels because the item renderer
displays content that exceeds the default row height of the List control. To see an image that
shows this application, see “Using custom item renderers and item editors” on page 943.
<mx:HBox >
<!-- Use Label controls to display state and capital names. -->
<mx:Label id="State" text="State: {data.label}"/>
<mx:Label id="Statecapital" text="Capital: {data.data}" />
</mx:HBox>
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(super.data)
{
if(TreeListData(super.listData).hasChildren)
{
var tmp:XMLList =
new XMLList(TreeListData(super.listData).item);
var myStr:int = tmp[0].children().length();
super.label.text = TreeListData(super.listData).label +
"(" + myStr + ")";
}
<mx:Script>
<![CDATA[
import mx.collections.*;
[Bindable]
public var xlcBalanced:XMLListCollection;
<mx:Text width="400"
text="The nodes with children are in bold red text, with the number
of children in parenthesis.)"/>
<mx:Tree id="compBalanced"
width="400" height="500"
dataProvider="{xlcBalanced}"
labelField="@label"
itemRenderer="myComponents.MyTreeItemRenderer"/>
</mx:Application>
CHAPTER 24
Contents
The cell editing process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 993
Creating an editable cell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 994
Returning data from an item editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 995
Sizing and positioning an item editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 999
Making an item editor that responds to the Enter key . . . . . . . . . . . . . . . . . . . . . . . 1001
Using the cell editing events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1002
Item editor examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1010
Examples using item editors with the list controls. . . . . . . . . . . . . . . . . . . . . . . . . . .1024
993
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
3. Flex dispatches the itemEditBegin event to open the item editor. You can use this event
to modify the data passed to the item editor. For more information, see “Example:
Modifying data passed to or received from an item editor” on page 1013.
4. The user edits the cell.
5. The user ends the editing session. Typically the cell editing session ends when the user
removes focus from the cell.
6. Flex dispatches the itemEditEnd event to close the item editor and update the list control
with the new cell data. You can use this event to modify the data returned to the cell,
validate the new data, or return data in a format other than the format returned by the item
editor. For more information, see “Example: Modifying data passed to or received from an
item editor” on page 1013.
7. The new data value appears in the cell.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var myDP:ArrayCollection = new ArrayCollection([
{label1:"Order #2314", quant:3, Sent:true},
{label1:"Order #2315", quant:3, Sent:false}
]);
]]>
</mx:Script>
<mx:Script>
<![CDATA[
// Define a property for returning the new value to the cell.
public var cbSelected:Boolean;
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{Company: 'Acme', Contact: 'Bob Jones',
Phone: '413-555-1212', Date: '5/5/05' , FollowUp: true },
{Company: 'Allied', Contact: 'Jane Smith',
Phone: '617-555-3434', Date: '5/6/05' , FollowUp: false}
]);
]]>
</mx:Script>
<mx:DataGrid id="myGrid"
dataProvider="{initDG}"
editable="true" >
<mx:columns>
<mx:DataGridColumn dataField="Company" editable="false"/>
<mx:DataGridColumn dataField="Contact"/>
<mx:DataGridColumn dataField="Phone"/>
<mx:DataGridColumn dataField="Date"/>
<mx:DataGridColumn dataField="FollowUp"
width="150"
headerText="Follow Up?"
itemEditor="myComponents.EditorDGCheckBox"
editorDataField="cbSelected"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
Notice that the editorDataField property is set to cbSelected, the new property of the
VBox container.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{Company: 'Acme', Contact: 'Bob Jones',
Phone: '413-555-1212', Date: '5/5/05' , FollowUp: true },
{Company: 'Allied', Contact: 'Jane Smith',
Phone: '617-555-3434', Date: '5/6/05' , FollowUp: false}
]);
]]>
</mx:Script>
<mx:DataGrid id="myGrid"
dataProvider="{initDG}"
editable="true">
<mx:columns>
<mx:DataGridColumn dataField="Company" editable="false"/>
<mx:DataGridColumn dataField="Contact"/>
<mx:DataGridColumn dataField="Phone"/>
<mx:DataGridColumn dataField="Date"/>
<mx:DataGridColumn dataField="FollowUp"
width="150"
headerText="Follow Up?"
editorDataField="cbSelected">
<mx:itemEditor>
<mx:Component>
<mx:VBox backgroundColor="yellow">
<mx:Script>
<![CDATA[
// Define a property for returning
// the new value to the cell.
[Bindable]
public var cbSelected:Boolean;
]]>
</mx:Script>
<mx:CheckBox id="followUpCB"
label="Follow up needed"
height="100%" width="100%"
Property Description
editorHeightOffset Specifies the height of the item editor, in pixels, relative to the size of
the cell for a DataGridColumn control, or the text field of a Tree
control.
editorWidthOffset Specifies the width of the item editor, in pixels, relative to the size of
the cell for a DataGridColum control, or the text field of a Tree control.
editorXOffset Specifies the x location of the upper-left corner of the item editor, in
pixels, relative to the upper-left corner of the cell for a
DataGridColumn control, or from the upper-left corner of the text field
of a Tree control.
editorYOffset Specifies the y location of the upper-left corner of the item editor, in
pixels, relative to the upper-left corner of the cell for a
DataGridColumn control, or from the upper-left corner of the text field
of a Tree control.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{Company: 'Acme', Contact: 'Bob Jones',
Phone: '413-555-1212', Date: '5/5/05' , FollowUp: true },
{Company: 'Allied', Contact: 'Jane Smith',
Phone: '617-555-3434', Date: '5/6/05' , FollowUp: false}
]);
]]>
</mx:Script>
<mx:DataGrid id="myGrid"
dataProvider="{initDG}"
editable="true" >
<mx:columns>
<mx:DataGridColumn dataField="Company" editable="false"/>
<mx:DataGridColumn dataField="Contact"/>
<mx:DataGridColumn dataField="Phone"/>
<mx:DataGridColumn dataField="Date"/>
<mx:DataGridColumn dataField="FollowUp"
width="150"
headerText="Follow Up?"
editorDataField="cbSelected"
editorXOffset="15"
editorYOffset="15">
<mx:itemEditor>
<mx:Component>
<mx:VBox backgroundColor="yellow">
<mx:Script>
<![CDATA[
// Define a property for returning
// the new value to the cell.
[Bindable]
public var cbSelected:Boolean;
]]>
</mx:Script>
<?xml version="1.0"?>
<!-- itemRenderers\dataGrid\myComponents\EditorDGCheckBox.mxml -->
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundColor="yellow">
<mx:Script>
<![CDATA[
// Define a property for returning the new value to the cell.
public var cbSelected:Boolean;
]]>
</mx:Script>
<mx:Script>
<![CDATA[
// Define a property for returning the new value to the cell.
public var cbSelected:Boolean;
<mx:CheckBox id="followUpCB"
label="Follow up needed"
height="100%" width="100%"
selected="{data.FollowUp}"
click="cbSelected=followUpCB.selected"
updateComplete="cbSelected=followUpCB.selected;"/>
</mx:VBox>
While the IFocusManagerComponent interface defines several properties and methods, the
UIComponent class defines or inherits implementations for all of them except for the
drawFocus() method. Therefore, you only have to implement that one method so that your
item editor responds to the Enter key.
List ListEvent
Tree ListEvent
Notice that the event class for the List and Tree controls is ListEvent.
When defining the event listener for a list control, ensure that you specify the correct type for
the event object passed to the event listener, as the following example shows for a DataGrid
control:
public function myCellEndEvent(event:DataGridEvent):void {
// Define event listener.
}
<mx:Script>
<![CDATA[
import mx.controls.TextInput;
import mx.events.DataGridEvent;
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{Artist:'Pavement', Album:'Slanted and Enchanted',
Price:11.99},
{Artist:'Pavement', Album:'Brighten the Corners',
Price:11.99 }
]);
<mx:DataGrid id="myGrid"
Value Description
CANCELLED Specifies that the user canceled editing and that they do not want to save the
edited data. Even if you call the preventDefault() method from within your
event listener for the itemEditEnd event, Flex still calls the
destroyItemEditor() method to close the editor.
NEW_COLUMN (DataGrid only) Specifies that the user moved focus to a new column in the
same row. In an event listener, you can let the focus change occur, or prevent
it.
For example, your event listener might check that the user entered a valid
value for the cell currently being edited. If not, you can prevent the user from
moving to a new cell by calling the preventDefault() method. In this case, the
item editor remains open, and the user continues to edit the current cell. If you
call the preventDefault() method and also call the destroyItemEditor()
method, you block the move to the new cell, but the item editor closes.
<mx:Script>
<![CDATA[
import mx.controls.TextInput;
import mx.events.DataGridEvent;
import mx.events.DataGridEventReason;
import mx.formatters.NumberFormatter;
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{Artist:'Pavement', Album:'Slanted and Enchanted',
Price:11.99},
{Artist:'Pavement', Album:'Brighten the Corners',
Price:11.99 }
]);
if(newData == "")
{
// Prevent the user from removing focus,
// and leave the cell editor open.
event.preventDefault();
// Write a message to the errorString property.
// This message appears when the user
// mouses over the editor.
]]>
</mx:Script>
<mx:DataGrid id="myGrid"
dataProvider="{initDG}"
editable="true"
itemEditEnd="formatData(event);">
<mx:columns>
<mx:DataGridColumn dataField="Artist"/>
<mx:DataGridColumn dataField="Album"/>
<mx:DataGridColumn dataField="Price"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
In this example, if the user’s reason for the event is CANCELLED, the event listener does
nothing.
If the reason is NEW_COLUMN, NEW_ROW, or OTHER, the event listener performs the following
actions:
1. Checks if the new cell value is an empty String.
2. If it is an empty String, the event listener calls the preventDefault() method to prevent
Flex from closing the editor and from updating the cell with the empty String.
3. Writes a message to the errorString property of the TextInput control. This message
causes a red box to appear around the TextInput control, and the message appears as a
tooltip when the user moves the mouse over the cell.
<mx:Script>
<![CDATA[
import mx.events.DataGridEvent;
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{Artist:'Pavement', Album:'Slanted and Enchanted',
Price:11.99},
{Artist:'Pavement', Album:'Brighten the Corners',
Price:11.99}
]);
]]>
</mx:Script>
<mx:DataGrid id="myGrid"
dataProvider="{initDG}"
editable="true"
itemEditBeginning="disableEditing(event);" >
<mx:columns>
<mx:DataGridColumn dataField="Artist"/>
<mx:DataGridColumn dataField="Album"/>
<mx:DataGridColumn dataField="Price"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
Although the preceding example uses the column index, you could inspect any property of the
DataGrid, or of the cell being edited, to make your decision about allowing the user to edit
the cell.
<mx:Script>
<![CDATA[
import mx.controls.TextInput;
import mx.events.DataGridEvent;
import mx.events.DataGridEventReason;
import mx.formatters.NumberFormatter;
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{Artist:'Pavement', Album:'Slanted and Enchanted',
Price:11.99},
{Artist:'Pavement', Album:'Brighten the Corners',
Price:11.99 }
]);
<mx:DataGrid id="myGrid"
dataProvider="{initDG}"
editable="true"
itemEditEnd="formatData(event);" >
<mx:columns>
<mx:DataGridColumn dataField="Artist"/>
<mx:DataGridColumn dataField="Album"/>
<mx:DataGridColumn dataField="Price"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.events.DataGridEvent;
import mx.events.DataGridEventReason;
import mx.collections.ArrayCollection;
import myComponents.CityStateEditor;
[Bindable]
public var initDG:ArrayCollection = new ArrayCollection([
{Company: 'Acme', Contact: 'Bob Jones',
Phone: '413-555-1212', City: 'Boston', State: 'MA'},
{Company: 'Allied', Contact: 'Jane Smith',
Phone: '617-555-3434', City: 'SanFrancisco', State: 'CA'}
]);
<mx:DataGrid id="myGrid"
rowHeight="75"
dataProvider="{initDG}"
editable="true"
itemEditEnd="processData(event);">
<mx:columns>
<mx:DataGridColumn dataField="Company" editable="false"/>
<mx:DataGridColumn dataField="Contact"/>
<mx:DataGridColumn dataField="Phone"/>
<mx:DataGridColumn dataField="City and State" width="150"
itemEditor="myComponents.CityStateEditor">
<mx:itemRenderer>
<mx:Component>
<mx:Text selectable="false" width="100%"
text="{data.City}, {data.State}"/>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
</mx:columns>
</mx:DataGrid>
</mx:Application>
Notice that the preceding example uses an inline item renderer to display the city and state in
a single column of the DataGrid control.
The event listener for the itemEditEnd event determines if the column being edited is the
city and state column. If so, the event listener performs the following actions:
1. Calls the preventDefault() method to prevent Flex from returning a String value.
2. Obtains the new city and state values from the item editor using the itemEditorInstance
property of the list control.
3. Calls the destroyItemEditor() method to close the item editor.
4. Calls the itemUpdated() method to cause the list control to update its display based on
the new data passed to it. If you do not call this method, the new data does not appear until
the next time the list control updates its appearance.
For examples of using the List and Tree controls, see Chapter 23, “Using Item Renderers and
Item Editors,” on page 939.
<mx:Script>
<![CDATA[
import mx.events.DataGridEvent;
import mx.collections.ArrayCollection;
import mx.controls.TextInput;
[Bindable]
public var initDG:ArrayCollection = new ArrayCollection([
{Company: 'Acme', Contact: 'Bob Jones',
Phone: '413-555-1212', City: 'Boston', State: 'MA'},
{Company: 'Allied', Contact: 'Jane Smith',
Phone: '617-555-3434', City: 'SanFrancisco', State: 'CA'}
]);
myGrid.editedItemRenderer.data.City=
myEditor(myGrid.itemEditorInstance).setCity.text;
myGrid.editedItemRenderer.data.State=
myEditor(myGrid.itemEditorInstance).pickState.selectedItem;
myGrid.destroyItemEditor();
myGrid.dataProvider.itemUpdated(myGrid.editedItemRenderer);
}
}
]]>
</mx:Script>
<mx:DataGrid id="myGrid"
rowHeight="75"
<mx:itemEditor>
<mx:Component className="myEditor">
<mx:VBox backgroundColor="yellow">
<mx:ComboBox id="pickState"
selectedItem="{data.State}">
<mx:dataProvider>
<mx:String>AL</mx:String>
<mx:String>AK</mx:String>
<mx:String>AR</mx:String>
<mx:String>CA</mx:String>
<mx:String>MA</mx:String>
</mx:dataProvider>
</mx:ComboBox>
</mx:VBox>
</mx:Component>
</mx:itemEditor>
</mx:DataGridColumn>
</mx:columns>
</mx:DataGrid>
</mx:Application>
The <mx:Component> tag includes a className property with a value of "myEditor". The
className property defines the name of the class that Flex creates to represent the inline item
editor, just as the name of the MXML file in the previous example defines the name of the
class for the component item editor. In the event listener for the itemEditEnd event, you can
access the TextInput and ComboBox controls as properties of the myEditor class.
<mx:Script>
<![CDATA[
// Define a property for returning the new value to the cell.
[Bindable]
public var newContact:String;
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{label1: "Order #2314", Contact: "John Doe",
Confirmed: false, Photo: "john_doe.jpg", Sent: false},
{label1: "Order #2315", Contact: "Jane Doe",
Confirmed: true, Photo: "jane_doe.jpg", Sent: false}
]);
]]>
</mx:Script>
<mx:DataGrid id="myDG"
width="500" height="250"
dataProvider="{initDG}"
variableRowHeight="true"
editable="true">
<mx:columns>
<mx:DataGridColumn dataField="Photo"
editable="false"/>
<mx:DataGridColumn dataField="Contact"
width="200"
editable="true"
rendererIsEditor="true"
itemRenderer="myComponents.MyContactEditable"
editorDataField="newContact"/>
<mx:DataGridColumn dataField="Confirmed"
editable="true"
rendererIsEditor="true"
itemRenderer="mx.controls.CheckBox"
editorDataField="selected"/>
<mx:DataGridColumn dataField="Sent"
editable="true"
rendererIsEditor="false"
itemEditor="mx.controls.CheckBox"
editorDataField="selected"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
<mx:Script>
<![CDATA[
// Define a property for returning the new value to the cell.
[Bindable]
public var returnPN:String;
]]>
</mx:Script>
<mx:PhoneNumberValidator id="pnV"
source="{newPN}"
property="text"
trigger="{newPN}"
triggerEvent="change"
required="true"/>
<mx:TextInput id="newPN"
text="{data.phone}"
updateComplete="returnPN=newPN.text;"
change="returnPN=newPN.text;"/>
</mx:VBox>
If the user enters an incorrect phone number, the PhoneNumberValidator draws a red box
around the editor and shows a validation error message when the user moves the mouse over
it.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var initDG:ArrayCollection = new ArrayCollection([
{name: 'Bob Jones', phone: '413-555-1212',
email: '[email protected]'},
{name: 'Sally Smith', phone: '617-555-5833',
email: '[email protected]'},
]);
]]>
</mx:Script>
<mx:DataGrid id="dg"
width="500" height="200"
editable="true"
dataProvider="{initDG}">
<mx:columns>
<mx:DataGridColumn dataField="name"
headerText="Name" />
<mx:DataGridColumn dataField="phone"
headerText="Phone"
itemEditor="myComponents.EditorPhoneValidator"
editorDataField="returnPN"/>
<mx:DataGridColumn dataField="email" headerText="Email" />
</mx:columns>
</mx:DataGrid>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.events.ListEvent;
import myComponents.EditorStateInfo;
<mx:List id="myList"
height="180" width="250"
editable="true"
itemRenderer="myComponents.RendererState"
itemEditor="myComponents.EditorStateInfo"
variableRowHeight="true"
backgroundColor="white"
<mx:Script>
<![CDATA[
import mx.collections.*;
import mx.controls.DateField;
import mx.collections.ArrayCollection;
[Bindable]
private var catalog:ArrayCollection = new ArrayCollection([
{confirmed: new Date(), Location: "Spain"},
{confirmed: new Date(2006,0,15), Location: "Italy"},
{confirmed: new Date(2004,9,24), Location: "Bora Bora"},
{confirmed: new Date(), Location: "Vietnam"}
]);
]]>
</mx:Script>
<mx:List id="myList"
width="300" height="300"
rowHeight="50"
dataProvider="{catalog}"
editable="true"
labelField="confirmed"
itemEditor="mx.controls.DateField"
editorDataField="selectedDate"/>
</mx:Application>
In this example, you specify "confirmed" as the value of the labelField property to specify
that the DateField control modifies that field of the data provider.
<mx:Script>
<![CDATA[
import mx.events.ListEvent;
import myComponents.TreeEditor;
<mx:Tree id="myTree"
width="400" height="400"
editable="true"
itemEditor="myComponents.TreeEditor"
editorHeightOffset="75" editorWidthOffset="-100"
editorXOffset="40" editorYOffset="30"
creationComplete="initCatalog(contacts1);"
itemEditBeginning="disableEditing(event);"
itemEditEnd="processData(event);"/>
</mx:Application>
You specify the custom item editor using the itemEditor property of a tree control. You also
use the editorHeightOffset, editorWidthOffset, editorXOffset, and editorYOffset
properties to position the item editor.
<mx:Script>
<![CDATA[
]]>
</mx:Script>
<!-- Display the text 'Phone:' and let the user edit it.-->
<mx:HBox>
<mx:Text text="Phone:"/>
<mx:TextInput id="contactPhone"
width="150"
text="{data.phone}"
change="newPhone=contactPhone.text;"/>
</mx:HBox>
CHAPTER 25
Using ToolTips 25
Adobe Flex ToolTips are a flexible method of providing helpful information to your users.
When a user moves the mouse pointer over graphical components, ToolTips pop up and text
appears. You can use ToolTips to guide users through working with your application or
customize them to provide additional functionality. This topic describes how to use ToolTips
in your Flex applications.
Contents
About ToolTips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1033
Creating ToolTips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1034
Using the ToolTip Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1042
Using error tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1055
Reskinning ToolTips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1059
About ToolTips
ToolTips are a standard feature of many desktop applications. They make the application
easier to use by displaying messages when the user moves the mouse pointer over an onscreen
element, such as a Button control.
The following image shows ToolTip text that appears when the user hovers the mouse pointer
over a button:
When the user moves the mouse pointer away from the component or clicks the mouse
button, the ToolTip disappears. If the mouse pointer remains over the component, the
ToolTip eventually disappears. The default behavior is to display only one ToolTip at a time.
1033
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
You can set the time it takes for the ToolTip to appear when a user moves the mouse pointer
over the component, and set the amount of time it takes for the ToolTip to disappear.
If you define a ToolTip on a container, the ToolTipManager displays the parent’s ToolTip for
the children if the child does not have one.
Flex ToolTips support style sheets and the dynamic loading of ToolTip text. ToolTip text does
not support embedded HTML. For more information on using style sheets and dynamic
loading of text, see “Setting styles in ToolTips” on page 1036 and “Using dynamic ToolTip
text” on page 1045.
Some Flex components have their own ToolTip-like “data tips.” These components include
the List control, most chart controls, and DataGrid control. For more information, see that
component’s documentation.
ToolTips are the basis for the accessibility implementation within Flex. All controls that
support accessibility do so by making their ToolTip text readable by screen readers such as
JAWS. For more information on accessibility, see Chapter 39, “Creating Accessible
Applications,” on page 1407.
Creating ToolTips
Every visual Flex component that extends the UIComponent class (which implements the
IToolTipManagerClient interface) supports a toolTip property. This property is inherited
from the UIComponent class. You set the value of the toolTip property to a text string and,
when the mouse pointer hovers over that component, the text string appears. The following
example sets the toolTip property text for a Button control:
<?xml version="1.0"?>
<!-- tooltips/BasicToolTip.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
</mx:Application>
<mx:VBox toolTip="VBOX">
<mx:Button id="b1" label="Button 1" toolTip="BUTTON"/>
<mx:Button id="b2" label="Button 2"/>
</mx:VBox>
</mx:Application>
When the mouse pointer is over button b1, the ToolTip displays BUTTON. When the
mouse pointer is over button b2 or anywhere in the VBox container except over button b1,
the ToolTip displays VBOX.
<mx:Style>
ToolTip {
fontFamily: "Arial";
fontSize: 19;
fontStyle: "italic";
color: #FF6699;
backgroundColor: #33CC99;
}
</mx:Style>
</mx:Application>
<mx:Script><![CDATA[
import mx.styles.StyleManager;
private function setToolTipStyle():void {
StyleManager.getStyleDeclaration("ToolTip").setStyle("fontStyle","italic");
StyleManager.getStyleDeclaration("ToolTip").setStyle("fontSize","19");
StyleManager.getStyleDeclaration("ToolTip").setStyle("fontFamily","Arial");
StyleManager.getStyleDeclaration("ToolTip").setStyle("color","#FF6699");
StyleManager.getStyleDeclaration("ToolTip").setStyle("backgroundColor","#33
CC99");
}
]]></mx:Script>
</mx:Application>
ToolTips use inheritable styles that you set globally. For example, you can set the fontWeight
of ToolTips with the StyleManager by setting it on the global selector, as the following
example shows:
<?xml version="1.0"?>
<!-- tooltips/ToolTipGlobalStyles.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="setToolTipStyle()">
<mx:Script><![CDATA[
import mx.styles.StyleManager;
private function setToolTipStyle():void {
StyleManager.getStyleDeclaration("global").setStyle("fontWeight","bold");
}
]]></mx:Script>
</mx:Application>
}
]]></mx:Script>
<mx:Button id="b1" label="Create Another Button"
click="createNewButton(event);" toolTip="Click this button to create a new
one."/>
</mx:Application>
Flex wraps the text of a ToolTip onto multiple lines to ensure that the width does not exceed
this value. If the text in the ToolTip box is not as wide as the maxWidth property, Flex creates
a box only wide enough for the text to fit.
[Embed(source="../assets/sound1.mp3")]
private var beepSound:Class;
private var myClip:Sound;
<!-- Define the ViewStack and the three child containers. -->
<mx:ViewStack id="vs1" borderStyle="solid" width="100%" height="150">
<mx:Canvas id="search" label="Search" toolTip="Search Screen">
<mx:Label text="Search Screen"/>
</mx:Canvas>
<mx:Canvas id="custInfo" label="Customer"
toolTip="Customer Info Screen">
<mx:Label text="Customer Info"/>
</mx:Canvas>
<mx:Canvas id="accountInfo" label="Account"
toolTip="Account Info Screen">
<mx:Label text="Account Info"/>
</mx:Canvas>
</mx:ViewStack>
</mx:VBox>
</mx:Application>
You can also set the value of the NavBar’s toolTipField property to point to the field in the
data provider that provides a ToolTip. The data provider in the following example defines
ToolTips in the myToolTip field:
<?xml version="1.0"?>
<!-- tooltips/ToolTipFieldExample.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:ButtonBar toolTipField="myToolTip">
<mx:Object label="OK" myToolTip="OK tip"/>
<mx:Object label="Cancel" myToolTip="Cancel tip"/>
</mx:ButtonBar>
</mx:Application>
The following example toggles ToolTips on and off when the user clicks the Toggle ToolTips
button:
<?xml version="1.0"?>
<!-- tooltips/ToggleToolTips.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import mx.managers.ToolTipManager;
</mx:Application>
Property Description
showDelay The length of time, in milliseconds, that Flex waits before displaying the ToolTip
box when a user moves the mouse pointer over a component that has a ToolTip.
To make the ToolTip appear instantly, set the showDelay property to 0.
The default value is 500 milliseconds, or half of a second.
hideDelay The length of time, in milliseconds, that Flex waits to hide the ToolTip box after
it appears. After Flex hides a ToolTip box, the user must move the mouse
pointer off the component and back onto it to see the ToolTip box again.
If you set the hideDelay property to 0, Flex does not display the ToolTip. Adobe
recommends that you use the default value of 10,000 milliseconds, or 10
seconds.
If you set the hideDelay property to Infinity, Flex does not hide the ToolTip
until the user triggers an event (such as moving the mouse pointer off the
component). The following example sets the hideDelay property to Infinity:
import mx.managers.ToolTipManager;
ToolTipManager.hideDelay = Infinity;
scrubDelay The length of time, in milliseconds, that a user can take when moving the mouse
between controls before Flex again waits for the duration of showDelay to
display a ToolTip box.
This setting is useful if the user moves quickly from one control to another; after
displaying the first ToolTip, Flex displays the others immediately rather than
waiting for the duration of the showDelay setting. The shorter the setting for
scrubDelay, the more likely that the user must wait for an amount of time
specified by the showDelay property in order to see the next ToolTip.
A good use of this property is if you have several buttons on a toolbar, and the
user will quickly scan across them to see brief descriptions of their functionality.
The default value is 100.
</mx:Application>
<mx:Script><![CDATA[
import mx.managers.ToolTipManager;
public function app_init():void {
ToolTipManager.showEffect = fadeIn;
}
]]></mx:Script>
</mx:Application>
By default, the font used in this example does not fade. You must use an embedded font to
achieve the embed effect. For more information on using embedded fonts, see “Using
embedded fonts” on page 838.
For more information about using effects and defining custom effects, see Chapter 19, “Using
Behaviors,” on page 719.
</mx:Application>
The text parameter defines the contents of the ToolTip. The x and y parameters define the x
and y coordinates of the ToolTip, relative to the application container. The
errorTipBorderStyle property sets the location of the pointer on the error tip. This
parameter is optional. If you specify this value in the createToolTip() method, Flex styles
the ToolTip as an error tip. The following example shows the valid values and their resulting
locations on the error tip:
These methods of casting differ only in the way they behave when a cast fails.
For more information about using error tips, see “Using error tips” on page 1055.
Flex displays the ToolTip until you destroy it. In general, you should not display more than
one ToolTip box at a time, because it is confusing to the user.
You can use the destroyToolTip() method to destroy the specified ToolTip object. The
destroyToolTip() method has the following signature:
destroyToolTip(toolTip:IToolTip):void
</mx:Panel>
In your application, you can create a custom ToolTip by intercepting the toolTipCreate
event handler of the target component. In the event handler, you instantiate the new ToolTip
and set its properties. You then point the toolTip property of the ToolTipEvent object to the
new ToolTip.
<mx:Button id="b1"
label="Delete"
toolTip=" "
toolTipCreate="createCustomTip('DELETE','Click this button to delete
the report.', event)"
/>
<mx:Button id="b2"
label="Generate"
toolTip=" "
toolTipCreate="createCustomTip('GENERATE','Click this button to
generate the report.', event)"
/>
<mx:Button id="b3"
label="Stop"
toolTip="Click this button to stop the creation of the report. This
button uses a standard ToolTip style."
/>
</mx:Application>
You also set the value of the ToolTip’s y position to be the same as the target component’s y
position to line the two up horizontally.
One way to get the necessary values so that you can calculate the x position of the ToolTip, is
to use an event handler. Event objects passed to an event handler can give you the x position
and the width of the target component.
<mx:Script>
<![CDATA[
import mx.controls.ToolTip;
import mx.managers.ToolTipManager;
<mx:TextInput id="a"
width="100"
focusIn="showTip(event)"
focusOut="destroyTip(event)"
/>
<mx:TextInput id="b"
width="100"
focusIn="showTip(event)"
focusOut="destroyTip(event)"
/>
</mx:Application>
tip = ToolTipManager.createToolTip(s,
pt.x + event.currentTarget.width + 10,
pt.y
) as ToolTip;
}
<mx:VBox >
<!-- A ToolTip inside a container. -->
<!-- The event handler for this ToolTip accounts for the control
being inside a container and positions the ToolTip using the
contentToGlobal() method. -->
<mx:TextInput id="b"
text="Good ToolTip placement"
width="175"
focusIn="showTipB(event)"
focusOut="destroyTip(event)"
/>
<mx:TextInput id="c"
text="Bad ToolTip placement"
width="175"
focusIn="showTipA(event)"
focusOut="destroyTip(event)"
/>
</mx:VBox>
</mx:Application>
You can customize the appearance of error tips by creating a new theme that overrides these
styles, or by overriding the style properties in your application. For more information on
creating themes, see “About themes” on page 828.
event.currentTarget.errorString = myError;
}
]]></mx:Script>
]]></mx:Script>
<mx:Panel rollOver="createBigTip(event)" rollOut="destroyBigTip()">
<mx:Button label="OK" toolTip="Save your changes and exit."/>
<mx:Button label="Apply" toolTip="Apply changes and continue."/>
<mx:Button label="Cancel" toolTip="Cancel and exit."/>
</mx:Panel>
</mx:Application>
For more information on using validators, see Chapter 44, “Validating Data,” on page 1529.
Reskinning ToolTips
This section describes how to apply a programmatic skin to ToolTip controls. It illustrates
some of the concepts presented earlier in this topic.
ToolTip skins are defined by the ToolTipBorder programmatic skin. This file is located in the
mx.skins.halo package.
4. Change the class name in the file, as the following example shows:
//public class ToolTipBorder extends RectangularBorder // Old name
public class MyToolTipBorder extends RectangularBorder // New name
5. Change the constructor to reflect the new class name, as the following example shows:
//public function ToolTipBorder() // Old constructor
public function MyToolTipBorder() // New constructor
7. Edit the class file to change the appearance of the ToolTip. You do this by editing the
“toolTip” case in the updateDisplayList() method. That is the method that draws the
ToolTip’s border and sets the default styles. Most commonly, you change the arguments
of the drawRoundRect() method to change the appearance of the ToolTip.
The following example adds a red tinge to the background of the ToolTip’s box by
replacing the default backgroundColor property with an array of colors:
var highlightAlphas:Array = [0.3,0.0];
drawRoundRect(3, 1, w-6, h-4, cornerRadius, [0xFF0000, 0xFFFFBB],
backgroundAlpha);
8. Save the class file.
CHAPTER 26
Contents
About the Cursor Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1063
Using the Cursor Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1064
Creating and removing a cursor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1065
Using a busy cursor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1066
1063
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Using the Cursor Manager
To use the Cursor Manager, you import the mx.managers.CursorManager class into your
application, and then reference its properties and methods.
The Cursor Manager controls a prioritized list of cursors, where the cursor with the highest
priority is currently visible. If the cursor list contains more than one cursor with the same
priority, the Cursor Manager displays the most recently created cursor.
You create a new cursor, and set an optional priority for the cursor, by using the static
setCursor() method of the CursorManager class. This method adds the new cursor to the
cursor list. If the new cursor has the highest priority, it is displayed immediately. If the priority
is lower than a cursor already in the list, it is not displayed until the cursor with the higher
priority is removed.
To remove a cursor from the list, you use the static removeCursor() method. If the cursor is
the currently displayed cursor, the Cursor Manager displays the next cursor in the list, if one
exists. If the list ever becomes empty, the Cursor Manager displays the default system cursor.
The setCursor() method has the following signature:
public static setCursor(cursorClass:Class, priority:int = 2,
xOffset:Number = 0, yOffset:Number = 0) : int
The following table describes the arguments for the setCursor() method:
xOffset The x offset of the cursor relative to the mouse pointer. The default Optional
value is 0.
yOffset The y offset of the cursor relative to the mouse pointer. The default Optional
value is 0.
This method returns the ID of the new cursor. You pass the ID to the removeCursor()
method to delete the cursor. This method has the following signature:
static removeCursor(cursorID:int):void
The Flex framework includes a default busy cursor. For information on using this cursor
see “Using a busy cursor” on page 1066.
<?xml version="1.0"?>
<!-- cursors\CursorManagerApp.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.managers.CursorManager;
import flash.events.*;
<mx:VBox>
<!-- Image control to load the image. -->
<mx:Image id="image1" complete="loadComplete(event);"/>
Or, you can reference a symbol from a SWF file, as the following example shows:
[Embed(source="assets/cursorList.swf", symbol="wait")]
var waitCursorSymbol:Class;
An advantage of using a SWF file is that you can create an animated cursor.
Method Description
setBusyCursor() Displays the busy cursor.
removeBusyCursor() Removes the busy cursor from the cursor list. If other busy cursor
requests are still active in the cursor list, which means that you
called the setBusyCursor() method more than once, a busy cursor
does not disappear until you remove all busy cursors from the list.
<mx:Script>
<![CDATA[
import mx.managers.CursorManager;
import flash.events.*;
<mx:VBox>
<!-- Image control to load the image. -->
<mx:Image id="image1" complete="loadComplete(event);"/>
<mx:Script>
<![CDATA[
import mx.managers.CursorManager;
import mx.managers.CursorManagerPriority;
import flash.events.*;
<mx:VBox>
<!-- Image control to load the image. -->
<mx:Image id="image1" complete="loadComplete(event);"/>
For the SWFLoader control, if you set the showBusyCursor property to true, Flex displays
the busy cursor when the first progress event of the control is triggered, and hides the busy
cursor when the complete event is triggered. The following example shows how you can
simplify the example in the section “Setting a busy cursor” on page 1066 by using the
showBusyCursor property:
<?xml version="1.0"?>
<!-- cursors\ShowBusyCursorApp.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:VBox>
<!-- SWFLoader control to load the image. -->
<mx:SWFLoader id="image1" showBusyCursor="true"/>
Contents
About localized Flex applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1071
Creating a localized application. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1072
1071
The localization workflow
To localize an application, you use the ResourceBundle API. You do this by adding
[ResourceBundle] metadata tags in ActionScript or @Resource calls in MXML, creating
localized properties files and localization classes and put them into a locale directory, and
using the mxmlc compiler to compile the main application.
Optionally, you can package libraries of localized properties files and ActionScript classes in a
SWC file that you create with the compc compiler. However, a resource bundle SWC file is
necessary only when you are creating a library rather than an application.
For more information about the mxmlc and compc utilities, see Chapter 9, “Using the Flex
Compilers,” in Building and Deploying Flex Applications.
[ResourceBundle("RegistrationForm")]
private static var rb:ResourceBundle;
]]></mx:Script>
<mx:Form>
<mx:FormItem label="@Resource(key='personname',
bundle='RegistrationForm')">
<mx:TextInput/>
</mx:FormItem>
<mx:FormItem label="@Resource(key='street_address',
bundle='RegistrationForm')">
<mx:TextInput/>
</mx:FormItem>
<mx:FormItem label="@Resource(key='city',
bundle='RegistrationForm')">
<mx:TextInput/>
</mx:FormItem>
<mx:FormItem label="@Resource(key='state',
bundle='RegistrationForm')">
<mx:TextInput/>
</mx:FormItem>
<mx:FormItem label="@Resource(key='zip',
bundle='RegistrationForm')">
<mx:TextInput/>
</mx:FormItem>
</mx:Form>
<mx:Button id="b1" label="@Resource(key='submit',
bundle='RegistrationForm')" click="registrationComplete()"/>
</mx:Application>
5. Use the following mxmlc command line to compile the application with the es_ES resource
bundle:
mxmlc -locale es_ES -source-path+=path_to_locale_dir/{locale}
-o Form-es.swf LocalizedForm.mxml
6. Run the two SWF files to see the different form labels and alerts in the applications.
The bundlename refers to a properties file in your compiler’s source path that stores the
localized data. It must match the name of the properties file, minus the .properties extension.
For example, if your properties file is called MyProps.properties, you use the ResourceBundle
metadata tag as the following example shows:
[ResourceBundle("MyProps")]
...
You cannot create a ResourceBundle instance in ActionScript by using the new keyword; you
must use the [ResourceBundle] metadata tag.
The compiler instantiates the variable. In your code, you can use the ResourceBundle API to
access keys in the resource bundle. This API includes the ResourceBundle.getString() and
ResourceBundle.getObject() methods.
[Bindable]
[ResourceBundle("RegistrationForm")]
private var rb:ResourceBundle;
]]></mx:Script>
</mx:Application>
For information on accessing objects with the getObject() method, see “Using localized
ActionScript classes” on page 1077.
The bundlename refers to a properties file in your compiler’s source path that stores the
localized data. As with the ResourceBundle metadata tag, the bundle name must match the
properties file name, minus the .properties extension.
</mx:Application>
[Bindable]
[ResourceBundle("RegistrationForm")]
private var rb:ResourceBundle;
[Bindable]
private var s:String;
</mx:Application>
<mx:Script><![CDATA[
import mx.resources.ResourceBundle;
[Bindable]
[ResourceBundle("MyObjectClassesBundle")]
private var rb:ResourceBundle;
b1.label = sc.returnString();
}
]]></mx:Script>
<mx:Button id="b1"/>
</mx:Application>
In this example, MyObjectClassesBundle is the name of a ResourceBundle subclass that you
create to embed your localized ActionScript classes.
return contentObj;
}
}
}
In this example, the localized ActionScript class is a simple class that has a method that returns
a String, as the following example shows:
package {
// Constructor
public function SimpleClass() {
}
}
You can store the localized ActionScript class files in your locale/{locale} directories, or any
directory that is accessible by the bundle class.
return contentObj;
}
}
}
[Bindable]
[ResourceBundle("MyEmbeddedClassesBundle")]
private var rb2:ResourceBundle;
[Bindable]
[ResourceBundle("MyObjectClassesBundle")]
private var rb:ResourceBundle;
[Bindable]
private var bird:Object = rb2.getObject("MyBird");
]]></mx:Script>
<mx:Button id="b1"/>
</mx:Application>
[Bindable]
[ResourceBundle("MyEmbeddedClassesBundle")]
private var rb2:ResourceBundle;
[Bindable]
[ResourceBundle("MyObjectClassesBundle")]
private var rb:ResourceBundle;
[Bindable]
private var bird:Object = rb2.getObject("MyBird");
]]></mx:Script>
<mx:Button id="b1"/>
</mx:Application>
/fr_FR/Grape.as This file is used because it is at the top of the search order.
/fr_FR/Orange.as This file is used because it is at the top of the search order.
When you specify a locale for a SWF file, you must also specify that same locale for the parent
of that SWF file if that SWF file is loaded into the parent.
You can then use the locale token to add the location of the locale files in the <source-
path>, as the following example shows:
<!-- list of path elements that form the roots of ActionScript class
hierarchies -->
<source-path>
<path-element>./user_classes</path-element>
<path-element>./locale/{locale}</path-element>
</source-path>
For more information about the mxmlc compiler, see Chapter 9, “Using the Flex Compilers,”
in Building and Deploying Flex Applications.
The following example shows a compc command line for creating a localized SWC file with
the fr_FR resource bundle:
compc -locale fr_FR -source-path locale/{locale} -include-resource-bundles
HelloWorld -output locale/fr_FR/HelloWorld.swc
For more information about the compc compiler, see Chapter 9, “Using the Flex Compilers,”
in Building and Deploying Flex Applications.
4
PART 4
1089
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
CHAPTER 28
Dynamically Repeating
Controls and Containers
28
This topic describes how to use Repeater components. Repeater components let you
dynamically repeat MXML content at run time.
Flex also supports list controls, which provide better performance when you display large
amounts of data. For more information about the HorizontalList, TileList, and List controls,
see Chapter 13, “Using Data-Driven Controls,” on page 447.
Contents
About Repeater components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1091
Using the Repeater component . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1092
Considerations when using a Repeater component . . . . . . . . . . . . . . . . . . . . . . . . . . 1113
1091
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The HorizontalList control is a list control that displays data horizontally, much like the
HBox container. The HorizontalList control always displays items from left to right. For more
information, see “HorizontalList control” on page 458.
The TileList control is a list control that displays data in a tile layout, much like the Tile
container. The TileList control provides a direction property that determines if the next
item is down or to the right. For more information, see “TileList control” on page 462.
The List control displays data in a single vertical column. For more information, see “List
control” on page 448.
Event Description
repeat Dispatched each time an item is processed and currentIndex and
currentItem are updated.
<mx:Script>
<![CDATA[
[Bindable]
public var myArray:Array=[1,2,3,4];
]]>
</mx:Script>
<mx:Script>
<![CDATA[
[Bindable]
public var myArray:Array=[10,20,30,40];
]]>
</mx:Script>
You can also use the startingIndex and count properties to adjust the starting point and
total number of executions. The count property sets a maximum on the number of times the
Repeater component executes. The count property is often—but not always—an exact
measure of the number of times that the content within the Repeater component will execute.
This number is because the Repeater component stops after the last element of the data
provider is reached, regardless of the value of the count property.
<mx:Script>
<![CDATA[
[Bindable]
public var myArray:Array=[100,200,300,400,500,600];
]]>
</mx:Script>
<mx:HRule/>
<mx:HRule/>
The first Repeater component loops through each element of the data provider, starting with
the first and stopping after the last. The second Repeater component starts at the second
element of the data provider and iterates four times, ending at the fifth element. The third
Repeater component starts with the fourth element and continues until the end of the data
provider array, and then stops. Only three iterations occur despite the fact that the count
property is set to 6.
You can still use the count property to restrict the number of iterations performed. You can
use the startingIndex property to skip entries at the beginning of the data provider.
In the preceding example, the first product entry in the XML file contains metadata that
other applications use to create column headers. Because it doesn’t make sense to include that
entry in the radio buttons, start the Repeater component at the second element of the data
provider, as in the following code example:
<?xml version="1.0"?>
<!-- repeater\StartSecondElement.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:HTTPService id="catalogService" url="assets/catalog.xml"
resultFormat="e4x"/>
<mx:XMLListCollection id="myXC"
source="{catalogService.lastResult.product}"/>
<mx:Repeater id="r" dataProvider="{myXC}"
startingIndex="1">
<mx:RadioButton id="Radio" label="{r.currentItem.name}"
width="150"/>
</mx:Repeater>
</mx:Application>
The preceding example produces the following output:
<mx:Script>
<![CDATA[
public function labelTrace():void {
for (var i:int = 0; i < nameLabel.length; i++)
trace(nameLabel[i].text);
}
]]>
</mx:Script>
<mx:Script>
<![CDATA[
public function labelTrace():void {
for (var i:int = 0; i < nameLabel.length; i++)
for (var j:int = 0; j < nameLabel[i].length; j++)
trace(nameLabel[i][j].text);
}
]]>
</mx:Script>
<mx:Model id="data">
<color>
<colorName>Red</colorName>
<colorName>Yellow</colorName>
<colorName>Blue</colorName>
</color>
</mx:Model>
In the previous example, the instances of the Label control are multiply indexed because they
are inside multiple Repeater components. For example, the index nameLabel[1][2] contains
a reference to the Label control produced by the second iteration of r and the third iteration
of r2.
The following example illustrates the getRepeaterItem() method. When the user clicks
each repeated Button control, the corresponding colorName value from the data model
appears in the Button control label.
<?xml version="1.0"?>
<!-- repeater\GetItem.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
public function clicker(cName:String):void {
foolabel.text=cName;
}
]]>
</mx:Script>
<mx:Model id="data">
<color>
<colorName>Red</colorName>
<colorName>Yellow</colorName>
<colorName>Blue</colorName>
</color>
</mx:Model>
<mx:ArrayCollection id="myAC" source="{data.colorName}"/>
The code in the following example uses the getRepeaterItem() method to display a specific
URL for each Button control that the user clicks. The Button controls must share a common
data-driven click handler, because you cannot use binding expressions inside event handlers.
However, the getRepeaterItem() method lets you change the functionality for each Button
control.
<?xml version="1.0"?>
<!-- repeater\DisplayURL.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
[Bindable]
public var dp:Array = [ { label: "Flex",
url: "http://www.adobe.com/flex" },
{ label: "Flash", url: "http://www.adobe.com/flash" } ];
]]>
</mx:Script>
Property Description
instanceIndices Array that contains the indices required to reference the component from its
document. This Array is empty unless the component is in one or more
Repeater components. The first element corresponds to the outermost
Repeater component. For example, if the id is b and instanceIndices is
[2,4], you would reference it on the document as b[2][4].
repeaters Array that contains references to the Repeater components that produced
the component. The Array is empty unless the component is in one or more
Repeater component. The first element corresponds to the outermost
Repeater component.
repeaterIndices Array that contains the indices of the items in the dataProvider properties of
the Repeater components that produced the component. The Array is
empty unless the component is within one or more Repeater components.
The first element corresponds to the outermost Repeater component. For
example, if repeaterIndices is [2,4], the outer Repeater component used
its dataProvider[2] data item and the inner Repeater component used its
dataProvider[4] data item.
This property differs from instanceIndices if the startingIndex of any of the
Repeater components is not 0. For example, even if a Repeater component
starts at dataProvider item 4, the document reference of the first repeated
component is b[0], not b[4].
<mx:Script>
<![CDATA[
import mx.controls.Alert;
[Bindable]
public var myArray:Array=[1,2];
]]>
</mx:Script>
The following example application uses the instanceIndices property to set the text
property of a TextInput control when the user clicks the corresponding Button control in the
set of repeated Button and TextInput controls. You need to use the instanceIndices
property because you must get the correct object dynamically; you cannot get it by its id
value.
<mx:Script>
<![CDATA[
[Bindable]
public var myArray:Array=[1,2,3,4,5,6,7,8];
]]>
</mx:Script>
<mx:Script>
<![CDATA[
[Bindable]
public var myArray:Array = [1,2,3,4,5,6,7,8];
]]>
</mx:Script>
The value of the repeaterIndices property is equal to the startingIndex property on the
first iteration of the Repeater component. Subtracting the startingIndex value from the
repeaterIndices value always yields the instanceIndices value. An alternative,
equivalent click event would be:
click="myText[event.target.instanceIndices].text=event.target.repeaterIndices.to
String()"/>
<mx:Script>
<![CDATA[
[Bindable]
public var dp:Array=[1,2,3,4];
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.controls.Alert;
public function getLabelRep():void {
Alert.show(comp.repbutton[1].label);
}
]]>
</mx:Script>
<MyComp:CustButton id="comp"/>
When a Repeater component re-executes, it destroys any children that it previously created
(assuming the recycleChildren property is set to false), and then reinstantiates its children
based on the current dataProvider property. The number of children in the container might
change, and the container layout changes to accommodate any changes to the number of
children.
CHAPTER 29
Contents
About view states . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1115
Create and apply view states . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1123
Defining view state overrides. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1133
Defining view states in custom components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1149
Using view states with a custom item renderer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1152
Using view states with history management. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1156
Creating your own override classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1158
1115
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
At its simplest, a view state defines a particular view of a component. For example, a product
thumbnail could have two view states; a base state with minimal information, and a “rich”
state with links for more information or to add the item to a shopping cart, as the following
figure shows:
To create a view state, you define a base state, and then define a set of changes, or overrides,
that modify the base state to define the new view state. Each additional view state can modify
the base state by adding or remove child components, by setting style and property values, or
by defining state-specific event handlers.
A view state does not have to modify the base state. A view state can specify modifications to
any other view state. This lets you create a set of view states that share common functionality
while adding the overrides specific to each view state. For more information, see “Basing a
view state on another view state” on page 1127.
LinkButton control
Notice the following changes to the base view state to create this new view state:
■ The title of the Panel container is set to Register
■ The Form container has a new TextInput control for confirming the password
■ The label of the Button control is set to Register
■ The LinkButton control has been replaced with a new LinkButton control that lets the
user change state back to the base view state
When the user clicks the Return to Login link, the view state changes back to base view state
to display the Login form, reversing all of the changes made when changing to the register
view state.
The following table shows the classes that you use to define view states:
Class Description
AddChild and RemoveChild Adds or removes a child component as part of a change of view
state. For more information, see “Adding and removing
components by using overrides” on page 1137.
The following example creates the Login and Register forms shown in “Example: Login form
application” on page 1118. This application has the following features:
■ When the user clicks the Need to Register LinkButton control, the event handler for the
click event sets the view state to Register.
■ The Register state code adds a TextInput control, changes properties of the Panel
container and Button control, removes the existing LinkButton controls, and adds a new
LinkButton control.
For an example that adds a transition to animate the change between view states, see
“Example: Using transitions with a login form” on page 1165.
<?xml version="1.0"?>
<!-- states\LoginExample.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
verticalAlign="middle">
<!-- The Application class states property defines the view states.-->
<mx:states>
<mx:State name="Register">
<!-- Add a TextInput control to the form. -->
<mx:AddChild relativeTo="{loginForm}"
position="lastChild">
<mx:FormItem id="confirm" label="Confirm:">
<mx:TextInput/>
</mx:FormItem>
</mx:AddChild>
<mx:Panel id="loginPanel"
title="Login"
horizontalScrollPolicy="off"
verticalScrollPolicy="off">
<mx:Form id="loginForm">
<mx:FormItem label="Username:">
<mx:TextInput/>
</mx:FormItem>
<mx:ControlBar>
<!-- Use the LinkButton to change to the Register view state.-->
<mx:LinkButton id="registerLink"
label="Need to Register?"
click="currentState='Register'"/>
<mx:Spacer width="100%" id="spacer1"/>
<mx:Button label="Login" id="loginButton"/>
</mx:ControlBar>
</mx:Panel>
</mx:Application>
<!-- Define the two view states, in addition to the base state.-->
<mx:states>
<mx:State name="One">
<mx:SetProperty target="{p1}" name="x" value="110"/>
<mx:SetProperty target="{p1}" name="y" value="0"/>
<mx:SetProperty target="{p1}" name="width" value="200"/>
<mx:SetProperty target="{p1}" name="height" value="210"/>
<mx:SetProperty target="{p2}" name="x" value="0"/>
<mx:SetProperty target="{p2}" name="y" value="0"/>
<mx:SetProperty target="{p2}" name="width" value="100"/>
<mx:SetProperty target="{p2}" name="height" value="100"/>
<mx:SetProperty target="{p3}" name="x" value="0"/>
<mx:SetProperty target="{p3}" name="y" value="110"/>
<mx:SetProperty target="{p3}" name="width" value="100"/>
<mx:SetProperty target="{p3}" name="height" value="100"/>
</mx:State>
<mx:State name="Two">
<mx:SetProperty target="{p2}" name="x" value="110"/>
<mx:SetProperty target="{p2}" name="y" value="0"/>
<mx:SetProperty target="{p2}" name="width" value="200"/>
<mx:SetProperty target="{p2}" name="height" value="210"/>
<mx:SetProperty target="{p3}" name="x" value="0"/>
<mx:SetProperty target="{p3}" name="y" value="110"/>
<mx:SetProperty target="{p3}" name="width" value="100"/>
<mx:SetProperty target="{p3}" name="height" value="100"/>
</mx:State>
</mx:states>
<!-- Define the Canvas container holding the three Panel containers.-->
<mx:Canvas id="pm" width="100%" height="100%">
<mx:Panel id="p1" title="One"
x="0" y="0" width="100" height="100"
click="currentState='One'">
<mx:Label fontSize="24" text="One"/>
</mx:Panel>
For more information, see “Setting overrides on component properties” on page 1134.
Styles,by using the SetStyle class. The following line sets the color property of the
button1 Button control as part of a view state:
<mx:SetStyle target="{button1}" name="color" value="0xAAAAAA"/>
For more information, see “Setting overrides on component styles” on page 1136.
■ Adding or removing child objects, by using the AddChild and RemoveChild classes. For
example, the following lines add a Button child control to the v1 VBox control as part of
a view state:
<mx:AddChild relativeTo="{v1}">
<mx:Button label="New Button"/>
</mx:AddChild>
For more information, see “Adding and removing components by using overrides”
on page 1137.
For more information, see “Setting overrides on event handlers” on page 1146.
■ Using a custom class that you define by implementing the IOverride interface. For
information on creating and using custom overrides, see “Creating your own override
classes” on page 1158.
You can also change a component’s view state by calling the setCurrentState() method of
the UIComponent class. Use this method when you do not want to apply a transition that you
have defined between two view states. For more information on transitions, see Chapter 30,
“Using Transitions,” on page 1163.
The following example code lets the user change between two view states by clicking Button
controls; button b1 sets the view state to the newButton state, and button b2 sets the view
state to the base state.
<mx:Button id="b1" label="Add a Button" click="currentState='newButton';"/>
<mx:Button id="b2" label="Remove Added Button" click="currentState='';"/>
<mx:states>
<!-- Define the new view state. -->
<mx:State name="NewButton">
<mx:VBox id="v1">
<mx:Button id="b1"/>
<mx:states>
<mx:State name="NewButton">
<mx:AddChild relativeTo="{v1}">
<mx:Button id="b3" label="New Button"/>
</mx:AddChild>
<mx:VBox id="v1">
<mx:Button id="b1"/>
<mx:Button id="b2" enabled="false"/>
<mx:states>
<mx:State name="NewButton">
<mx:AddChild relativeTo="{v1}">
<mx:Button id="b2" label="New Button B2"/>
</mx:AddChild>
<mx:SetProperty target="{b1}"
name="enabled" value="false"/>
</mx:State>
<mx:VBox id="v1">
<mx:Button id="b1" label="Initial Button"/>
<mx:Script>
<![CDATA[
import mx.states.*;
import mx.controls.Button;
// Initialization method to
// create a view state in ActionScript.
private function createState():void {
<mx:Panel id="loginPanel"
title="Login"
horizontalScrollPolicy="off"
verticalScrollPolicy="off">
<mx:Form id="loginForm">
<mx:FormItem label="Username:">
<mx:TextInput/>
</mx:FormItem>
<mx:FormItem label="Password:">
<mx:TextInput/>
</mx:FormItem>
</mx:Form>
<mx:ControlBar>
<!-- Use the LinkButton to change to the Register view state.-->
<mx:LinkButton id="registerLink"
label="Need to Register?"
click="currentState='Register'"/>
<mx:Spacer width="100%" id="spacer1"/>
<mx:Button label="Login" id="loginButton"/>
</mx:ControlBar>
</mx:Panel>
</mx:Application>
<mx:states>
<mx:State name="Register">
<mx:SetProperty
target="{loginPanel}"
name="title" value="Register"/>
<mx:SetProperty
target="{loginButton}"
name="label" value="Register"/>
</mx:State>
</mx:states>
<mx:Panel id="loginPanel"
title="Login"
horizontalScrollPolicy="off"
verticalScrollPolicy="off">
<mx:Form id="loginForm">
<mx:Button label="Login" id="loginButton"/>
</mx:Form>
<mx:ControlBar width="100%">
<mx:Button label="Change State"
click="currentState =
currentState=='Register' ? '':'Register';"/>
</mx:ControlBar>
</mx:Panel>
</mx:Application>
<mx:Script>
<![CDATA[
// Define a variable in ActionScript.
[Bindable]
public var registerValue:String="Register";
]]>
</mx:Script>
<mx:states>
<mx:State name="Register">
<mx:SetProperty
target="{loginPanel}"
name="title" value="{registerValue}"/>
<mx:SetProperty
target="{loginButton}"
name="label" value="{registerValue}"/>
</mx:State>
</mx:states>
<mx:Panel id="loginPanel"
title="Login"
horizontalScrollPolicy="off"
verticalScrollPolicy="off">
<mx:Form id="loginForm">
<mx:Button label="Login" id="loginButton"/>
</mx:Form>
<mx:ControlBar width="100%">
<mx:Button label="Change State"
click="currentState =
currentState=='Register' ? '':'Register';"/>
</mx:ControlBar>
</mx:Panel>
</mx:Application>
When you switch to the Register state, the value property of the SetProperty class is
determined by the current value of the registerValue variable. However, this binding occurs
only when you switch to the Register view state; if you modify the value of the registerValue
variable after switching to the Register view state, the title property of the target component
is not updated.
<mx:states>
<mx:State name="Register">
<mx:SetProperty
target="{loginPanel}"
name="title" value="Register"/>
<mx:SetStyle
target="{loginPanel}"
name="backgroundColor" value="0x00FFFF"/>
<mx:SetProperty
target="{loginButton}"
name="label" value="Register"/>
<mx:SetStyle
target="{loginButton}"
name="color" value="0xFFFF00"/>
</mx:State>
</mx:states>
<mx:Panel id="loginPanel"
title="Login"
horizontalScrollPolicy="off"
verticalScrollPolicy="off">
<mx:Form id="loginForm">
<mx:Button label="Login" id="loginButton"/>
</mx:Form>
<mx:ControlBar width="100%">
<mx:Button label="Change State"
click="currentState =
currentState=='Register' ? '':'Register';"/>
</mx:ControlBar>
</mx:Panel>
</mx:Application>
<mx:states>
<mx:State name="NewButton">
<mx:AddChild relativeTo="{h1}" position="firstChild">
<mx:Button id="buttonNew" label="New Button"/>
</mx:AddChild>
</mx:State>
</mx:states>
<mx:HBox id="h1">
<mx:Button label="Change State"
click=
"currentState = currentState=='NewButton' ? '':'NewButton';"/>
</mx:HBox>
</mx:Application>
You can add multiple child components, or a container that contains multiple child
components, as the following example shows:
<?xml version="1.0"?>
<!-- states\StatesAddRelativeMultiple.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:states>
<mx:State name="NewVBox">
<mx:AddChild relativeTo="{v1}">
<mx:VBox id="v2">
<mx:Button id="buttonNew1" label="New Button"/>
<mx:Button id="buttonNew2" label="New Button"/>
<mx:Button id="buttonNew3" label="New Button"/>
</mx:VBox>
</mx:AddChild>
</mx:State>
</mx:states>
<mx:VBox id="v1">
<mx:Button label="Change State"
click=
"currentState = currentState=='NewVBox' ? '':'NewVBox';"/>
</mx:VBox>
</mx:Application>
<mx:states>
<mx:State name="NewVBox">
<mx:AddChild relativeTo="{v1}">
<mx:VBox id="v2"/>
</mx:AddChild>
<mx:AddChild relativeTo="{v2}">
<mx:Button id="buttonNew1" label="New Button"/>
</mx:AddChild>
<mx:AddChild relativeTo="{v2}">
<mx:Button id="buttonNew2" label="New Button"/>
</mx:AddChild>
<mx:AddChild relativeTo="{v2}">
<mx:Button id="buttonNew3" label="New Button"/>
</mx:AddChild>
</mx:State>
</mx:states>
<mx:VBox id="v1">
<mx:Button label="Change State"
click=
"currentState = currentState=='NewVBox' ? '':'NewVBox';"/>
</mx:VBox>
</mx:Application>
<mx:states>
<mx:State name="NewParent">
<mx:RemoveChild target="{button1}"/>
<mx:AddChild target="{button1}" relativeTo="{v2}"/>
</mx:State>
</mx:states>
Because targetFactory property is the default property of the AddChild class, the previous
example is equivalent to the following:
<mx:AddChild relativeTo="{v1}">
<mx:targetFactory>
<mx:Button id="b0" label="New Button"/>
</mx:targetFactory>
</mx:AddChild>
You can specify either of the following items to the targetFactory property:
■ A Flex component, (that is, any class that is a subclass of the UIComponent class), such as
the Button control. If you use a Flex component, the Flex compiler automatically wraps
the component in a factory class.
■ A factory class that implements the IDeferredInstance interface and creates the child
instance or instances. “Example: Adding a Button control using the IDeferredInstance
interface” on page 1145.
When you use the targetFactory property to specify the child, you can optionally use the
creationPolicy property to specify the creation policy. The creationPolicy property
supports the following values:
auto Creates the child instance when it is first added by a change to the view state. This is
the default value. In ActionScript, specify this property by using the
mx.core.ContainerCreationPolicy.AUTO constant.
all Creates the child instance at application startup. In ActionScript, specify this property
by using the ContainerCreationPolicy.ALL constant. This is equivelant to using the
target property.
The following example adds a child and has Flex create a child when the application first
starts. The application does not display the child until the view state with the AddChild tag is
activated.
<mx:AddChild relativeTo="{v1}" position="lastChild" creationPolicy="all">
<mx:Button id="b0" label="New Button"/>
</mx:AddChild>
<mx:Script>
<![CDATA[
<mx:states>
<!-- Create the Button control at application startup. -->
<mx:State name="cpAll">
<mx:AddChild relativeTo="{myPanel}" creationPolicy="all">
<mx:Button id="newButton"/>
</mx:AddChild>
</mx:State>
<!-- Create the Button control when you want to create it. -->
<mx:State name="cpNone">
<mx:AddChild id="noCP"
relativeTo="{myPanel}" creationPolicy="none">
<mx:Button label="cpNone button"/>
</mx:AddChild>
</mx:State>
</mx:states>
<mx:Panel id="myPanel"
title="Static and dynamic states"
width="300" height="150">
<!-- Create the Button control for the noCP state that
</mx:Panel>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.core.*;
import mx.states.*;
[Bindable]
public var defInst:DeferredInstanceFromFunction =
new DeferredInstanceFromFunction(createMyButton);
<mx:states>
<mx:State name="deferredButton">
<mx:AddChild relativeTo="{myPanel}" targetFactory="{defInst}"/>
</mx:State>
</mx:states>
<mx:Panel id="myPanel"
title="Static and dynamic states"
width="300" height="150">
<mx:Button id="myButton2"
label="Toggle Deferred Button"
click="currentState =
currentState == 'deferredButton' ? '' : 'deferredButton';"/>
</mx:Panel>
</mx:Application>
You use the SetEventHandler.name property to specify the event name for the associated
event handler. Notice that you only specify the name of the event handler to the
handlerFunction property because that event handler is required to take a single argument
of type flash.events.Event. Therefore, the function handler2 must have the following
declaration:
private function handler2(event:Event):void
{
The following example shows how you specify a handler function that takes two arguments;
the Event object and a user ID String variable:
<mx:SetEventHandler target="{myButton1}"
name="click" handler="myAlert(event, userID)"/>
<mx:Script>
<![CDATA[
import flash.events.Event;
<mx:states>
<mx:State name="State1">
<mx:SetEventHandler target="{b1}"
name="click"
handlerFunction="handlerState1"/>
<mx:SetProperty target="{b1}"
name="label" value="Click Me: State 1"/>
</mx:State>
<mx:State name="State2">
<mx:SetEventHandler target="{b1}"
name="click"
handler="ta1.text='Specify an inline event listener';"/>
<mx:SetProperty target="{b1}"
name="label" value="Click Me: State 2"/>
</mx:State>
<mx:State name="State3">
<mx:SetEventHandler target="{b1}"
name="click"
handler="handlerState3('Event listener arg');"/>
<mx:SetProperty target="{b1}"
name="label" value="Click Me: State 3"/>
</mx:State>
</mx:states>
<mx:Button id="b1"
label="Click Me: Base State"
click="handlerBase();"/>
<mx:VBox>
<mx:Button
label="Set state 1, use handlerFunction property"
click="currentState='State1';"/>
<mx:Button
label="Set state 2, specify inline handler"
click="currentState='State2';"/>
<mx:Button
label="Set state 3, specify handler function"
click="currentState='State3';"/>
<mx:Button
label="Set base state"
click="currentState='';"/>
</mx:VBox>
</mx:Application>
<mx:Script>
<![CDATA[
[Embed(source="closeButtonDownSkin.jpg")]
[Bindable]
public var closeBDown:Class;
[Embed(source="closeButtonOverSkin.jpg")]
[Bindable]
public var closeBOver:Class;
<mx:states>
<mx:State name="collapsed">
<mx:SetProperty
name="height"
value="{getStyle('headerHeight')}"/>
<mx:SetStyle
name="closeButtonUpSkin"
value="{closeBUp}"/>
<mx:SetStyle
name="closeButtonDownSkin"
value="{closeBDown}"/>
<mx:SetStyle
name="closeButtonOverSkin"
value="{closeBOver}"/>
</mx:State>
</mx:states>
</mx:TitleWindow>
<mx:ControlBar width="100%">
<mx:Label text="Quantity"/>
<mx:NumericStepper/>
<!-- Use Spacer to push Button control to the right. -->
<mx:Spacer width="100%"/>
<mx:Button label="Add to Cart"/>
</mx:ControlBar>
</MyComp:StateTitleWindow>
</mx:Application>
In this example, the application item renderer’s two view states have different child
components and have different component styles. The summary state, for example, includes
an availability label and a star rating image, and has no border. The rolled-over state replaces
the label and rating components with three buttons, and has an outset border.
For information on item renderers, see Chapter 23, “Using Item Renderers and Item Editors,”
on page 939.
<mx:TileList id="myList"
dataProvider="{catArray}"
columnWidth="150"
rowHeight="150"
width="310"
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
horizontalAlign="center"
verticalAlign="top"
mouseOver="currentState='showdesc'"
mouseOut="currentState=''">
<!-- In the base state, display the image and the label. -->
<mx:Image id="img1"
source="{data.image}"
width="75"
height="75"/>
<mx:Label text="{data.name}"/>
<mx:states>
<mx:State name="showdesc">
<!-- In the showdesc state, add the price, make the image bigger,
and put the description in the parent application's TextArea.-->
<mx:AddChild>
<mx:Text text="{data.price}"/>
</mx:AddChild>
<mx:SetProperty target="{img1}" name="width" value="85"/>
<mx:SetProperty target="{img1}" name="height" value="85"/>
<mx:SetProperty target="{parentApplication.t1}" name="text"
value="{data.description}"/>
</mx:State>
</mx:states>
</mx:VBox>
<mx:Script>
<![CDATA[
import mx.managers.HistoryManager;
/////////////////////////
// IHistoryState methods
/////////////////////////
// Restore the state and searchString value.
public function loadState(state:Object):void {
if (state) {
currentState = state.currentState;
searchString = searchInput.text = state.searchString;
}
else {
currentState = '';
}
}
// Save the current state and the searchString value.
public function saveState():Object {
var state:Object = {};
state.currentState = currentState;
state.searchString = searchString;
return state;
}
/////////////////////////
// App-specific scripts
/////////////////////////
// The search string value.
[Bindable]
public var searchString:String;
<mx:states>
<!-- The state for displaying the search results -->
<mx:State name="results">
<mx:SetProperty target="{p}" name="width" value="100%" />
<mx:SetProperty target="{p}" name="height" value="100%" />
<mx:SetProperty target="{p}" name="title" value="Results" />
<mx:AddChild relativeTo="{searchFields}">
<mx:Button label="Reset" click="reset()" />
</mx:AddChild>
<mx:AddChild relativeTo="{p}">
<mx:Label text="Search results for {searchString}" />
</mx:AddChild>
</mx:State>
</mx:states>
Method Description
initialize() Initializes the override.
apply() Saves the original value and applies the override.
remove() Restores the original value.
filters.push(new BlurFilter());
obj.filters = filters;
}
filters.pop();
obj.filters = filters;
}
}
}
<mx:states>
<mx:State name="State1">
<myOverride:AddBlur target="{b1}"/>
</mx:State>
</mx:states>
<mx:Button id="b1"
label="Click Me: Base State"/>
<mx:Button
label="Set state 1"
click="currentState='State1';"/>
<mx:Button
label="Set base state"
click="currentState='';"/>
</mx:Application>
CHAPTER 30
Using Transitions 30
View states let you change appearance of an application, typically in response to a user action.
Transitions define how a change of view state looks as it occurs on the screen. You define a
transition by using the effect classes, in combination with several effects designed explicitly for
handling transitions. This topic describes how to define transitions to work with view states.
To use transitions, you should be familiar with how effects and view states work. For more
information on effects, see Chapter 19, “Using Behaviors,” on page 719. For more
information on view states, see Chapter 29, “Using View States,” on page 1115.
Contents
About transitions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1163
Defining transitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1167
Handling events when using transitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1174
Using action effects in a transition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1175
Filtering effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1179
Transition tips and troubleshooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1192
About transitions
View states let you vary the content and appearance of an application, typically in response to
a user action. To use view states, you define the base view state of an application, and one or
more additional view states.
When you change view states, Adobe Flex performs all the visual changes to the application at
the same time. That means when you resize, move, or in some other way alter the appearance
of the application, the application appear to jump from one view state to the next.
Instead, you might want to define a smooth visual change from one view state to the next, in
which the change occurs over a period of time. A transition is one or more effects grouped
together to play when a view state change occurs.
1163
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
For example, your application defines a form that in its base view state shows only a few fields,
but in an expanded view state shows additional fields. Rather than jumping from the base
version of the form to the expanded version, you define a Flex transition that uses the Resize
effect to expand the form, and then uses the Fade effect to slowly make the new form elements
appear on the screen.
When a user changes back to the base version of the form, your transition uses a Fade effect to
make the fields of the expanded form disappear, and then uses the Resize effect to slowly
shrink the form back to its original size.
By using a transition, you can apply one or more effects to the form, to the fields added to the
form, and to fields removed from the form. You can apply the same effects to each form field,
or apply different effects. You can also define one set of effects to play when you change state
to the expanded form, and a different set of effects to play when changing from the expanded
state back to the base state.
<mx:Script>
<![CDATA[
// Import easing classes if you use them only in MXML.
import mx.effects.easing.Bounce;
]]>
</mx:Script>
<!-- Define the transition to animate the change of view state. -->
<mx:transitions>
<mx:Transition>
<mx:Parallel
targets="{[loginPanel, registerLink, loginButton, confirm]}">
<mx:Resize duration="500" easingFunction="Bounce.easeOut"/>
<mx:Sequence target="{confirm}">
<mx:Blur duration="200" blurYFrom="1.0" blurYTo="20.0"/>
<mx:Blur duration="200" blurYFrom="20.0" blurYTo="1"/>
</mx:Sequence>
</mx:Parallel>
</mx:Transition>
</mx:transitions>
<mx:states>
<mx:State name="Register">
<mx:AddChild relativeTo="{loginForm}"
position="lastChild">
<mx:FormItem id="confirm" label="Confirm:">
<mx:TextInput/>
</mx:FormItem>
</mx:AddChild>
<mx:SetProperty target="{loginPanel}"
name="title" value="Register"/>
<mx:SetProperty target="{loginButton}"
name="label" value="Register"/>
<mx:RemoveChild target="{registerLink}"/>
<mx:AddChild relativeTo="{spacer1}" position="before">
<mx:LinkButton label="Return to Login"
click="currentState=''"/>
</mx:AddChild>
<mx:Panel
title="Login" id="loginPanel"
horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:Form id="loginForm">
<mx:FormItem label="Username:">
<mx:TextInput/>
</mx:FormItem>
<mx:FormItem label="Password:">
<mx:TextInput/>
</mx:FormItem>
</mx:Form>
<mx:ControlBar>
<mx:LinkButton id="registerLink"
label="Need to Register?"
click="currentState='Register'"/>
<mx:Spacer width="100%" id="spacer1"/>
<mx:Button label="Login" id="loginButton"/>
</mx:ControlBar>
</mx:Panel>
</mx:Application>
Property Definition
fromState A String that specifies the view state that you are changing from when you
apply the transition. The default value is an asterisk, "*", which means any
view state.
toState A String that specifies the view state that you are changing to when you apply
the transition. The default value is an asterisk, "*", which means any view
state.
effect The Effect object to play when you apply the transition. Typically, this is a
composite effect, such as the Parallel or Sequence effect, that contains
multiple effects.
You can define multiple Transition objects in an application. The UIComponent class
includes a transitions property that you set to an Array of Transition objects. For example,
you define an application with three Panel containers and three view states, as the following
example shows:
<!-- Define the two view states, in addition to the base state.-->
<mx:states>
<mx:State name="One">
<mx:SetProperty target="{p1}" name="x" value="110"/>
<mx:SetProperty target="{p1}" name="y" value="0"/>
<mx:SetProperty target="{p1}" name="width" value="200"/>
<mx:SetProperty target="{p1}" name="height" value="210"/>
<mx:SetProperty target="{p2}" name="x" value="0"/>
<mx:SetProperty target="{p2}" name="y" value="0"/>
<mx:SetProperty target="{p2}" name="width" value="100"/>
<mx:SetProperty target="{p2}" name="height" value="100"/>
<mx:SetProperty target="{p3}" name="x" value="0"/>
<mx:SetProperty target="{p3}" name="y" value="110"/>
<mx:SetProperty target="{p3}" name="width" value="100"/>
<mx:SetProperty target="{p3}" name="height" value="100"/>
</mx:State>
<mx:State name="Two">
<mx:SetProperty target="{p2}" name="x" value="110"/>
<mx:SetProperty target="{p2}" name="y" value="0"/>
<mx:SetProperty target="{p2}" name="width" value="200"/>
<mx:SetProperty target="{p2}" name="height" value="210"/>
<mx:SetProperty target="{p3}" name="x" value="0"/>
<mx:SetProperty target="{p3}" name="y" value="110"/>
<mx:SetProperty target="{p3}" name="width" value="100"/>
<mx:SetProperty target="{p3}" name="height" value="100"/>
</mx:State>
</mx:states>
<!-- Define the Canvas container holding the three Panel containers.-->
<mx:Canvas id="pm" width="100%" height="100%" >
<!-- Play for a change from any view state to any other view state. -->
<mx:Transition id="toAnyFromAny" fromState="*" toState="*">
...
</mx:Transition>
</mx:transitions>
If a state change matches two transitions, the toState property takes precedence over the
fromState property. If more than one transition matches, Flex uses the first matching
definition detected in the transition Array.
You removed the third panel from the transition, so it is no longer a target of the Move and
Resize effects. Therefore, the third panel appears to jump to its new position and size during
the change in view state. The other two panels show a smooth change in size and position for
the 400-millisecond (ms) duration of the effects.
You can also use the target or targets properties of the effects within the transition to
explicitly specify the effect target, as the following example shows:
<mx:Parallel id="t1" targets="{[p1,p2,p3]}">
<mx:Move targets="{[p1,p2]}" duration="400"/>
<mx:Resize duration="400"/>
</mx:Parallel>
In this example, the Resize effect plays on all three panels, while the Move effect plays only on
the first two panels. You could also write this example as the following code shows:
<mx:Parallel id="t1" targets="{[p1,p2]}">
<mx:Move duration="400"/>
In this example, the two Blur filters explicitly define the properties of the effect.
2. If the effect does not explicitly define the start values of the effect, Flex determines them
from the current settings of the target component, as defined by the current view state.
In the example in rule 1, notice that the Move and Resize effects do not define start values.
Therefore, Flex determines them from the current size and position of the effect targets in
the current view state.
3. If the effect does not explicitly define the end values of the effect, Flex determines them
from the settings of the target component in the destination view state.
In the example in rule 1, the Move and Resize effects determine the end values from the
size and position of the effect targets in the destination view state. In some cases, the
destination view state explicitly defines these values. If the destination view state does not
define the values, Flex determines them from the settings of the base view state.
4. If there are no explicit values, and Flex cannot determine values from the current or
destination view states, the effect uses its default property values.
<!-- Define the two view states, in addition to the base state.-->
<mx:states>
<mx:State name="One">
<mx:SetProperty target="{p1}" name="x" value="110"/>
<mx:SetProperty target="{p1}" name="y" value="0"/>
<mx:SetProperty target="{p1}" name="width" value="200"/>
<mx:SetProperty target="{p1}" name="height" value="210"/>
<mx:SetProperty target="{p2}" name="x" value="0"/>
<mx:SetProperty target="{p2}" name="y" value="0"/>
<mx:SetProperty target="{p2}" name="width" value="100"/>
<mx:SetProperty target="{p2}" name="height" value="100"/>
<mx:SetProperty target="{p3}" name="x" value="0"/>
<mx:SetProperty target="{p3}" name="y" value="110"/>
<mx:SetProperty target="{p3}" name="width" value="100"/>
<mx:SetProperty target="{p3}" name="height" value="100"/>
</mx:State>
<mx:State name="Two">
<mx:SetProperty target="{p2}" name="x" value="110"/>
<mx:SetProperty target="{p2}" name="y" value="0"/>
<mx:SetProperty target="{p2}" name="width" value="200"/>
<mx:SetProperty target="{p2}" name="height" value="210"/>
<mx:SetProperty target="{p3}" name="x" value="0"/>
<mx:SetProperty target="{p3}" name="y" value="110"/>
<mx:SetProperty target="{p3}" name="width" value="100"/>
<mx:SetProperty target="{p3}" name="height" value="100"/>
</mx:State>
</mx:states>
<!-- Define the single transition for all view state changes.-->
<mx:transitions>
<mx:Transition fromState="*" toState="*">
<mx:Sequence id="t1" targets="{[p1,p2,p3]}">
<mx:Blur duration="100" blurXFrom="0.0" blurXTo="10.0"
blurYFrom="0.0" blurYTo="10.0"/>
<mx:Parallel>
<mx:Move duration="400"/>
<mx:Resize duration="400"/>
</mx:Parallel>
<mx:Blur duration="100" blurXFrom="10.0" blurXTo="0.0"
blurYFrom="10.0" blurYTo="0.0"/>
</mx:Sequence>
</mx:Transition>
<!-- Define the Canvas container holding the three Panel containers.-->
<mx:Canvas id="pm" width="100%" height="100%" >
<mx:Panel id="p1" title="One"
x="0" y="0" width="100" height="100"
click="currentState='One'" >
<mx:Label fontSize="24" text="One"/>
</mx:Panel>
To move from the base view state to the OneOnly view state, you create the following view
state definition:
<mx:states>
<mx:State name="OneOnly">
<mx:SetProperty target="{p2}" name="visible" value="false"/>
<mx:SetProperty target="{p2}"
name="includeInLayout" value="false"/>
</mx:State>
</mx:states>
You set the value of the visible and includeInLayout properties to false so that Flex
makes the second Panel container invisible and ignores it when laying out the application. If
the visible property is false, and the includeInLayout property is true, the container is
invisible, but Flex lays out the application as if the component were visible.
A view state defines how to change states, and the transition defines the order in which the
visual changes occur. In the example shown in the previous image, you play an Iris effect on
the second panel when it disappears, and when it reappears on a transition back to the base
state.
For the change from the base state to the OneOnly state, you define the toOneOnly transition
which uses the Iris effect to make the second panel disappear, and then sets the panel’s
visible and includeInLayout properties to false. For a transition back to the base state,
you define the toAnyFromAny transition that makes the second panel visible by setting its
visible and includeInLayout properties to true, and then uses the Iris effect to make the
panel appear, as the following example shows:
<mx:transitions>
<mx:Transition id="toOneOnly" fromState="*" toState="OneOnly">
In the toOneOnly transition, if you hide the target by setting its visible property to false,
and then play the Iris effect, you would not see the Iris effect play because the target is already
invisible.
To control the order of view state changes during a transition, Flex defines several action
effects. The previous example uses the SetPropertyAction action effect to control when to set
the visible and includeInLayout properties in the transition. The following table describes
the action effects:
When you create a view state, you use the SetProperty, SetStyle, AddChild, and RemoveChild
classes to define the view state. To control when a change defined by the view state property
occurs in a transition, you use the corresponding action effect. The action effects give you
control over the order of the state change.
In the previous example, you used the following statement to define an action effect to occur
when the value of the visible property of a component changes:
<mx:SetPropertyAction name="visible"/>
This action effect plays when the value of the visible property changes to either true or
false. You can further control the effect using the value property of the
<mx:SetPropertyAction> tag, as the following example shows:
<mx:SetPropertyAction name="visible" value="true"/>
Filtering effects
By default, Flex applies all of the effects defined in a transition to all of the target components
of the transition. Therefore, in the following example, Flex applies the Move and Resize
effects to all three targets:
<mx:Transition fromState="*" toState="*">
<!-- Define a Parallel effect as the top most effect.-->
<mx:Parallel id="t1" targets="{[p1,p2,p3]}">
<!-- Define a Move and Resize effect.-->
<mx:Move duration="400"/>
<mx:Resize duration="400"/>
</mx:Parallel>
</mx:Transition>
However, you might want to conditionalize an effect so that it does not apply to all target
components, but only to a subset of the components. For example, you define an application
with three view states, as the following image shows:
Each change of view state removes the top panel, moves the bottom panel to the top, and adds
the next panel to the bottom of the screen. In this example, the third panel is invisible in the
base view state.
For this example, you define a single transition that applies a WipeUp effect to the top panel
as it is removed, applies a Move effect to the bottom panel as it moves to the top position, and
applies another WipeUp effect to the panel being added to the bottom, as the following
example shows:
<mx:transitions>
<mx:Transition fromState="*" toState="*">
The sequence1 Sequence effect uses the filter property to specify the change that a
component must go through in order for the effect to play on it. In this example, the
sequence1 effect specifies a value of "hide" for the filter property. Therefore, the WipeUp
and SetPropertyAction effects only play on those components that change from visible to
invisible by setting their visible property to false.
In the sequence2 Sequence effect, you set the filter property to show. Therefore, the
WipeUp and SetPropertyAction effects only play on those components whose state changes
from invisible to visible by setting their visible property to true.
The Move effect also specifies a filter property with a value of move. Therefore, it applies to
all target components that are changing position.
The following table describes the possible values of the filter property:
Value Description
add Specifies to play the effect on all children added during the change of view state.
hide Specifies to play the effect on all children whose visible property changes from
true to false during the change of view state.
move Specifies to play the effect on all children whose x or y properties change during the
change of view state.
remove Specifies to play the effect on all children removed during the change of view state.
resize Specifies to play the effect on all children whose width or height properties change
during the change of view state.
show Specifies to play the effect on all children whose visible property changes from
false to true during the change of view state.
Property Description
filterProperties An Array of Strings specifying component properties. If any of the
properties in the Array have changed on the target component, play the
effect on the target.
filterStyles An Array of Strings specifying style properties. If any of the style
properties in the Array have changed on the target component, play the
effect on the target.
filterFunction A property containing a reference to a callback function that defines
custom filter logic. Flex calls this method on every target of the effect. If
the function returns true, the effect plays on the target; if it returns false,
the target is skipped by that effect.
The callback function specified by the filterFunction property has the following signature:
filterFunc(propChanges:Array, instanceTarget:Object):Boolean
{
// Return true to play the effect on instanceTarget,
// or false to not play the effect.
}
<mx:states>
<mx:State name="One">
<mx:SetProperty target="{p1}" name="x" value="110"/>
<mx:SetProperty target="{p1}" name="y" value="0"/>
<mx:SetProperty target="{p1}" name="width" value="500"/>
<mx:SetProperty target="{p1}" name="height" value="210"/>
<mx:SetProperty target="{p2}" name="x" value="0"/>
<mx:SetProperty target="{p2}" name="y" value="0"/>
<mx:SetProperty target="{p2}" name="width" value="100"/>
<mx:SetProperty target="{p2}" name="height" value="100"/>
<mx:SetProperty target="{p3}" name="x" value="0"/>
<mx:SetProperty target="{p3}" name="y" value="110"/>
<mx:SetProperty target="{p3}" name="width" value="100"/>
<mx:SetProperty target="{p3}" name="height" value="100"/>
</mx:State>
<mx:State name="Two">
<mx:SetProperty target="{p2}" name="x" value="110"/>
<mx:SetProperty target="{p2}" name="y" value="0"/>
<mx:SetProperty target="{p2}" name="width" value="500"/>
<mx:SetProperty target="{p2}" name="height" value="210"/>
<mx:SetProperty target="{p3}" name="x" value="0"/>
<mx:SetProperty target="{p3}" name="y" value="110"/>
<mx:SetProperty target="{p3}" name="width" value="100"/>
<mx:SetProperty target="{p3}" name="height" value="100"/>
</mx:State>
</mx:states>
<mx:transitions>
<mx:Transition fromState="*" toState="*">
<mx:Sequence id="t1" targets="{[p1,p2,p3]}">
<mx:Blur id="myBlur" duration="100" blurXFrom="0.0"
blurXTo="10.0" blurYFrom="0.0" blurYTo="10.0">
<!-- Define the custom filter. -->
<mx:customFilter>
<mx:EffectTargetFilter
filterProperties="['width','x']"/>
</mx:customFilter>
</mx:Blur>
<mx:Parallel>
<mx:Move duration="400"/>
<mx:Resize duration="400"/>
</mx:Parallel>
<mx:Script>
<![CDATA[
import mx.effects.EffectTargetFilter;
myBlur.customFilter=myBlurFilter;
myUnBlur.customFilter=myBlurFilter;
}
]]>
</mx:Script>
<mx:transitions>
<mx:Transition fromState="*" toState="*">
<mx:Sequence id="t1" targets="{[p1,p2,p3]}">
<mx:Blur id="myBlur"/>
<mx:Parallel>
<mx:Move duration="400"/>
<mx:Resize duration="400"/>
</mx:Parallel>
<mx:Blur id="myUnBlur"/>
</mx:Sequence>
</mx:Transition>
</mx:transitions>
...
</mx:Application>
<mx:Script>
<![CDATA[
import mx.effects.EffectTargetFilter;
import flash.events.Event;
myBlurFilter.filterFunction=filterFunc;
myBlur.customFilter=myBlurFilter;
myUnBlur.customFilter=myBlurFilter;
}
]]>
</mx:Script>
<mx:transitions>
<mx:Transition fromState="*" toState="*">
<mx:Sequence id="t1" targets="{[p1,p2,p3]}">
<mx:Blur id="myBlur"/>
<mx:Parallel>
<mx:Move duration="400"/>
<mx:Resize duration="400"/>
</mx:Parallel>
<mx:Blur id="myUnBlur"/>
</mx:Sequence>
</mx:Transition>
</mx:transitions>
...
</mx:Application>
Property Description
target A target component of the effect. The end and start properties of the
PropertyChanges class define how the target component is modified by the
change to the view state.
start An Object that contains the starting properties of the target component, as
defined by the current view state. For example, for a target component that is
both moved and resized by a change to the view state, the start property
contains the starting position and size of the component, as the following
example shows:
{x:00, y:00, width:100, height:100}
end An Object that contains the ending properties of the target component, as
defined by the destination view state. For example, for a target component that is
both moved and resized by a change to the view state, the end property contains
the ending position and size of the component, as the following example shows:
{x:100, y:100, width:200, height:200}
Within the custom filter function, you first search the propChanges Array for the
PropertyChanges object that matches the instanceTarget argument by comparing the
instanceTarget argument to the propChanges.target property.
The following filter function examines the propChanges Array to determine if it should play
the effect on the instanceTarget. In this example, the filter function returns true only for
those components being moved to a position where the x property equals 110, as the
following example shows:
// This function returns true for a target moving to x=110.
public function filterFunc(propChanges:Array,
instanceTarget:Object):Boolean {
<mx:Script>
<![CDATA[
import mx.effects.EffectTargetFilter;
import flash.events.Event;
return false;
}
myBlurFilter.filterFunction=filterFunc;
myBlur.customFilter=myBlurFilter;
<mx:states>
<mx:State name="One">
<mx:SetProperty target="{p1}" name="x" value="110"/>
<mx:SetProperty target="{p1}" name="y" value="0"/>
<mx:SetProperty target="{p1}" name="width" value="500"/>
<mx:SetProperty target="{p1}" name="height" value="210"/>
<mx:SetProperty target="{p2}" name="x" value="0"/>
<mx:SetProperty target="{p2}" name="y" value="0"/>
<mx:SetProperty target="{p2}" name="width" value="100"/>
<mx:SetProperty target="{p2}" name="height" value="100"/>
<mx:SetProperty target="{p3}" name="x" value="0"/>
<mx:SetProperty target="{p3}" name="y" value="110"/>
<mx:SetProperty target="{p3}" name="width" value="100"/>
<mx:SetProperty target="{p3}" name="height" value="100"/>
</mx:State>
<mx:State name="Two">
<mx:SetProperty target="{p2}" name="x" value="110"/>
<mx:SetProperty target="{p2}" name="y" value="0"/>
<mx:SetProperty target="{p2}" name="width" value="500"/>
<mx:SetProperty target="{p2}" name="height" value="210"/>
<mx:SetProperty target="{p3}" name="x" value="0"/>
<mx:SetProperty target="{p3}" name="y" value="110"/>
<mx:SetProperty target="{p3}" name="width" value="100"/>
<mx:SetProperty target="{p3}" name="height" value="100"/>
</mx:State>
</mx:states>
<mx:transitions>
<mx:Transition fromState="*" toState="*">
<mx:Sequence id="t1" targets="{[p1,p2,p3]}">
<mx:Blur id="myBlur" duration="100" blurXFrom="0.0"
blurXTo="10.0" blurYFrom="0.0" blurYTo="10.0"/>
<mx:Parallel>
<mx:Move duration="400"/>
<mx:Resize duration="400"/>
</mx:Parallel>
<mx:Blur id="myUnBlur" duration="100" blurXFrom="10.0"
blurXTo="0.0" blurYFrom="10.0" blurYTo="0.0"/>
</mx:Sequence>
</mx:Transition>
</mx:transitions>
Tips
Determine the type of transition you are defining:
■ With dynamic transitions, you know what effects you want to play, but not which targets
they will play on.
■ With explicit transitions, you know exactly what happens to each individual target.
Complex transitions may consist of both dynamic and explicit elements.
Tips for dynamic transitions
List all possible targets in the parent composite effect.
By default, all effects play on all specified targets. Use filtering with dynamic transitions to
limit the target set.
Dynamic transitions can be used with a wide variety of state changes.
Tips for explicit transitions
Specify targets on the child effects, or on a composite effect when all child effects of the
composite effect have the same targets.
By default, all effects play on all specified targets. For explicit transitions, make sure the targets
are correctly set.
Troubleshooting
Troubleshooting a transition effect that does not play
Is the effect target being hidden or removed? If so, make sure you add an <mx:RemoveChild>
property to the view state definition, or an <mx:SetPropertyAction name="visible"> tag
in the transition definition.
Does the change to the view state define settings that pertain to the transition effect? For
example, if you have a Resize effect, you must change the width or height property of the
target when the view state changes to trigger the effect.
Check that you specified the correct targets to the transition.
Check that your filter settings on the effect and on any parent effect are not excluding the
target.
Troubleshooting an effect playing on too many targets
Add a filter for a dynamic transition, or change the targets for an explicit transition.
Troubleshooting wrong effect parameters
Did you specify explicit parameters on the effect? Are they correct?
Ensure that you correctly set the showTarget property for mask effects such as the Iris effect,
and the wipe effects.
Troubleshooting a flickering or flashing target
Ensure that you correctly set the showTarget property for mask effects such as the Iris effect,
and the wipe effects.
Is the effect target being hidden or removed? If so, make sure you add an <mx:RemoveChild>
property to the view state definition to remove the target, or an <mx:SetPropertyAction
name="visible"> tag in the transition definition to hide the target.
Troubleshooting when an application does not look correct after a transitions
Some effects leave the target with changed properties. For example, a Fade effect leaves the
alpha property of the target at the alphaTo value specified to the effect. If you use the Fade
effect on a target that sets alpha property to zero, you must set the alpha property to a
nonzero value before the object appears again.
Try removing one effect at a time from the transition until it no longer leaves your application
with the incorrect appearance.
CHAPTER 31
Contents
About drag and drop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1195
Using drag-and-drop with list-based controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1197
Manually adding drag-and-drop support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1204
Drag and drop examples. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1217
Moving and copying data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1227
1195
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Initiation A user initiates a drag-and-drop operation by using the mouse to select a Flex
component, or an item in a Flex component, and then moving the component or item while
holding down the mouse button. For example, a user selects an item in a List control with the
mouse and, while holding down the mouse button, moves the mouse several pixels. The
selected component, the List control in this example, is the drag initiator.
Dragging While still holding down the mouse button, the user moves the mouse around
the Flex application. Flex displays an image during the drag, called the drag proxy. A drag
source object (an object of type DragSource) contains the data being dragged.
Dropping When the user moves the drag proxy over another Flex component, that
component becomes a possible drop target. The drop target inspects the drag source object to
determine whether the data is in a format that the target accepts and, if so, allows the user
drop the data onto it. If the drop target determines that the data is not in an acceptable
format, the drop target disallows the drop.
A drag-and-drop operation either copies or moves data from the drag initiator to the drop
target. Upon a successful drop, Flex adds the data to the drop target and, optionally, deletes it
from the drag initiator in the case of a move.
The following figure shows one List control functioning as the drag initiator and a second List
control functioning as the drop target. In this example, you use drag and drop to move the
’Television’ list item from the drag initiator to the drop target:
Television
(drag proxy)
Reading Television
Television
Movies
A single Flex component can function as both the drag initiator and the drop target. This lets
you move the data within the component. The following example shows a List control
functioning as both the drag initiator and the drop target:
List control
(drag initiator and drop target)
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
<mx:HBox>
<mx:VBox>
<mx:Label text="Available Activities"/>
<mx:List id="srclist"
allowMultipleSelection="true"
dragEnabled="true"
dragMoveEnabled="true"/>
</mx:VBox>
<mx:VBox>
<mx:Label text="Activities I Like"/>
<mx:List id="destlist"
dropEnabled="true"/>
</mx:VBox>
</mx:HBox>
</mx:Application>
By setting the dragEnabled property to true on the first List and the dropEnabled property
to true on the second List control, you enabled users to drag items from the first list to the
second without worrying about any of the underlying event processing.
For all list classes except the Tree control, the default value of the dragMoveEnabled property
is false, so you can only copy elements from one control to the other. By setting the
dragMoveEnabled to true in the first List control, you can move and copy data. For the Tree
control, the default value of the dragMoveEnabled property is true.
When the dragMoveEnabled property is set to true, the default drag-and-drop action is to
move the drag data. To perform a copy, hold down the Control key during the drag-and-drop
operation.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
<mx:HBox>
<mx:VBox>
<mx:Label text="Available Albums"/>
<mx:DataGrid id="srcgrid"
allowMultipleSelection="true"
dragEnabled="true"
dropEnabled="true"
dragMoveEnabled="true">
<mx:columns>
<mx:DataGridColumn dataField="Artist"/>
<mx:DataGridColumn dataField="Album"/>
<mx:DataGridColumn dataField="Price"/>
</mx:columns>
</mx:DataGrid>
</mx:VBox>
<mx:VBox>
<mx:Label text="Buy These Albums"/>
<mx:DataGrid id="destgrid"
allowMultipleSelection="true"
dragEnabled="true"
<mx:Script>
<![CDATA[
// Initialize the data provider for the Tree.
private function initApp():void {
firstList.dataProvider = treeDP;
}
]]>
</mx:Script>
<mx:XML id="treeDP">
<node label="Mail">
<node label="Inbox"/>
<node label="Personal Folder">
<node label="Demo"/>
<node label="Personal"/>
<node label="Saved Mail"/>
<node label="bar"/>
</node>
<node label="Calendar"/>
<node label="Sent"/>
<node label="Trash"/>
</node>
</mx:XML>
<mx:Tree id="firstList"
showRoot="false"
labelField="@label"
dragEnabled="true"
dropEnabled="true"
allowMultipleSelection="true"
creationComplete="initApp();"/>
</mx:Application>
Property/ Description
Method
dropIndicatorSkin Specifies the name of the skin to use for the drop-insert indicator which
shows where the dragged data will be inserted.
The default value is ListDropIndicator.
dragEnabled A Boolean value that specifies whether the control is a drag initiator. The
default value is false. When true, users can drag selected items from
the control. When a user drags items from the control, Flex creates a
DragSource object that contains the following data objects:
• A copy of the selected item or items in the control.
For all controls except for Tree, the format string is "items" and the
items implement the IDataProvider interface.
For Tree controls the format string is "treeItems" and the items
implement the ITreeDataProvider API interface.
• A copy of the initiator, with a format String of "source".
dropEnabled A Boolean value that specifies whether the control can be a drop target
that uses default values for handling items dropped onto it. The default
value is false, which means that you must write event handlers for the
drag events. When the value is true, you can drop items onto the control
by using the default drop behavior.
When you set dropEnabled to true, Flex automatically calls the
showDropFeedback() and hideDropFeedback() methods to display the
drop indicator.
dragMoveEnabled If the value is true, and the dragEnabled property is true, specifies that
you can move or copy items from the drag initiator to the drop target.
When you move an item, the item is deleted from the drag initiator when
you add it to the drop target.
If the value is false, you can only copy an item to the drop target. For a
copy, the item in the drag initiator is not affected by the drop.
When the dragMoveEnabled property is true, you must hold down the
Control key during the drop operation to perform a copy.
The default value is false for all list controls except the Tree control, and
true for the Tree control.
calculateDropIndex Returns the item index in the drop target where the item will be dropped.
Used by the dragDrop event handler to add the items in the correct
location.
Not available in the TileList or HorizontalList controls.
showDropFeedback() Specifies to display the focus rectangle around the target control and
positions the drop indicator where the drop operation should occur. If
the control has active scroll bars, hovering the mouse pointer over the
control’s top or bottom scrolls the contents.
You typically call this method from within the handler for the dragOver
event.
Class Function
DragManager Manages the drag-and-drop operations; for example, its doDrag() method
starts the drag operation.
DragSource Contains the data being dragged. It also provides additional drag
management features, such as the ability to add a handler that is called when
data is requested.
When adding drag-and-drop support to a component, you must implement an event handler
for either the mouseDown or mouseMove event, and optionally for the dragComplete event.
When you set the dragEnabled property to true for a list-based control, Flex automatically
adds event handlers for the dragStart and dragComplete events.
N OTE
Do not add an event handler for the dragStart event. That is an internal event handled by
Flex.
You can define your own drag proxy image. For more information, see “Example:
Specifying the drag proxy” on page 1220.
N OTE
Releasing the mouse button when the drag proxy is not over a target ends the drag-
and-drop operation. Flex generates a DragComplete event on the drag initiator, and the
DragManager.getFeedback() method returns DragManager.NONE.
3. If the user moves the drag proxy over a Flex component, Flex dispatches a dragEnter event
for the component.
List-based components with dropEnabled=true Flex checks to see if the component
can be a drop target.
Nonlist-based components, or list-based components with dropEnabled=false The
component must define an event handler for the dragEnter event to be a drop target.
The dragEnter event handler can examine the DragSource object to determine whether
the data being dragged is in an accepted format. To accept the drop, the event handler
calls the DragManager.acceptDragDrop() method. You must call the
DragManager.acceptDragDrop() method for the drop target to receive the dragOver,
dragExit, and dragDrop events.
■ If the drop target does not accept the drop, the drop target component’s parent chain
is examined to determine if any component in the chain accepts the drop data.
■ If the drop target or a parent component accepts the drop, Flex dispatches the
dragOver event as the user moves the proxy over the target.
4. (Optional) The drop target can handle the dragOver event. For example, the drop target
can use this event handler to set the focus on itself.
5. (Optional) If the user decides not to drop the data onto the drop target and moves the drag
proxy outside of the drop target without releasing the mouse button, Flex dispatches a
dragExit event for the drop target. The drop target can optionally handle this event; for
example, to undo any actions made in the dragOver event handler.
6. If the user releases the mouse while over the drop target, Flex dispatches a dragDrop event
on the drop target.
List-based components with dropEnabled=true Flex automatically adds the drag data
to the drop target. If this is a copy operation, you have to implement the event handler for
the dragDrop event for a list-based control. For more information, see “Example:
Copying data from one List control to another List control” on page 1228.
<mx:Script>
<![CDATA[
import mx.core.DragSource;
import mx.managers.DragManager;
import mx.events.*;
import mx.containers.Canvas;
// Called when the user moves the drag proxy onto the drop target.
private function dragEnterHandler(event:DragEvent):void {
// Called if the target accepts the dragged object and the user
// releases the mouse button while over the Canvas container.
private function dragDropHandler(event:DragEvent):void {
<!-- A horizontal box with red and green canvases the user can drag -->
<mx:HBox>
<mx:Canvas
width="30" height="30"
backgroundColor="red"
borderStyle="solid"
mouseMove="mouseMoveHandler(event);"/>
<mx:Canvas
width="30" height="30"
backgroundColor="green"
borderStyle="solid"
mouseMove="mouseMoveHandler(event);"/>
</mx:HBox>
The format argument is a text string such as "color", "list data", or "employee
record". In the event handler for the dragEnter event, the drop target examines this
string to determine whether the data format matches the type of data that the drop target
accepts. If the format matches, the drop target lets users drop the data on the target; if the
format does not match, the target does not enable the drop operation.
One example of using the format string is when you have multiple components in your
application that function as drop targets. Each drop target examines the DragSource
object during its dragEnter event to determine if the drop target supports that format.
For more information, see “Handling the dragEnter event” on page 1213.
N OTE
The list controls have predefined values for format argument. For all list controls
other than the Tree control, the format String is "items". For the Tree control, the
format String is "treeItems". For more information, see “Using drag-and-drop with
list-based controls” on page 1197.
If you drag large or complex data items, consider creating a handler to copy the data, and
specify it by calling the DragSource.addListener() method instead of using the
DragSource.addData() method. If you do this, the data does not get copied until the
user drops it, which avoids the processing overhead of copying the data if a user starts
dragging data but never drops it. The implementation of the list-based classes use this
technique.
2. Call the DragManager.doDrag() method to start the drag-and-drop operation.
The doDrag() method has the following signature:
doDrag(
dragInitiator:IUIComponent,
dragSource:DragSource,
mouseEvent:MouseEvent,
dragImage:IFlexDisplayObject = null,
xOffset:Number = 0, yOffset:Number = 0,
imageAlpha:Number = 0.5,
allowMove:Boolean = true):void
If you call Event.preventDefault() in the event handler for the dragComplete or dragDrop
event for a Tree control when dragging data from one Tree control to another, it prevents
the drop.
<mx:Script>
<![CDATA[
import mx.events.DragEvent;
import mx.controls.Alert;
import mx.collections.ArrayCollection;
Alert.show(artistList);
}
]]>
</mx:Script>
<mx:HBox>
<mx:VBox>
<mx:VBox>
<mx:Label text="Buy These Albums"/>
<mx:DataGrid id="destgrid"
allowMultipleSelection="true"
dragEnabled="true"
dropEnabled="true"
dragMoveEnabled="true"
dragDrop="dragDropHandler(event);">
<mx:columns>
<mx:DataGridColumn dataField="Artist" />
<mx:DataGridColumn dataField="Album" />
<mx:DataGridColumn dataField="Price" />
</mx:columns>
</mx:DataGrid>
</mx:VBox>
</mx:HBox>
</mx:Application>
Notice that the dataForFormat() method specifies an argument value of "items". This is
because the list-based controls have predefined values for the data format of drag data. For all
list controls other than the Tree control, the format String is "items". For the Tree control, the
format String is "treeItems".
Notice also that the return value of the dataForFormat() method is an Array. The
dataForFormat() method always returns an Array for a list-based control, even if you are
only dragging a single item, because list-based controls let you select multiple items.
<mx:Script>
<![CDATA[
//Import classes so you don't have to use full names.
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.events.DragEvent;
import flash.events.MouseEvent;
Argument Description
dragImage The image that specifies the drag proxy.
To specify a symbol, such as a JPEG image of a product that a user wants to
order, use a string that specifies the symbol’s name, such as myImage.jpg.
To specify a component, such as a Flex container or control, create an instance
of the control or container, configure and size it, and then pass it as an
argument to the doDrag() method.
xOffset Number that specifies the x offset, in pixels, for the dragImage. This argument is
optional. If omitted, the drag proxy is shown at the upper-left corner of the drag
initiator. The offset is expressed in pixels from the left edge of the drag proxy to
the left edge of the drag initiator, and is usually a negative number.
yOffset Number that specifies the y offset, in pixels, for the dragImage. This argument is
optional. If omitted, the drag proxy is shown at the upper-left corner of the drag
initiator. The offset is expressed in pixels from the top edge of the drag proxy to
the top edge of the drag initiator, and is usually a negative number.
imageAlpha A Number that specifies the alpha value used for the drag proxy image. If
omitted, Flex uses an alpha value of 0.5. A value of 0 corresponds to
transparent and a value of 1.0 corresponds to fully opaque.
<mx:Script>
<![CDATA[
//Import classes so you don't have to use full names.
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.events.DragEvent;
import flash.events.MouseEvent;
DragManager.NONE A red circle with a white x appears indicating that a drop is prohibited.
This is the same image that appears when the user drags over an object
that is not a drag target.
You typically show the feedback indicator based on the keys pressed by the user during the
drag-and-drop operation. The DragEvent object for the dragOver event contains Boolean
properties that indicate whether the Control or Shift keys are pressed at the time of the event:
ctrlKey and shiftKey, respectively. No key pressed indicates a move, the Control key
indicates a copy, and the Shift key indicates a link. You then call the showFeedback() method
as appropriate for the key pressed.
Another use of the showFeedback() method is that it determines the value of the action
property of the DragEvent object for the dragDrop, dragExit, and dragComplete events. If
you do not call the showFeedback() method in the dragOver event handler, the action
property of the DragEvent is always set to DragManager.MOVE.
The dragExit event is dispatched when the user drags the drag proxy off the drop target, but
does not drop the data onto the target. You can use this event to restore any visual changes
that you made to the drop target in the dragOver event handler.
In the following example, you set the dropEnabled property of a List control to true to
configure it as a drop target and to use the default event handlers. However, you want to
provide your own visual feedback, so you also define event handlers for the dragEnter,
dragExit, and dragDrop events. The dragOver event handler completely overrides the
default event handler, so you call the Event.preventDefault() method to prohibit the
default event handler from execution.
<mx:Script>
<![CDATA[
import mx.managers.DragManager;
import mx.events.DragEvent;
import mx.collections.ArrayCollection;
if (event.dragSource.hasFormat("items"))
{
// Set the border to green to indicate that
// this is a drop target.
// Since the dragOver event is dispatched continuosly
<mx:HBox id="myHB">
<mx:List id="firstList"
dragEnabled="true"/>
<mx:List id="secondList"
borderThickness="2"
dropEnabled="true"
dragMoveEnabled="true"
dragOver="dragOverHandler(event);"
dragDrop="dragExitHandler(event);"
You call Event.preventDefault() because the drop target is a List control, one of the list-
based controls that defines a default dragDrop handler. In the case of a copy, you want to
explicitly handle the dragDrop event, but use all the other default event handlers. For a
nonlist-based component, you do not have to call Event.preventDefault() because only
list-based controls define default drag-and-drop event handlers.
The default value of the dragMoveEnabled property is false, so that you can only copy
elements from one List control to the other. If you modify the example to set
dragMoveEnabled to true in the drag initiator, you can move and copy elements. To copy a
list element, hold down the Control key during the drag-and-drop operation:
<?xml version="1.0"?>
<!-- dragdrop\DandDListToListCopy.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp();">
<mx:Script>
<![CDATA[
import mx.events.DragEvent;
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.collections.IList;
import mx.collections.ArrayCollection;
<mx:HBox>
<mx:List id="firstList"
dragEnabled="true"/>
<mx:List id="secondList"
dropEnabled="true"
dragDrop="dragDropHandler(event);"/>
</mx:HBox>
</mx:Application>
To perform the copy, the event handler creates a new Object, then copies the individual data
fields of the drag data into the new Object. Then, the event handler adds the new Object to
the drop target’s data provider.
Unlike the example in the section “Example: Moving and a copying data for a nonlist-based
control” on page 1232, you do not have to write the dragOver or dragComplete event
handlers. While Flex cannot perform the copy, Flex does recognize when you perform a copy
or a move, and automatically removes the data from the drag initiator for you on a move.
<mx:Script>
<![CDATA[
import mx.events.DragEvent;
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.collections.IList;
import mx.collections.ArrayCollection;
var itemsArray:Array =
event.dragSource.dataForFormat('items') as Array;
var tempItem:Object =
{ label: itemsArray[0].label,
IList(dropTarget.dataProvider).addItemAt(tempItem, dropLoc);
}
}
]]>
</mx:Script>
<mx:HBox>
<mx:List id="srcList"
dragEnabled="true"
dragMoveEnabled="true"/>
<mx:DataGrid id="destDG"
dropEnabled="true"
dragDrop="dragDropHandler(event);">
<mx:columns>
<mx:DataGridColumn dataField="label"/>
<mx:DataGridColumn dataField="data"/>
<mx:DataGridColumn dataField="date"/>
</mx:columns>
</mx:DataGrid>
</mx:HBox>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.events.DragEvent;
import flash.events.MouseEvent;
DragManager.showFeedback(DragManager.NONE);
}
if (event.action == DragManager.MOVE)
dragInitCanvas.removeChild(draggedImage);
}
]]>
<!-- Canvas holding the Image control that is the drag initiator. -->
<mx:Canvas
width="250" height="500"
borderStyle="solid"
backgroundColor="#DDDDDD">
<!-- The Image control is the drag initiator and the drag proxy. -->
<mx:Image id="myimg"
source="@Embed(source='assets/globe.jpg')"
mouseMove="mouseOverHandler(event);"
dragComplete="dragCompleteHandler(event);"/>
</mx:Canvas>
CHAPTER 32
Embedding Assets 32
Many Adobe Flex applications use external assets like images, sounds, and fonts. Although
you can reference and load assets at run time, you often compile these assets into your
applications. The process of compiling an asset into your application is called embedding the
asset. Flex lets you embed image files, movie files, MP3 files, and TrueType fonts into your
applications.
This topic contains an overview of the process that you use to embed an image or a SWF file
as an asset into your application. For information on embedding fonts, see Chapter 21,
“Using Fonts,” on page 835.
Contents
About embedding assets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1237
Syntax for embedding assets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1240
Embedding asset types. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1245
1237
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Examples of embedding assets
One of the most common uses of the embed mechanism is to import an image for a Flex
control by using the @Embed() directive in an MXML tag definition. For example, many
controls support icons or skins that you can embed in the application. The Button control lets
you specify label text, as well as an optional icon image, as the following example shows:
<?xml version="1.0"?>
<!-- embed\ButtonIcon.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
[Embed(source="logo.gif")]
[Bindable]
public var imgCls:Class;
]]>
</mx:Script>
<mx:Style>
.myCustomButton {
overSkin:Embed(source="overIconImage.gif");
upSkin:Embed(source="upIconImage.gif");
downSkin:Embed(source="downIconImage.gif");
}
</mx:Style>
The equal sign (=) in the style sheet is a Flex extension that might not be supported by all
CSS processors. If you find that it is not supported, you can use the Embed(filename)
syntax.
Embed parameters
Each form of the embed syntax takes one or more optional parameters. The exact syntax that
you use to embed assets depends on where they are embedded. Some of these parameters are
available regardless of what type of asset you are embedding, and others are specific to a
particular type of media. For example, you can use the source and mimeType parameters with
any type of media, but the scaleGridRight parameter applies only to images.
The following table describes the parameters available for any type of embedded asset. For
more information, see “About the source parameter” on page 1242 and “About the MIME
type” on page 1243.
Parameter Description
source Specifies the name and path of the asset to embed; either an absolute path
or a path relative to the file containing the embed statement. The
embedded asset must be a locally stored asset. Therefore, you cannot
specify a URL for an asset to embed.
For more information on setting the path, see “About setting the path to the
embedded asset” on page 1242.
mimeType Specifies the mime type of the asset.
The following table describes the parameters specific for images and Sprite objects. For more
information, see “Using 9-slice scaling with embedded images” on page 1251.
Parameter Description
scaleGridTop Specifies the distance, in pixels, of the upper dividing line from the top of
the image in a 9-slice scaling formatting system. The distance is relative to
the original, unscaled size of the image.
scaleGridBottom Specifies the distance in pixels of the lower dividing line from the top of the
image in a 9-slice scaling formatting system. The distance is relative to the
original, unscaled size of the image.
The following table describes the parameter that is specific to SWF files. For more
information, see “Embedding SWF files” on page 1249.
Parameter Description
symbol Specifies the symbol in a SWF file to embed, for use with Adobe’s
Macromedia Flash Player 8 and earlier.
In this example, Flex searches the subdirectory named assets in the directory containing the
testEmbed.mxml file. If the image is not found, Flex then searches for the image in the SWC
files associated with the application.
If the path starts with a slash character, Flex first searches the directory of the MXML file for
the asset, and then it searches the source path. You specify the source path to the Flex compiler
by using the source-path compiler option. For example, you set the source-path option as
the following code shows:
-source-path=a1,a2,a3
Flex first searches for the file in a1/assets, then a2/assets, and then a3/assets. If the image is not
found, Flex searches for the image in the SWC files associated with the application.
If the MXML file is in the a2 directory, as in a2/testEmbed.mxml, Flex first searches the a2
directory, and then the directories specified by the source-path option.
<mx:Script>
<![CDATA[
[Embed(source="logo.gif")]
[Bindable]
public var imgCls:Class;
]]>
</mx:Script>
<mx:Image source="{imgCls}"/>
</mx:Application>
Notice that Flex uses data binding to tie the imgCls variable to the source property. If you
omit the [Bindable] metadata tag preceding the imgCls variable definition, Flex can only
perform the data binding operation once, at application startup. When you include the
[Bindable] metadata tag, Flex recognizes any changes to the imgCls variable, and updates
any components that use that variable when a change to it occurs.
Generally, this method of embedding assets provides more flexibility than other methods
because you can import an asset once, and then use it in multiple places in your application,
and because you can update the asset and have the data binding mechanism propagate that
update throughout your application.
</mx:Application>
In this example, you define a class named imgCls that represents the embedded image. When
embedding JPEG, GIF, and PNG files, Flex defines imgCls as a reference to a subclass of the
mx.core.BitmapAsset class, which is a subclass of the flash.display.BitmapData class.
In ActionScript, you can create and manipulate an object that represents the embedded image
before passing it to a control. To do so, you create an object with the type of the embedded
class, manipulate it, and then pass the object to the control, as the following example shows:
<?xml version="1.0"?>
<!-- embed/EmbedAccessClassObject.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.core.BitmapAsset;
[Embed(source="logo.gif")]
[Bindable]
public var imgCls:Class;
<mx:HBox>
<mx:Image id="myImageRaw" source="{imgCls}"/>
<mx:Image id="myImage" creationComplete="modImage();"/>
<mx:Text id="myText" text="foo"/>
</mx:HBox>
</mx:Application>
In this example, you define a class named imgCls that represents the embedded image. When
embedding an SVG image, Flex defines imgCls as a reference to a subclass of the
mx.core.SpriteAsset class, which is a subclass of the flash.display.Sprite class. Therefore, you
can manipulate the image by using the methods and properties of the SpriteAsset class. For an
example that manipulates an imported image, see “Embedding JPEG, GIF, and PNG images”
on page 1245.
<mx:Script>
<![CDATA[
import flash.media.*;
[Embed(source="sample.mp3")]
[Bindable]
public var sndCls:Class;
<mx:HBox>
<mx:Button label="play" click="playSound();"/>
<mx:Button label="stop" click="stopSound();"/>
</mx:HBox>
</mx:Application>
In this example, you define a class named sndCls that represents the embedded MP3 file.
When embedding MP3 files, Flex defines sndCls as a reference to a subclass of the
mx.core.SoundAsset, which is a subclass of the flash.media.Sound class.
Flex can handle any legal filename, including filenames that contain spaces and punctuation
marks. If the MP3 filename includes regular quotation marks, ensure that you use single
quotation marks around the filename.
You do not have to embed the sound file to use it with Flex. You can also use the Sound class
to load a sound file at run time. For more information, see the Sound class in the Adobe Flex
Language Reference.
For example, you use the [Embed] metadata tag in ActionScript to embed a SWF file, as the
following code shows:
[Embed(source="icon.swf")]
[Bindable]
public var imgCls:Class;
In this example, you define a class named imgCls that represents the embedded SWF file. Flex
defines imgCls as a reference to a subclass of the mx.core.MovieClipLoaderAsset class, which
is a subclass of the flash.display.MovieClip class. Therefore, you can manipulate the image by
using the methods and properties of the MovieClipLoaderAsset class.
Flash defines three types of symbols: Button, MovieClip, and Graphic. You can embed
Button and MovieClip symbols in a Flex application, but you cannot embed a Graphic
symbol because it cannot be exported for ActionScript.
This capability is useful when you have a SWF file that contains multiple exported symbols,
but you want to load only some of them into your Flex application. Loading only the symbols
required by your application makes your resulting Flex SWF file smaller than if you imported
the entire SWF file.
In this example, you define a class named imgCls that represents the embedded symbol.
Internally, Flex defines imgCls as a reference to a subclass of either one of the following
classes:
SpriteAsset For single-frame SWF files.
MovieClipLoaderAsset For multiframe SWF files.
When you scale an embedded image that uses 9-slice scaling, all text and gradients are scaled
normally. However, for other types of objects the following rules apply:
■ Content in the center region is scaled normally.
■ Content in the corners is not scaled.
■ Content in the top and bottom regions is scaled only horizontally. Content in the left and
right regions is scaled only vertically.
<mx:Script>
<![CDATA[
[Embed(source="slice_9_grid.gif",
scaleGridTop="25", scaleGridBottom="125",
scaleGridLeft="25", scaleGridRight="125")]
[Bindable]
public var imgCls:Class;
]]>
</mx:Script>
<mx:HBox>
<mx:Image source="{imgCls}"/>
<mx:Image source="{imgCls}" width="300" height="300"/>
<mx:Image source="{imgCls}" width="450" height="450"/>
</mx:HBox>
</mx:Application>
If you had omitted the 9-slice scaling, the scaled image would have appeared exactly like the
unscaled image, as the following image shows:
In this example, you define a class named imgCls that represents the embedded image. If the
image is a SWF file that uses 9-slice scaling, Flex defines imgCls as a subclass of the
mx.core.SpriteAsset class, which is a subclass of the flash.display.Sprite class. Therefore, you
can use all of the methods and properties of the SpriteAsset class to manipulate the object.
CHAPTER 33
Contents
Installing the Adobe Flex Component Kit for Flash CS3 . . . . . . . . . . . . . . . . . . . . . 1255
About importing SWF 9 assets into Flex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1256
Importing static SWF 9 assets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1256
Importing dynamic SWF 9 assets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1258
Using Flash components in a Flex application. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1264
System requirements
Your system must meet the following requirements to install the Flex Component Kit for
Flash CS3:
■ Flex 3
■ Flash CS3 Professional
■ Adobe Extension Manager for Flash CS3. You can download the extension manager from
http://www.adobe.com/exchange/em_download/.
1255
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Installation procedure
The Flex Component Kit for Flash CS3 consists of the FlexIntegration.mxp file.
<mx:Script>
<![CDATA[
// Embed the SWF file and the symbols from the SWF file. -->
[Embed(source="../assets/circlesquare.swf")]
[Bindable]
public var LogoCls:Class;
<!-- Load the SWF file using the Image control. -->
<mx:Image source="{LogoCls}"/>
<!-- Load the SWF file as the icon for a Button control. -->
<mx:Button icon="{LogoCls}" height="100" width="200"/>
<!-- Load the BlueSquare symbol as the icon for a Button control. -->
<mx:Button icon="{LogoClsBlueSquare}" height="100" width="100"/>
<!-- Load the GreenCircle symbol as the icon for a Button control. -->
<mx:Button icon="{LogoClsGreenCircle}" height="100" width="100"/>
UIMovieClip implements the interfaces necessary for a Flash component to be used like any
other Flex component. Therefore, you can use a subclass of UIMovieClip can be used as a
child of a Flex container or as a skin, and it can respond to events, define view states and
transitions, and work with effects in the same way as any Flex component.
When you install the Flex Component Kit for Flash CS3, you also install the
UIMovieClip.swc file. This SWC file contains all of the information necessary to use the
UIMovieClip class in Flash.
For more information on the mx.flash.UIMovieClip class and its interfaces, see Adobe Flex
Language Reference.
Instead of using the Make Flex Component command, you can manually configure a
symbol to be used as a Flex component by making all of the settings described in this
section. However, before you can reference the UIMovieClip class, you must open the
Components pane and drag the UIMovieClip into the Library pane.
<myComps:MyButtonUpSkin/>
<myComps:MyButtonOverSkin/>
<myComps:MyButtonDownSkin/>
<myComps:MyButtonDisabledSkin/>
</mx:Application>
In this example, you use the Flash components to skin the Button control and use the
components as stand-alone Flex components.
// EventBlueSquare.as
import mx.flash.UIMovieClip;
import flash.events.Event;
[Event(name="blueSquareSelected", type="flash.events.Event")]
<mx:Script>
<![CDATA[
<myComps:EventBlueSquare id="myBS"
blueSquareSelected="handleBlueSquareSelected();"/>
<mx:TextArea id="myTA"/>
</mx:Application>
For more information on defining custom events, see Chapter 4, “Creating Custom Events,”
in Creating and Extending Flex Components.
<myComps:EventBlueSquare id="myBS"
toolTip="MXML Tooltip"/>
</mx:Application>
For more information on tool tips, see Chapter 25, “Using ToolTips,” in Flex Developer’s
Guide.
The rectangle surrounding the green oval is the MovieClip that corresponds to the bounding
box. As the green oval rotates, it stays within the area defined by the bounding box, so Flex
does not attempt to resize it.
The UIMovieClip class defines a property named boundingBoxName specifies the bounding
box MovieClip for the Flash component. The default value of the boundingBoxName property
is boundingBox. Therefore, you typically specify boundingBox as the instance name of the
bounding box MovieClip. If you use a different instance name for the MovieClip, ensure that
you set the boundingBoxName property to that name.
The Make Flex Component command sets the visible property to false for the MovieClip
that represents the bounding box so that it does not appear in your Flex application.
Add a bounding box to a Flash component
1. Add a new layer to the symbol definition of your component.
2. Use the Rectangle tool to draw a bounding box rectangle.
3. Set the size of the rectangle.
4. Convert the rectangle to a symbol of type MovieClip.
// Set the number of visble dots at run time based on the size
// Flex passes to the component at runtime.
override public function
setActualSize(newWidth:Number, newHeight:Number):void
{
if (newWidth != _width || newHeight != _height)
{
_width = newWidth;
_height = newHeight;
addChild(dot);
dot.x = col * (SIZE + GAP);
dot.y = row * (SIZE + GAP);
}
}
}
}
}
}
You then use the DotPattern component in a Flex application, as the following example
shows:
<?xml version="1.0"?>
<!-- embedSWF9/EmbedSWF9ViewStates.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
width="100%" height="100%"
xmlns:myComps="*">
Ensure that you add the key frames and frame labels to the symbol definition in Flash,
not to the scene.
The following figure shows a Flash component named StatesGreenOval with three view
states:
.
The green oval includes a bounding box that Flex uses to control the run-time size of the
component. For more information, see “Adding a bounding box to a Flash component”
on page 1268.
In the Flex application, you change the view state of the component by setting its
currentState property to the frame label, as the following example shows:
<?xml version="1.0"?>
<!-- embedSWF9/EmbedSWF9ViewStates.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" height="1500"
xmlns:myComps="*">
<myComps:StatesGreenOval id="myOval"/>
</mx:Application>
Adding transitions
A Flash component can define an animation that plays during a view state change, where the
animation corresponds to a Flex transition. For example, if the change of view state alters the
color, size, or other visual aspect of the component, the transition animates that change.
When you change the view state of the Flash component from BaseState to Ninety, Flex
automatically looks for frame labels that define the beginning and end of the transition and, if
found, plays the associated animation. When you switch back from the view state Ninety to
BaseState, Flex automatically looks for frame labels in the form:
Ninety-BaseState:start
Ninety-BaseState:end
If found, Flex automatically plays the animation. If these labels are not found, Flex plays the
animation for the BaseState to Ninety transition in reverse.
You can use the wildcard symbol, "*", when specifying the frame label, where the wildcard
symbol corresponds to any view state. For example, the frame label BaseState-*:start
specifies a transition from the BaseState view state to any other view state. The frame label
*-BaseState:start specifies a transition from any view state to BaseState.
Flex searches for frame labels that match the view state change in the following order:
■ currentViewState-destinationViewState (no wildcards)
■ currentViewState-destinationViewState (reversed)
■ *-destinationViewState
■ *-destinationViewState (reversed)
■ currentViewState-*
■ currentViewState-* (reversed)
■ *-*
</mx:Application>
CHAPTER 34
Creating Modular
Applications
34
You can create modules that you dynamically load in your Flex applications.
Contents
Modular applications overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1277
Creating modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1280
Compiling modules. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1284
Loading and unloading modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1292
Using ModuleLoader events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1301
Passing data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1310
About modules
Modules are SWF files that can be loaded and unloaded by an application. They cannot be run
independently of an application, but any number of applications can share the modules.
Modules let you split your application into several pieces, or modules. The main application,
or shell, can dynamically load other modules that it requires, when it needs them. It does not
have to load all modules when it starts, nor does it have to load any modules if the user does
not interact with them. When the application no longer needs a module, it can unload the
module to free up memory and resources.
Modular applications have the following benefits:
■ Smaller initial download size of the SWF file.
■ Shorter load time due to smaller SWF file size.
1277
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
■ Better encapsulation of related aspects of an application. For example, a “reporting”
feature can be separated into a module that you can then work on independently.
Benefits of modules
A module is a special type of dynamically-loadable SWF that contains an IFlexModuleFactory
class factory. This allows an application to load code at run time and create class instances
without requiring that the class implementations be linked into the main application.
Modules are similar to Runtime Shared Libraries (RSLs) in that they separate code from an
application into separately loaded SWF files. Modules are much more flexible than RSLs
because modules can be loaded and unloaded at run time and compiled without the
application.
Two common scenarios in which using modules is beneficial are a large application with
different user paths and a portal application.
An example of the first common scenario is an enormous insurance application that includes
thousands of screens, for life insurance, car insurance, health insurance, dental insurance,
travel insurance, and veterinary pet insurance.
Using a traditional approach to rich Internet application (RIA) design, you might build a
monolithic application with a hierarchical tree of MXML classes. Memory use and start-up
time for the application would be significant, and the SWF file size would grow with each
new set of functionality.
When using this application, however, any user accesses only a subset of the screens. By
refactoring the screens into small groups of modules that are loaded on demand, you can
improve the perceived performance of the main application and reduce the memory use. Also,
when the application is separated into modules, developers’ productivity may increase due to
better encapsulation of design. When rebuilding the application, the developers also have to
recompile only the single module instead of the entire application.
An example of the second common scenario is a system with a main portal application,
written in ActionScript 3, that provides services for numerous portlets. Portlets are configured
based on data that is downloaded on a per-user basis. Using the traditional approach, you
might build an application that compiles in all known portlets. This is inefficient, both for
deployment and development.
By using modules, you can establish an interface that contains portal services, and a generic
portlet interface. You can use XML data to determine which modules to load for a given
session. When the module is loaded, you obtain a handle to a class factory inside the module,
and from that you create an instance of a class that implements the portlet interface. In this
scenario, full recompilation is necessary only if the interfaces change.
Application
ConcreteShell
Manager AbstractClient
Module
AbstractFactory AbstractProduct
ConcreteFactory ConcreteProduct
The ModuleManager manages the set of loaded modules, which are treated as a map of
singletons indexed by the module URL. Loading a module triggers a series of events that let
clients monitor the status of the module. Modules are only ever loaded once, but subsequent
reloads also dispatch events so that client code can be simplified and rely on using the READY
event to know that the module’s class factory is available for use.
The ModuleLoader class is a thin layer on top of the ModuleManager API that is intended to
act similarly to the mx.controls.SWFLoader class for modules that only define a single visual
UIComponent. The ModuleLoader class is the easiest class to use when implementing a
module-based architecture, but the ModuleManager provides greater control over the
modules.
Modules are loaded into child domains of the current application domain. You can specify a
different application domain by using the applicationDomain property of the
ModuleLoader class.
4. In the Application file, use an <mx:ModuleLoader> tag to load each of the modules. You
can also load modules by using methods of the mx.modules.ModuleLoader and
mx.modules.ModuleManager classes.
The following sections describes these steps in detail.
Creating modules
Modules are classes just like application files. You can create them in either ActionScript or by
extending a Flex class by using MXML tags. This section describes how to create modules in
MXML and in ActionScript.
</mx:Application>
5. To convert this new application to a module, replace the <mx:Application> tag with the
<mx:Module> tag so that the resulting code looks like the following:
<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
</mx:Module>
By default, whenever you add an MXML application file to your Flex project, it is runnable
and is added to the list of project application files. All files defined as application files must
reside in your project’s source folder. Because modules must be runnable, they must be in your
project’s source folder.
Compiling modules
The way you compile modules is similar to the way you compile Flex applications. On the
command line, you use the mxmlc command-line compiler. In Flex Builder, you create
modules as applications and compile them by either building the project or running the
application.
The result is a SWF file that you load into your application as a module. You cannot run the
module-based SWF file as a stand-alone Flash application or load it into a browser window. It
must be loaded by an application as a module. When you run it in Flex Builder to compile it,
you should close the Player or browser Window and ignore any errors. Modules should not be
requested by the Player or through a browser directly.
For more information on compiling modules on the command line, see “Compiling modules
with the command-line compiler” on page 1285.
For information on compiling modules in Flex Builder, see “Compiling modules with Flex
Builder” on page 1285.
After you compile your module, you try to remove redundancies between the module and the
application that uses it. To do this, you create a link report for the application, and then
externalize any assets in the module that appear in that report. For more information, see
“Reducing module size” on page 1290.
Once you compile a module, you should try to reduce its size by removing dependencies that
overlap with the application that uses the module. For more information, see “Reducing
module size” on page 1290.
Overview
There are two approaches to using modules in Flex Builder projects:
■ Single project — In this approach, you create a single project for your application, and
then add modules to the application list. This approach provides less customization and is
more limiting than creating modules in separate projects. For more information, see
“Using modules in a single project” on page 1285.
■ Multiple projects — In this approach, you create a separate project for each module or a
single project for all the modules. This approach can be appropriate for when you only
have a few modules or need to customize the compilation of your modules. For more
information, see “Using multiple projects” on page 1286.
To add a new module to your project, see “Creating MXML-based modules” on page 1281.
When you run your application, Flex Builder compiles the modules’ SWF files for you. The
SWF files are then loaded into the application at run time. The module SWF files and main
application SWF file are in the same directory.
A related approach is to use a single project for all modules, while keeping the application in
its own separate project. This has some of the drawbacks of using a single project for both the
application and the modules, but has many of the same benefits as using a separate project for
each of the modules.
Using one project for all modules has the following benefits:
■ The module project can be located anywhere in the workspace.
■ You can compile just the modules or just the application, without having to recompile
both at the same time.
Creating projects
When creating a separate project for modules, you change the module project’s output folder
to a directory that is used by the application. You also suppress the generation of wrapper files.
Compiling projects
Compiling multiple projects in Flex Builder is a common operation. First, you choose the
order in which you want the projects to compile and then you compile all projects at the same
time.
If you are using Flex Builder to compile modules, you can use the technique described in this
section if you have a separate project for your modules. In that case, for the main application,
you add the link-report option to the Additional Compiler Arguments field of the Flex
Compiler options. You then use the load-externs option in the same field for each module’s
project to load this report.
The default output location of the link-report option in Flex Builder is the root
directory of the Flex Builder application itself. On Windows, the default directory is
c:\Program Files\Adobe\Flex Builder 2. As a result, if you add the following command to
your compiler options, Flex Builder writes the report.xml file to its root directory:
-link-report=report.xml
If you externalize the module’s dependencies by using the load-externs option, your
module might not be compatible with future versions of Adobe Flex. You might be
required to recompile the module. To ensure that a future Flex application can use a
module, compile that module with all the classes it requires. This also applies to
applications that you load inside other applications.
Debugging modules
To debug the application with modules, you reference the debug SWF file in the source code
during development, and switch to the non-debug file when you are ready to deploy. For
example, when you debug, your calls to the loadModule() method might appear as follows:
loadModule('ChartModule-debug.swf')
When you have finished debugging and want to deploy the application, you then remove
references to the debug SWF files. Your calls to the loadModule() method might appear as
follows:
loadModule('ChartModule.swf')
The technique described in this section also applies to the SWF file names that you pass to the
ModuleLoader’s url property, or any other way you refer to the URL of the module.
<mx:TabNavigator id="tn"
width="100%"
height="100%"
creationPolicy="auto"
>
<mx:VBox id="vb1" label="Column Chart Module">
<mx:Label id="l1" text="ColumnChartModule.swf"/>
<mx:ModuleLoader url="ColumnChartModule.swf"/>
</mx:VBox>
</mx:TabNavigator>
</mx:Panel>
</mx:Application>
<mx:VBox id="vb1"/>
</mx:Application>
MXML-based modules can load other modules. Those modules can load other modules, and
so on.
The following example shows the cross-domain file that resides on the remote server:
<!-- crossdomain.xml file located at the root of the server -->
<cross-domain-policy>
<allow-access-from domain="loaderservername" to-ports="*"/>
</cross-domain-policy>
For more information about using the cross-domain policy file, see Chapter 4, “Applying Flex
Security,” in Building and Deploying Flex Applications.
<mx:Panel
title="Module Example"
height="90%"
width="90%"
paddingTop="10"
paddingLeft="10"
paddingRight="10"
paddingBottom="10"
>
<mx:TabNavigator id="tn"
width="100%"
height="100%"
creationPolicy="auto"
standin = panel;
removeChild(standin);
}
progress.indeterminate=true;
unload.enabled=false;
reload.enabled=false;
}
if (contains(standin))
removeChild(standin);
}
]]>
</mx:Script>
[Bindable]
public var progBar:String = "";
[Bindable]
public var progMessage:String = "";
<mx:ModuleLoader
id="chartModuleLoader"
url="ColumnChartModule.swf"
progress="progressEventHandler(event)"
/>
</mx:Panel>
</mx:Application>
<mx:ProgressBar
id="progress"
width="100%"
source="{this}"
/>
<mx:HBox width="100%">
<mx:Button
id="load"
label="Load"
click="clickHandler()"
/>
<mx:Button
id="unload"
label="Unload"
click="unloadModule()"
/>
<mx:Button
id="reload"
label="Reload"
click="unloadModule();loadModule();"
/>
</mx:HBox>
</mx:ModuleLoader>
</mx:Application>
This example does not change the ProgressBar’s label property for all events. For example, if
you load and then unload the module, the label property remains at "LOADING 100%".
To adjust the label properly, you must define other event handlers for the ModuleLoader
events, such as unload and error.
Passing data
Communication between modules and the parent application, and among modules, is
possible. You can use the following approaches to facilitate inter-module, application-to-
module, and module-to-application communication:
■ ModuleLoader’s child, ModuleManager’s factory, and Application’s
parentApplication properties — You can use these properties to access modules and
applications. However, by using these properties, you might create a tightly-coupled
design that prevents code reuse. In addition, you might also create dependencies among
modules and applications that cause class sizes to be bigger. For more information, see
“Accessing modules from the parent application” on page 1311, “Accessing the parent
application from the modules” on page 1314, and “Accessing modules from other
modules” on page 1316.
■ Query string parameters — Modules are loaded with a URL; you can pass parameters on
this URL and then parse those parameters in the module. For more information, see
“Passing data with the query string” on page 1318.
[Bindable]
public var answer:Number = 0;
<mx:Form>
<mx:FormHeading label="Enter values to sum."/>
<mx:FormItem label="First Number">
<mx:TextInput id="ti1" width="50"/>
</mx:FormItem>
<mx:FormItem label="Second Number">
<mx:TextInput id="ti2" width="50"/>
</mx:FormItem>
<mx:FormItem label="Result">
[Bindable]
private var expenses:ArrayCollection;
</mx:Module>
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500},
{Month:"Feb", Profit:1000, Expenses:200},
{Month:"Mar", Profit:1500, Expenses:500}
]);
]]></mx:Script>
<mx:ModuleLoader url="ChartChildModule.swf" id="m1"/>
</mx:Application>
You can also call methods and access properties on other modules. For more information, see
“Accessing modules from other modules” on page 1316.
The drawbacks to this approach is that it can create dependencies on the parent application
inside the module. In addition, the modules are no longer portable across multiple
applications unless you ensure that you replicate the behavior of the applications.
To avoid these drawbacks, you should use interfaces that secure a contract between the
application and its modules. This contract defines the methods and properties that you can
access. Having an interface lets you reuse the application and modules as long as you keep the
interface updated. For more information, see “Using interfaces for module communication”
on page 1321.
]]></mx:Script>
<mx:ModuleLoader url="InterModule1.swf" id="m1"/>
<mx:ModuleLoader url="InterModule2.swf" id="m2"/>
</mx:Application>
Module 1:
<?xml version="1.0"?>
<!-- modules/InterModule1.mxml -->
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" width="100%"
height="100%">
<mx:Script><![CDATA[
// Defines the method that the other module calls.
public function getNewTitle():String {
return "New Module Title";
}
]]></mx:Script>
</mx:Module>
Module 2:
<?xml version="1.0"?>
<!-- modules/InterModule2.mxml -->
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" width="100%"
height="100%">
<mx:Script><![CDATA[
[Bindable]
private var title:String;
]]></mx:Script>
<mx:HBox>
<mx:Label id="l1" text="Title: "/>
<mx:Label id="myTitle" text="{title}"/>
</mx:HBox>
<mx:Button id="b1" label="Change Title" click="changeTitle()"/>
</mx:Module>
]]></mx:Script>
<mx:Form>
<mx:FormItem id="fi1" label="First Name:">
<mx:TextInput id="ti1"/>
</mx:FormItem>
<mx:FormItem id="fi2" label="Last Name:">
<mx:TextInput id="ti2"/>
</mx:FormItem>
</mx:Form>
<mx:ModuleLoader id="m1"/>
</mx:Application>
[Bindable]
private var salutation:String;
[Bindable]
public var selectedItem:Object;
[Bindable]
public var currentModuleName:String;
<mx:Form>
<mx:FormItem label="Current Module:">
<mx:Label id="l1" text="{currentModuleName}"/>
</mx:FormItem>
<mx:FormItem label="Adjuster ID:">
<mx:TextInput id="myId" text="Enter your ID"/>
function getModuleName():String;
function setAdjusterID(s:String):void;
function setBackgroundColor(n:Number):void;
}
<mx:Panel id="p1"
title="Auto Insurance"
width="100%"
height="100%"
backgroundColor="{bgcolor}"
>
<mx:Label id="myLabel" text="ID: {adjuster}"/>
</mx:Panel>
<mx:Script>
<![CDATA[
[Bindable]
private var adjuster:String;
[Bindable]
private var bgcolor:Number;
CHAPTER 35
Contents
About history management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1328
Using standard history management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1328
Using custom history management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1330
How the HistoryManager class saves and loads states. . . . . . . . . . . . . . . . . . . . . . 1336
Using history management in a custom wrapper . . . . . . . . . . . . . . . . . . . . . . . . . . . 1337
1327
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
About history management
The Flex History Manager lets users navigate through a Flex application by using the web
browser’s back and forward navigation commands. For example, a user can navigate through
several Accordion container panes in a Flex application, and then click the browser’s Back
button to return the application to its previous states.
History management is implemented as a set of files that are referenced in the application’s
wrapper. By default, Adobe Flex Builder generates a wrapper that supports history
management. The web-tier compiler included in LiveCycle Data Services ES also generates a
wrapper that supports history management by default. In both cases, you can disable history
management support.
If you are using the command-line compiler to create your Flex application, you must create
your own wrapper or use one of the wrapper templates. You can customize your wrapper to
include support for history management. For more information, see “Using history
management in a custom wrapper” on page 1337. For information on writing a custom
wrapper, see Chapter 16, “Creating a Wrapper,” in Building and Deploying Flex Applications.
For Flex components, history management is automatically supported by navigator containers
such as the Accordion and TabNavigator containers. You can also use the HistoryManager
class in ActionScript to provide custom history management for other objects in an
application, and to call the HistoryManager class’s methods.
In the following example, the user’s panel selections are saved for the first Accordion container
because it uses default settings, but the second Accordion container has the
historyManagementEnabled property explicitly set to false. When the user selects the web
browser’s back or forward command, the previous or next state is displayed for the first
container, but not for the second.
<?xml version="1.0"?>
<!-- historymanager/DisableHistoryManagement.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" width="600"
height="800">
The following example calls the boxChanged() method in the change event handler:
<mx:CheckBox
xmlns:mx="http://www.adobe.com/2006/mxml"
implements="mx.managers.IHistoryManagerClient"
creationComplete="mx.managers.HistoryManager.register(this);"
change="boxChanged(event)">
<mx:Script><![CDATA[
import mx.managers.HistoryManager;
...
<mx:Script><![CDATA[
import mx.managers.HistoryManager;
if (newState != selected) {
selected = newState;
} else {
if (newState) {
selected = false;
} else {
selected = true;
}
}
}
</mx:CheckBox>
<local:MyCheckBox/>
</mx:Application>
When the user checks and unchecks the custom CheckBox control, they can use the browser’s
forward and back buttons to return to the previous state of the control.
An application’s total navigation state is limited to the maximum URL size supported by the
user’s web browser, so you should write the saveState() method for a component to save the
least amount of data possible. For example, you can write a saveState() method for a List
control that saves just the selectedIndex property.
<mx:Script>
<![CDATA[
[Bindable]
private var listData:Array = ["Flex", "Dreamweaver",
"Flash", "Breeze", "Contribute"];
]]>
</mx:Script>
<mx:TextInput id="text1"
text="{list1.selectedItem? list1.selectedItem : ''}"/>
</mx:Application>
In this example, you populate the HistoryList control with an Array of Strings. As you select
an item in the HistoryList control, it also appears in the TextInput control. Use the browser’s
back button to cycle back through your selections.
Method Description
register(component) Registers a component with the HistoryManager class; for
example:
HistoryManager.register(myList);
3. Insert the history.htm file in an iframe element at the bottom of the page, as the following
example shows:
<iframe name="_history.htm" src="history.htm" width="22" height="0"/>
You must set the name property of the iframe to _history.htm (with the underscore). You
can set the height property to any value you want, but the width property must be a
minimum of 22 in order to work in Internet Explorer. Users do not interact with the
history.htm page, so it does not need to be visible on the page.
4. Add the historyUrl and lconid parameters to the flashVars variable for both the
object and embed tags, as the following example shows.
You must add these parameters in JavaScript, because history management uses a
JavaScript variable called lc_id.
document.write("flashvars='historyUrl=history%5Fhtml&lconid=" +
lc_id'");
5. Deploy the history.js and history.htm files to your web server and ensure that their
locations match those set in the wrapper.
6. Deploy the history.swf file to your web server and ensure that it is in the same location as
the history.htm file.
If you want to change the location of the history.swf file, be sure to update the path to the
history.swf file in the history.htm file.
If your wrapper supports history management but does not include any player version
detection logic or support for Express Install, you must combine the contents of the history.js
and myscript.js files.
2. Add the historyUrl and lconid parameters to the flashVars variable for both the
object and embed tags, as the following example shows.
You must add these parameters in JavaScript, because history management uses a
JavaScript variable called lc_id.
document.write("
flashvars='historyUrl=%2Fflex%2Fflex%2Dinternal%3Faction%3Dhistory%5F
html&lconid=" + lc_id'");
3. Add the _history iframe element, as the following example shows (note that the value of
the width property must be at least 22, although the height property can be any value):
<iframe src='/flex/flex-internal?action=history_html' name='_history'
frameborder='0' scrolling='no' width='22' height='0'></iframe>
CHAPTER 36
Printing 36
Many Adobe Flex applications let users print from within the application. For example, you
might have an application that returns confirmation information after a user completes a
purchase. Your application can allow users to print the information on the page to keep for
their records.
This topic describes the options for printing when you use the mx.printing.FlexPrintJob,
mx.printing.PrintDataGrid, and mx.printing.PrintAdvancedDataGridclasses.
N OTE
You can also print by using the context menu in Adobe Flash Player 9, or the Flash
ActionScript PrintJob class, which is documented in ActionScript 3.0 Language
Reference.
Contents
About printing by using Flex classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1342
Using the FlexPrintJob class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1342
Using a print-specific output format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1347
Printing multipage output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1351
1341
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
About printing by using Flex classes
The Flex mx.printing package contains three classes that facilitate the creation of printing
output from Flex applications:
FlexPrintJob A class that prints one or more objects. Automatically splits large objects for
printing on multiple pages and scales the output to fit the page size.
PrintDataGrid A subclass of the DataGrid control with a default appearance that is
customized for printing. The class includes properties and a method that provide additional
sizing and printing features.
PrintAdvancedDataGrid A subclass of the AdvancedDataGrid control with a default
appearance that is customized for printing. The class includes properties and a method that
provide additional sizing and printing features.
FlexPrintJobScaleType Defines constants used in the FlexPrintJob addObject() method.
Together, these classes give you control over how the user prints information from the
application. For example, your application can print only a selected subset of the information
on the screen, or it can print information that is not being displayed. Also, your application
can reformat the information and optimize its layout and appearance for printing.
Users can print to PostScript and non-PostScript printers, including the Adobe PDF and
Macromedia® FlashPaper™ from Adobe® printer drivers.
The FlexPrintJob class causes the operating system to display a Print dialog box. You
cannot print without some user action.
1342 Printing
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Building and sending a print job
You print output by building and sending a print job, as outlined in the following procedure.
Because you are spooling a print job to the user’s operating system between your calls
to the start() and send() methods, you should limit the code between these calls to
print-specific activities. For example, the Flash content should not interact with the user
between the start() and send() methods.
The following sections detail the procedures you use in these steps.
Depending on the user’s operating system, an additional dialog box might appear until
spooling is complete and the application calls the send() method.
Constant Action
MATCH_WIDTH (Default) Scales the object to fill the available page width. If the
resulting object height exceeds the page height, the output spans
multiple pages.
MATCH_HEIGHT Scales the object to fill the available page height. If the resulting
object width exceeds the page width, the output spans multiple
pages.
SHOW_ALL Scales the object to fit on a single page, filling one dimension; that is,
it selects the smaller of the MATCH_WIDTH or MATCH_HEIGHT
scale types.
FILL_PAGE Scales the object to fill at least one page completely; that is, it selects
the larger of the MATCH_WIDTH or MATCH_HEIGHT scale types.
NONE Does not scale the output. The printed page has the same
dimensions as the object on the screen. If the object height, width, or
both dimensions exceed the page width or height, the output spans
multiple pages.
If an object requires multiple pages, the output splits at the page boundaries. This can result
in unreadable text or inappropriately split graphics. For information on how to format your
print job to avoid these problems, see “Printing multipage output” on page 1351.
1344 Printing
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The FlexPrintJob class includes two properties that can help your application determine how
to scale the print job. These properties are read-only and are initially 0. When the application
calls the start() method and the user selects the Print option in the operating system Print
dialog box, Flash Player retrieves the print settings from the operating system. The start()
method populates the following properties:
A point is a print unit of measurement that is 1/72 of an inch. Flex automatically maps 72
pixels to one inch (72 points) of printed output, based on the printer settings.
<mx:Script>
<![CDATA[
import mx.printing.*;
<mx:VBox id="myVBox">
<mx:DataGrid id="myDataGrid" width="300">
<mx:dataProvider>
<mx:Object Product="Flash" Code="1000"/>
<mx:Object Product="Flex" Code="2000"/>
<mx:Object Product="ColdFusion" Code="3000"/>
<mx:Object Product="JRun" Code="4000"/>
</mx:dataProvider>
</mx:DataGrid>
<mx:Button id="myButton"
label="Print"
click="doPrint();"/>
</mx:VBox>
</mx:Application>
In this example, selecting the Button control invokes the doPrint() event listener. The event
listener creates an instance of the FlexPrintJob class to print the DataGrid control, adds the
DataGrid control to the print job using the addObject() method, and then uses the send()
method to print the page.
1346 Printing
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
To print the DataGrid and Button controls on your page, specify myVBox, the ID of the
object that contains both controls, in the addObject() method’s object parameter. If want
to print the DataGrid and Button controls on separate pages, specify each object in a separate
addObject() method.
To print the DataGrid control so that it spans the page width, omit the second addObject()
method parameter, or specify FlexPrintJobScaleType.MATCH_WIDTH. To print the
DataGrid control with the largest size that fits on a single page, specify
FlexPrintJobScaleType.SHOW_ALL . In the previous example,
FlexPrintJobScaleType.SHOW_ALL has the same result as
FlexPrintJobScaleType.MATCH_WIDTH because the DataGrid is short.
The following image shows how the output looks when the user clicks the Print button to
print the data:
In this example, the MXML application file displays the screen and controls the printing. A
separate custom MXML component defines the appearance of the printed output.
When the user clicks the Print button, the application’s doPrint() method does the
following things:
1. Creates and starts the print job to display the operating system’s Print dialog box.
2. After the user starts the print operation in the Print dialog box, creates a child control using
the myPrintView component.
3. Sets the MyPrintView control’s data from the form data.
1348 Printing
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
4. Sends the print job to the printer.
5. Cleans up memory by removing the print-specific child component.
The printed output does not include the labels from the screen, and the application combines
the text from the screen’s three input boxes into a single string for printing in a Label control.
The following code shows the contents of the application file:
<?xml version="1.0"?>
<!-- printing\DGPrintCustomComp.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
height="450"
width="550">
<mx:Script>
<![CDATA[
import mx.printing.FlexPrintJob;
import myComponents.MyPrintView;
1350 Printing
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The following MyPrintView.mxml file defines the component used by the application’s
doPrint() method. The component is a VBox container; it contains a Label control, into
which the application writes the contact information from the first three fields of the form,
and a PrintDataGrid control, which displays the data from the data source of the screen view’s
DataGrid control. For more information on the PrintDataGrid control and its advantages for
printing, see “Using the PrintDataGrid control for multipage grids” on page 1352.
<?xml version="1.0"?>
<!-- printing\myComponents\MyPrintView.mxml -->
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundColor="#FFFFFF"
height="250" width="450"
paddingTop="50" paddingLeft="50" paddingRight="50">
1352 Printing
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The following properties provide information on page sizing that are affected by the
sizeToPage property:
Property Description
currentPageHeight Contains the height of the grid, in pixels, that results if the sizeToPage
property is true. If the sizeToPage property is true, the
currentPageHeight property equals the height property.
originalHeight Contains the grid height that results if the sizeToPage property is
false. If the sizeToPage property is false, the originalHeight property
equals the height property.
In most applications, you leave the sizeToPage attribute at its default value (true), and use
the height property to determine the grid height.
The sizeToPage property does not affect the way the page breaks when a single
PrintDataGrid control page is longer than a print page. To print multipage data grids without
splitting rows, you must divide the grid items into multiple views by using the nextPage()
method, as described in “Using the nextPage() method and validNextPage property to print
multiple pages” on page 1353.
The following code shows a loop that prints a grid using multiple pages, without having rows
that span pages:
// Queue the first page.
printJob.addObject(thePrintView);
// While there are more pages, print them.
while (thePrintView.myDataGrid.validNextPage) {
//Put the next page of data in the view.
thePrintView.myDataGrid.nextPage();
//Queue the additional page.
printJob.addObject(thePrintView);
}
1354 Printing
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The files include detailed comments explaining the purpose of the code.
<mx:Script>
<![CDATA[
import mx.printing.*;
import mx.collections.ArrayCollection;
// Import the MXML custom print view control.
import myComponents.FormPrintView;
1356 Printing
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
// Try creating a last page.
thePrintView.showPage("last");
<mx:Script>
<![CDATA[
import mx.core.*
1358 Printing
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
}
]]>
</mx:Script>
1360 Printing
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The following example uses the PrintAdvancedDataGrid control to print an instance of the
AdvancedDataGrid control:
<?xml version="1.0"?>
<!-- printing\ADGPrint.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.printing.*;
import mx.collections.ArrayCollection;
import mx.printing.PrintAdvancedDataGrid;
include "SimpleHierarchicalData.as";
<mx:VBox id="myVBox"
width="100%" height="100%">
<mx:AdvancedDataGrid id="adg"
width="100%" height="100%">
<mx:dataProvider>
<mx:HierarchicalData source="{dpHierarchy}"/>
</mx:dataProvider>
<mx:columns>
<mx:AdvancedDataGridColumn dataField="Region"/>
<mx:AdvancedDataGridColumn dataField="Territory_Rep"
headerText="Territory Rep"/>
<mx:Button id="myButton"
label="Print"
click="doPrint();"/>
</mx:VBox>
</mx:Application>
This example uses the PrintAdvancedDataGrid.source property to initialize the
PrintAdvancedDataGrid control from the AdvancedDataGrid control.
To support the AdvancedDataGrid control, the PrintAdvancedDataGrid control adds the
following properties not available in the PrintDataGrid control:
Property Description
allowInteractions If true, allow some interactions with the control, such as column resizing,
column reordering, and expanding or collapsing nodes. The default value
is false.
displayIcons If true, display the folder and leaf icons in the navigation tree. The default
value is true.
source Initialize the PrintAdvancedDataGrid control and all of its properties from
the specified AdvancedDataGrid control.
validPreviousPage Indicates that the data provider contains data rows that precede the rows
that the PrintAdvancedDataGrid control currently displays.
1362 Printing
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
CHAPTER 37
Communicating with
the Wrapper
37
This topic describes how to exchange data between an Adobe Flex application and the HTML
page that embeds that application.
Contents
About exchanging data with Flex applications. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1363
Passing request data to Flex applications. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1368
Accessing JavaScript functions from Flex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1373
Accessing Flex from JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1387
About ExternalInterface API security in Flex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1393
1363
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
There are several ways to communicate between the surrounding environment and the Flex
application; depending on the type of integration required, any combination of flashVars
properties, query string parameters, the navigateToURL() method, and the ExternalInterface
class can be employed. In addition, you can communicate between two Flex applications on
the same page by using SharedObjects.
To pass request data into your Flex applications, you can define flashVars properties inside
your HTML wrapper and access their values using either the
Application.application.parameters or LoaderConfig.parameters objects. For more
information, see “Passing request data with flashVars properties” on page 1368. Using these
techniques, you can personalize a Flex application without requiring a recompilation.
Use the methods of the ExternalInterface API to call the methods of your Flex applications
and vice versa. The addCallback() method exposes methods of your Flex application to the
wrapper. The call() method invokes a method within the wrapper and returns any results. If
the wrapper is HTML, the addCallback() and call() methods enable method invocation
between your Flex application and the hosted JavaScript running within the browser. For
more information, see “About the ExternalInterface API” on page 1366.
In some situations, you want to open a new browser window or navigate to a new location.
You can do this with the navigateToURL() global function. Although it is not part of the
ExternalInterface API, this method is flexible enough to let you write JavaScript inside it, and
invoke JavaScript functions on the resulting HTML page. The navigateToURL() method is a
global function in the flash.net package.
[Bindable]
public var g_HostString:String;
[Bindable]
public var g_ContextRoot:String;
[Bindable]
public var g_BaseURL:String;
<mx:Form>
<mx:FormItem label="Base URL:">
<mx:Label text="{g_BaseURL}"/>
</mx:FormItem>
<mx:FormItem label="Host Name:">
<mx:Label text="{g_HostString}"/>
</mx:FormItem>
<mx:FormItem label="Context Root:">
<mx:Label text="@ContextRoot()"/>
</mx:FormItem>
</mx:Form>
</mx:Application>
You can also use the flash.system.Capabilities class to access information about the client, such
as Operating System, Player version, and language. For more information, see Using Flash
ActionScript.
You are not required to set the value of swliveconnect to true in the <object> tag because
the <object> tag is used by Microsoft Internet Explorer, but not Netscape browsers.
]]></mx:Script>
</mx:Application>
For examples of using the ExternalInterface API with Flex applications, see “Using the
ExternalInterface API to access JavaScript from Flex” on page 1374 and “Accessing Flex from
JavaScript” on page 1387.
In addition to requiring that browsers meet certain version requirements, the
ExternalInterface API requires that JavaScript is enabled in the browser. You can use the
<noscript> tag in the HTML page to handle a browser with disabled JavaScript. For more
information, see “Handling browsers that disable JavaScript” on page 1393.
The available property determines only if the browser can support the ExternalInterface
API, based on its version and manufacturer. If JavaScript is disabled in the browser, the
available property still returns true.
The ExternalInterface API is restricted by the security sandbox in which the SWF file is
running. Its use relies on the domain-based security restrictions that the allowScriptAccess
and allowNetworking parameters define. You set the values of the allowScriptAccess and
allowNetworking parameters in the SWF file’s wrapper.
For more information on these parameters, see Chapter 16, “Creating a Wrapper,” in Building
and Deploying Flex Applications.
</td></tr></table>
</body>
</html>
If you are using the wrapper that is generated by the web-tier compiler or wrappers that are
included in the resources/html-templates directory, your wrapper might not look the same,
but the basic approach to passing the flashVars properties is. For example, you might insert
flashVars properties by appending them to a function parameter, as the following example
shows:
"flashvars","historyUrl=%2Fflex%2Fflex%2Dinternal%3Faction%3Dhistory%5Fhtml
&lconid=" + lc_id + "&firstName=Nick&lastName=Danger",
The value of the flashVars properties do not have to be static. If you use JSP to return the
wrapper, for example, you can use any JSP expression for the value of the flashVars
properties that can be evaluated to a String.
<%
String fName = (String) request.getParameter("firstname");
String mName = (String) request.getParameter("middlename");
String lName = (String) request.getParameter("lastname");
%>
<body scroll='no'>
<table width='100%' height='100%' cellspacing='0' cellpadding='0'><tr><td
valign='top'>
<script>
<h1>Dynamic FlashVarTest Wrapper</h1>
</script>
</td></tr></table>
</body>
</html>
If your user requests the SWF file directly in the browser, without a wrapper, you can access
variables on the query string without providing additional code. The following URL passes
the name Nick and the hometown San Francisco to the Flex application:
http://localhost:8100/flex/myApp.swf?myName=Nick&myHometown=San%20Francisco
For more information about the HTML wrapper, see Building and Deploying Flex
Applications.
You cannot pass query string parameters to a Flex application that runs inside the stand-
alone Flash Player.
Variables you define in this manner are accessible in the same way as flashVars properties.
For more information, see “Accessing the flashVars properties” on page 1372.
<mx:VBox>
<mx:HBox>
<mx:Label text="Name: "/>
<mx:Label text="{myName}" fontWeight="bold"/>
</mx:HBox>
<mx:HBox>
<mx:Label text="Hometown: "/>
<mx:Label text="{myHometown}" fontWeight="bold"/>
</mx:HBox>
</mx:VBox>
</mx:Application>
When a user requests this application with the myName and myHometown parameters defined as
flashVars properties, Flex displays their values in the Label controls.
</mx:Application>
The function_name is the name of the function in the HTML page’s JavaScript. The
arguments are the arguments that you pass to the JavaScript function. You can pass one or
more arguments in the traditional way of separating them with commas, or you can pass an
object that is deserialized by the browser. The arguments are optional.
<mx:Form>
<mx:FormItem label="New Title:">
<mx:TextInput id="ti1"/>
</mx:FormItem>
</mx:Form>
<SCRIPT LANGUAGE="JavaScript">
function changeDocumentTitle(a) {
window.document.title=a;
alert(a);
return "successful";
}
</SCRIPT>
</mx:Application>
Flex only serializes public, nonstatic variables and read-write properties of ActionScript
objects. You can pass numbers and strings as properties on objects, simple objects such as
primitive types and arrays, or arrays of simple objects.
<SCRIPT LANGUAGE="JavaScript">
function receiveComplexDataTypes(o) {
alert("Welcome " + o.fname + " " + o.lname + "!");
return "successful";
}
</SCRIPT>
</body></html>
</mx:Application>
<SCRIPT LANGUAGE="JavaScript">
function receiveComplexDataTypes(o) {
// Get value of fname and lname properties.
var s = ("Welcome " + o.fname + " " + o.lname + "!\n");
// Iterate over embedded object's properties.
for (i=0; i<o.b.length; i++) {
s += o.b[i] + "\n";
}
alert(s);
}
</SCRIPT>
</body></html>
Flex and Flash Player have strict security in place to prevent cross-site scripting. By default,
you cannot call script on an HTML page if the HTML page is not in the same domain as the
Flex application. However, you can expand the sources from which scripts can be called. For
more information, see “About ExternalInterface API security in Flex” on page 1393.
You cannot pass objects or arrays that contain circular references. For example, you cannot
pass the following object:
var obj = new Object();
obj.prop = obj; // Circular reference.
For more information on these parameters, see Chapter 16, “Creating a Wrapper,” in Building
and Deploying Flex Applications. For more information on security restrictions, see Chapter 4,
“Applying Flex Security,” in Building and Deploying Flex Applications.
The request argument is a URLRequest object that specifies the destination. The window
argument specifies whether to launch a new browser window or load the new URL into the
current window. The following table describes the valid values for the window argument:
Value Description
_self Specifies the current frame in the current window.
_blank Specifies a new window. This new window acts as a pop-up window in the
client’s browser, so you must be aware that a pop-up blocker could prevent it
from loading.
You pass a URLRequest object to the navigateToURL() method. This object defines the
URL target, variables, method (POST or GET), window, and headers for the request. The
following example defines a simple URL to navigate to:
<?xml version="1.0"?>
<!-- wrapper/SimplestNavigateToURL.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import flash.net.*;
public function openNewWindow(event:MouseEvent):void {
var u:URLRequest = new URLRequest("http://www.adobe.com/flex");
navigateToURL(u,"_blank");
}
]]></mx:Script>
<mx:Button label="Open New Window" click="openNewWindow(event)"/>
</mx:Application>
The navigateToURL() method URL encodes the value of the url argument.
To send data with a URLRequest object, you can append variables to the request string. The
following example launches a new window and passes a search term to the URL:
<?xml version="1.0"?>
<!-- wrapper/SimpleNavigateToURL.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import flash.net.*;
public function executeSearch(event:MouseEvent):void {
var u:URLRequest = new URLRequest("http://www.google.com/
search?hl=en&q=" + ta1.text);
navigateToURL(u,"_blank");
}
]]></mx:Script>
<mx:TextArea id="ta1"/>
<mx:Button label="Search" click="executeSearch(event)"/>
</mx:Application>
The previous code does not work on all browsers. You should include code that detects the
browser type, and closes the window based on the type of browser. Also, some browsers, such
as Internet Explorer, behave in unexpected ways when you invoke a URLRequest that
contains JavaScript. Here are some examples:
■ Executes the JavaScript URLs asynchronously. This means that it is possible to have
multiple calls to the navigateToURL() method that is trying to execute JavaScript
methods, and have only the last one occur. Each one overwrites the next.
<SCRIPT LANGUAGE="JavaScript">
function catchClick(name, type) {
alert(name + " triggered the " + type + " event.");
}
</SCRIPT>
</body></html>
This feature requires that the client is running certain browsers. For more information,
see “About the ExternalInterface API” on page 1366.
</mx:Script>
<mx:Label id="l1"/>
</mx:Application>
<SCRIPT LANGUAGE="JavaScript">
function callApp() {
window.document.title = document.getElementById("newTitle").value;
mySwf.myFlexFunction(window.document.title);
}
</SCRIPT>
<h1>AddCallback Wrapper</h1>
<form id="f1">
Enter a new title: <input type="text" size="30" id="newTitle"
onchange="callApp()">
</form>
</body></html>
The default value of the id and name properties in the wrapper that is generated by LiveCycle
Data Services ES is mxml_filename.mxml.swf. The name that you use to access the Flex
application in your HTML page’s script cannot contain any periods, so you must change the
default values in the wrapper. For more information, see “Editing the Flex application’s id and
name properties” on page 1392.
<SCRIPT LANGUAGE="JavaScript">
// Internet Explorer and Mozilla-based browsers refer to the Flash
application
// object differently.
// This function returns the appropriate reference, depending on the
browser.
function getMyApp(appName) {
if (navigator.appName.indexOf ("Microsoft") !=-1) {
return window[appName];
} else {
return document[appName];
}
}
function callApp() {
window.document.title = document.getElementById("newTitle").value;
getMyApp("mySwf").myFlexFunction(window.document.title);
}
</SCRIPT>
<h1>AddCallBack Wrapper</h1>
<form id="f1">
Enter a new title: <input type="text" size="30" id="newTitle"
onchange="callApp()">
</form>
</body></html>
The following table describes the valid values of the allowScriptAccess parameter:
Value Description
never The call() method fails.
sameDomain The call() method succeeds if the calling application is from same domain as
the HTML page. This is the default value.
always The call() method succeeds, regardless of whether the calling application is
in the same domain as the HTML page.
CHAPTER 38
Contents
About shared objects. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1395
Creating a shared object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1397
Destroying shared objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1404
SharedObject example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1404
1395
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
■ They are stored in a location specified by the client browser.
■ They are transmitted from client to server through HTTP.
In contrast, shared objects have the following properties:
■ They do not expire by default.
■ By default, they are limited to a size of 100 KB each.
■ They can store simple data types (such as String, Array, and Date).
■ They are stored in a location specified by the application (within the user’s home
directory).
■ They are never transmitted between the client and server.
Method Description
clear() Purges all of the data from the SharedObject object, and deletes the
SharedObject file from the disk.
flush() Immediately writes the SharedObject file to a file on the client.
getLocal() Returns a reference to the client’s domain-specific, local SharedObject
object. If none exists, this method creates a new shared object on the client.
getSize() Gets the size of the SharedObject file, in bytes. The default size limit is
100 KB, although it can be larger if the client allows it.
Property Description
data Read-only property that represents the collection of attributes the shared
object stores.
onStatus The shared object’s event handler that is invoked for every warning, error, or
informational note.
Linux/Unix /home/username/.macromedia/Flash_Player/#SharedObjects/
web_domain/path_to_application/application_name/
object_name.sol
For example, if you request an application named MyApp.mxml on the local host, in the Flex
context, and within a subdirectory named /sos, Flash Player stores the *.sol file in the
following location on Windows:
c:/Documents and Settings/fred/localhost/Application Data/Macromedia/Flash
Player/#localhost/flex/sos/MyApp.mxml.swf/data.sol
N OTE
Although usually predictable, the location of the SharedObject file can be anywhere that Flash
Player has access to within its sandbox and can have any name that Flash Player assigns to it.
Specifying a path
You can use the optional pathname parameter to specify a location for the SharedObject file.
This file must be a subdirectory of that domain’s SharedObject directory. For example, if you
request an application on the localhost and specify the following:
mySO = SharedObject.getLocal("myObjectFile","/");
Flash Player writes the SharedObject file in the /#localhost directory. This is useful if you
want more than one application on the client to be able to access the same shared object. In
this case, the client could run two Flex applications, both of which specify a path to the shared
object that is the root of the domain; the client could then access the same shared object from
both applications. To share data between more than application without persistence, you can
use the LocalConnection object.
If you specify a directory that does not exist, Flash Player does not create a SharedObject file.
The following example adds the userName, itemNumbers, and adminPrivileges properties
and their values to a SharedObject:
public var currentUserName:String = "Reiner";
public var itemsArray:Array = new Array(101,346,483);
public var currentUserIsAdmin:Boolean = true;
mySO.data.userName = currentUserName;
mySO.data.itemNumbers = itemsArray;
mySO.data.adminPrivileges = currentUserIsAdmin;
After you assign values to the data property, you must instruct Flash Player to write those
values to the SharedObject’s file. To force Flash Player to write the values to the
SharedObject’s file, use the SharedObject.flush() method, as follows:
mySO.flush();
[Bindable]
public var welcomeMessage:String;
[Bindable]
public var localFeeds:ArrayCollection = new ArrayCollection();
[Bindable]
public var localSites:ArrayCollection = new ArrayCollection();
if (lsofeeds.getObjects()) {
localFeeds = lsofeeds.getObjects();
}
if (lsosites.getObjects()) {
localSites = lsosites.getObjects();
}
}
]]>
</mx:Script>
<mx:Panel title="Blogs">
<mx:Form id="blogForm">
<mx:HBox>
<mx:FormItem label="Name:">
<mx:TextInput id="ti1" width="100"/>
</mx:FormItem>
<mx:FormItem label="Location:">
<mx:TextInput id="ti2" width="400"/>
</mx:FormItem>
<mx:Button id="b1" label="Add Feed" click="addFeed()"/>
</mx:HBox>
<mx:Panel title="Sites">
<mx:Form id="siteForm">
<mx:HBox>
<mx:FormItem label="Site:">
<mx:TextInput id="ti3" width="400"/>
</mx:FormItem>
<mx:Button id="b3" label="Add Site" click="addSite()"/>
</mx:HBox>
</mx:Application>
SharedObject example
The following example shows that you can store simple objects, such as a Date object, in a
SharedObject object without having to manually serialize and deserialize those objects.
The following example begins by welcoming you as a first-time visitor. When you click Log
Out, the application stores the current date in a shared object. The next time you launch this
application or refresh the page, the application welcomes you back with a reminder of the
time you logged out.
]]></mx:Script>
<mx:Label id="label1" text="{welcomeMessage}"/>
<mx:Button label="Log Out" click="storeDate()"/>
<mx:Button label="Delete LSO" click="deleteLSO()"/>
</mx:Application>
For more examples of using shared objects, see the Flex example applications in the
samples.war file.
CHAPTER 39
Creating Accessible
Applications
39
Adobe Flex provides accessibility features that let you create applications that are accessible to
users with disabilities. As you design accessible applications, consider how your users will
interact with the content. Visually impaired users, for example, might rely on assistive
technology such as screen readers, which provide an audio version of screen content, or screen
magnifiers, which display a small portion of the screen at a larger size, effectively reducing the
visible screen area. Hearing-impaired users might read text and captions in the document in
place of audio content. Other considerations arise for users with mobility or cognitive
impairments.
This topic describes the accessibility features of Flex.
Contents
Accessibility overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1407
About screen reader technology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1409
Configuring Flex applications for accessibility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1411
Accessible components and containers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1412
Creating tab order and reading order . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1416
Creating accessibility with ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1420
Accessibility for hearing-impaired users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1421
Testing accessible content. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1421
Accessibility overview
You create accessible content by using accessibility features included with Flex, by taking
advantage of ActionScript designed to implement accessibility, and by following
recommended design and development practices. The following list of recommended
practices is not exhaustive, but suggests common issues to consider. Depending on your
audience’s needs, additional requirements may arise.
1407
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Visually impaired users For visually impaired users, keep in mind the following design
recommendations:
■ Design and implement a logical tab order for the tabs.
■ Design the document so that constant changes in content do not unnecessarily cause
screen readers to refresh. For example, you should group or hide looping elements.
■ Provide captions for narrative audio. Be aware of audio in your document that might
interfere with a user being able to listen to the screen reader.
■ Use percentage sizing so that your applications scale properly at smaller screen sizes. This
allows users of screen magnifiers to see more of your application at one time. Also take
into account that many visually impaired users run applications with lower screen
resolutions than other users.
■ Ensure that foreground and background colors contrast sufficiently to make text readable
for people with low vision.
■ Ensure that controls don’t depend on the use of a specific pointer device, such as a mouse
or trackball.
■ Ensure that components are accessible by keyboard. All Flex components defined as
accessible include keyboard navigation. For a list of these components and the available
keyboard commands for each, see “Accessible components and containers” on page 1412.
Color blind users For color blind users, ensure that color is not the only means of
conveying information.
Users with mobility impairment For users with mobility impairment, keep in mind the
following design recommendations:
■ Ensure that controls don’t depend on the use of a specific pointer device.
■ Ensure that components are accessible by keyboard. All Flex components defined as
accessible include keyboard navigation. For a list of these components and the available
keyboard commands for each, see “Accessible components and containers” on page 1412.
Hearing-impaired users For hearing-impaired users, ensure that you add captions to audio
content.
Users with cognitive impairment For users with cognitive impairments, such as dyslexia,
keep in mind the following design recommendations:
■ Ensure an uncluttered, easy-to-navigate design.
■ Provide graphical imagery that helps convey the purpose and message of the application.
These graphics should enhance, not replace, textual or audio content.
■ Provide more than one method to accomplish common tasks.
Flex support is most comprehensive in the JAWS screen reader. You must have JAWS
version 6.10.1006 or later.
MSAA is currently not supported in the opaque windowless and transparent windowless
modes. (These modes are options in the HTML Publish Settings panel, available for use
with the Windows version of Internet Explorer 4.0 or later, with the Flash ActiveX
control.) If your Flash content must be accessible to screen readers, avoid using these
modes.
■ Enable accessibility when you are using the mxmlc command-line compiler.
When you compile a file by using the mxmlc command-line compiler, you can use the
-accessible option to enable accessibility, as the following example shows:
mxmlc -accessible c:/dev/myapps/mywar.war/app1.mxml
For more information on the command-line compiler, see Chapter 9, “Using the Flex
Compilers,” in Building and Deploying Flex Applications.
If you are building applications for Adobe LiveCycle Data Services ES, and are deploying the
application as MXML files, you can enable accessibility on an individual request by setting the
accessible query parameter to true, as the following example shows:
http://www.mycompany.com/myflexapp/app1.mxml?accessible=true
If you edited the flex-config.xml file to enable accessibility by default, you can disable it for an
individual request by setting the accessible query parameter to false, as the following
example shows:
http://www.mycompany.com/myflexapp/app1.mxml?accessible=false
For more information on the command-line compiler, see Chapter 9, “Using the Flex
Compilers,” in Building and Deploying Flex Applications.
Alert control In Forms mode, the text in the Alert control is announced, and the label
of its default button.
When not in Forms mode, the text in the Alert control is announced twice
when you press the Down Arrow.
CheckBox control Press the Spacebar to activate the check box items.
For more information on keyboard navigation, see “CheckBox control
user interaction” on page 296.
ComboBox control For more information on keyboard navigation, see “ComboBox control
user interaction” on page 473.
DataGrid control Press the arrow keys to highlight the contents, and then move between
the individual characters within that field.
When using a screen reader in forms mode, use the Tab key to move
between editable TextInput fields in the DataGrid control.
For more information on keyboard navigation, see “DataGrid control
user interaction” on page 486.
DateChooser Press the Up, Down, Left, and Right Arrow keys to change the selected
control date. Use the Home key to reach the first enabled date in the month and
the End key to reach the last enabled date in a month. Use the Page Up
and Page Down keys to reach the previous and next months. For more
information on keyboard navigation, see “User interaction” on page 315.
Form container For information on keyboard navigation, see “Defining a default button”
on page 650.
Image control An Image control with a ToolTip defined is read by a screen reader only
when Forms mode is inactive. The Image control is not focusable in
Forms mode, or by the keyboard.
Label control A Label control is read by a screen reader when it is associated with
other controls, or when the Forms mode is inactive. The Label control is
not focusable in Forms mode, or by the keyboard.
LinkButton control LinkButton control activation when using a screen reader varies,
depending on the screen reader. In JAWS 6.10, press the Spacebar to
activate a LinkButton control when in Forms mode. When Forms mode
is inactive, use the Spacebar or Enter key to activate the control.
For more information on keyboard navigation, see “LinkButton control
user interaction” on page 319.
List control Screen reader navigation is the same as for keyboard navigation.
For more information on keyboard navigation, see “Keyboard
navigation” on page 461.
For information on creating data tips (tooltips for individual list
elements), see “Displaying DataTips” on page 452. For information on
creating scroll tips (tooltips that provide information while the user scrolls
through a list), see “Displaying ScrollTips” on page 452.
Menu control Screen reader navigation is the same as for keyboard navigation.
For more information on keyboard navigation, see “Menu control user
interaction” on page 438.
MenuBar control Screen reader navigation is the same as for keyboard navigation.
For more information on keyboard navigation, see “Menu control user
interaction” on page 438.
Panel container Screen reader announces the panel title only when Forms mode is
inactive.
RadioButtonGroup Screen reader navigation is the same as for the RadioButton control.
control
Slider control In forms mode the control is announced along with the orientation of the
control (left-right or up-down) and the current value.
The control uses the following keys for a left-right slider:
• Left Arrow / Right Arrow - move slider to lower/higher value.
• Page Up / Page Down - move slider to top/ bottom of range.
The control uses the following keys for an up/down slider:
• Down Arrow/Up Arrow - move slider to lower/higher value.
• Home/End - move slider to top/ bottom of range.
Text control A Text control is not focusable, and is only read by screen readers when
Forms mode is inactive.
TextArea control Use the Home or Page Down key to move to the beginning of a line. Use
the End or Page Up key to move to the end of a line.
TextInput control Use the Home or Page Down key to move to the beginning of a line. Use
the End or Page Up key to move to the end of a line.
TitleWindow A screen reader announces the TitleWindow control only when Forms
container mode is inactive.
Tree control Press the Up and Down Arrow keys to move between items in a Tree
control. To open a group, press the Right Arrow key or Spacebar. To
close a group, press the Left Arrow key or Spacebar. For more
information on keyboard navigation, see “Editing a node label at run
time” on page 498 and “Tree user interaction” on page 498.
<mx:Script>
<![CDATA[
import mx.core.Container;
import mx.core.EdgeMetrics;
[Bindable]
public var cards: Array = [
{label:"Visa", data:1},
{label:"Master Card", data:2},
{label:"American Express", data:3} ];
[Bindable]
public var selectedItem:Object;
[Bindable]
public var forListDP:Array = [
{label:'Apple', data:10.00},
{label:'Banana', data:15.00},
{label:'Melon', data:3.50},
{label:'Kiwi', data:7.65},
{label:'123', data:12.35 },
{label:'some', data:10.01 }];
target = target.parent;
}
Modifying these properties has no effect by itself. You must also use the
Accessibility.updateProperties() method to inform screen reader users of Flash Player
content changes. Calling this method causes Flash Player to re-examine all accessibility
properties, update property descriptions for the screen reader, and, if necessary, send events to
the screen reader that indicate changes occurred.
When updating the accessibility properties of multiple objects at once, you must include only
a single call to the Accessiblity.updateProperties() method. (Excessive updates to the
screen reader can cause some screen readers to become too verbose.)
PART 5
1423
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
CHAPTER 40
Contents
Using HTTPService components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1425
Using WebService components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1436
Using RemoteObject components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1447
Explicit parameter passing and parameter binding. . . . . . . . . . . . . . . . . . . . . . . . . . 1454
Handling results as XML with the e4x result format . . . . . . . . . . . . . . . . . . . . . . . . . 1468
1425
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Working with PHP and SQL data
You can use a Flex HTTPService component in conjunction with PHP and a SQL database
management system to display the results of a database query in a Flex application and insert
data into a database. You can call a PHP page with GET or POST to perform a database
query. You can then format the query result data in an XML structure and return the XML
structure to the Flex application in the HTTP response. When the result has been returned to
the Flex application, you can display it in one or more user interface controls.
MXML code
The Flex application in the following example calls a PHP page with the POST method. The
PHP page queries a MySQL database table called users. It formats the query results as XML
and returns the XML to the Flex application where it bound to the dataProvider property of
a DataGrid control and displayed in the DataGrid control. The Flex application also sends
the username and email address of new users to the PHP page, which performs an insert into
the user database table.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
xmlns="*" creationComplete="send_data()">
<mx:Script>
<![CDATA[
private function send_data():void {
userRequest.send();
}
]]>
</mx:Script>
<mx:Form x="22" y="10" width="493">
<mx:HBox>
<mx:Label text="Username"/>
<mx:TextInput id="username"/>
</mx:HBox>
<mx:HBox>
<mx:Label text="Email Address"/>
<mx:TextInput id="emailaddress"/>
</mx:HBox>
<mx:Button label="Submit" click="send_data()"/>
</mx:Form>
<mx:DataGrid id="dgUserRequest" x="22" y="128"
dataProvider="{userRequest.lastResult.users.user}">
<mx:columns>
<mx:DataGridColumn headerText="User ID" dataField="userid"/>
<mx:DataGridColumn headerText="User Name" dataField="username"/>
</mx:columns>
</mx:DataGrid>
<mx:TextInput x="22" y="292" id="selectedemailaddress"
The HTTPService’s send() method makes the call to the PHP page. This call is made in the
send_data() method in the Script block of the MXML file.
The resultFormat property of the HTTPService component is set to object, so the data is
sent back to the Flex application as a graph of ActionScript Objects. This is the default value
for the resultFormat property. Alternatively, you can use a resultFormat of e4x to return
data as an XMLList object on which you can perform ECMScript for XML (E4X) operations.
Switching the resultFormat property to e4x requires just the following minor changes to the
MXML code. Note that you do not include the root node of the XML structure in the dot
notation when binding to the DataGrid when the result format is e4x. The XML returned in
this example contains no namespace information; for information about working with XML
that does contain namespaces, see “Handling results as XML with the e4x result format”
on page 1468.
...
<mx:DataGrid id="dgUserRequest" x="22" y="128"
dataProvider="{userRequest.lastResult.user}">
...
<mx:HTTPService id="userRequest" url="http://server/myproj/
request_post2.php" useProxy="false" method="POST" resultFormat="e4x">
...
When using the e4x result format, you can optionally bind the lastResult property to an
XMLListCollection object and then bind that object to the DataGrid.dataProvider property,
as the following code snippet shows:
...
<mx:XMLListCollection id="xc"
source="{userRequest.lastResult.user}"/>
PHP code
This application calls the following PHP page. It is this PHP code that performs SQL
database inserts and queries, and returns query results to the Flex application in an XML
structure.
<html>
<head>
<title>PHP Test</title>
</head>
<body>
<?php
define( "DATABASE_SERVER", "servername" );
define( "DATABASE_USERNAME", "username" );
define( "DATABASE_PASSWORD", "password" );
define( "DATABASE_NAME", "sample" );
mysql_select_db( DATABASE_NAME );
$Return = "<users>";
MXML code
The Flex application in the following example calls a ColdFusion page with the POST
method. The ColdFusion page queries a MySQL database table called users. It formats the
query results as XML and returns the XML to the Flex application where it bound to the
dataProvider property of a DataGrid control and displayed in the DataGrid control. The
Flex application also sends the username and email address of new users to the ColdFusion
page, which performs an insert into the user database table.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*"
layout="absolute" creationComplete="userRequest.send()">
<mx:Form x="22" y="10" width="493">
<mx:HBox>
SQL script
The ColdFusion code for this application uses the a database table called users in a MySQL
database called sample. The following MySQL script creates the table:
CREATE TABLE `users` (
`userid` int(10) unsigned NOT NULL auto_increment,
`username` varchar(255) collate latin1_general_ci NOT NULL,
`emailaddress` varchar(255) collate latin1_general_ci NOT NULL,
PRIMARY KEY (`userid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci
AUTO_INCREMENT=3 ;
ColdFusion code
This application calls the following ColdFusion page. It is this ColdFusion code that performs
SQL database inserts and queries, and returns query results to the Flex application. The
ColdFusion page uses the cfquery tag to insert data into the database and query the database,
and the cfxml tag to format the query results in an XML structure.
<cfprocessingdirective pageencoding = "utf-8" suppressWhiteSpace = "Yes">
<cfif isDefined("username") and isDefined("emailaddress") and username NEQ
"">
<cfquery name="addempinfo" datasource="sample">
INSERT INTO users (username, emailaddress) VALUES (
<cfqueryparam value="#username#" cfsqltype="CF_SQL_VARCHAR"
maxlength="255">,
<cfqueryparam value="#emailaddress#" cfsqltype="CF_SQL_VARCHAR"
maxlength="255"> )
</cfquery>
</cfif>
<cfquery name="alluserinfo" datasource="sample">
SELECT userid, username, emailaddress FROM users
</cfquery>
<cfxml variable="userXML">
<users>
<cfloop query="alluserinfo">
<cfoutput>
<user>
MXML code
The Flex application in the following example calls a JSP page that retrieves data from a SQL
database. It formats database query results as XML and returns the XML to the Flex
application where it bound to the dataProvider property of a DataGrid control and
displayed in the DataGrid control.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:DataGrid dataProvider="{srv.lastResult.catalog.product}"
width="100%" height="100%"/>
</mx:Application>
The HTTPService’s send() method makes the call to the JSP page. This call is made in the
click event of the Button in the MXML file.
JSP code
The following example shows the JSP page used in this application. This JSP page does not
call a database directly. It gets its data from a Java class called ProductService, which in turn
uses a Java class called Product to represent individual products.
<%@page import="flex.samples.product.ProductService,
flex.samples.product.Product,
java.util.List"%>
<?xml version="1.0" encoding="utf-8"?>
<catalog>
<%
ProductService srv = new ProductService();
List list = null;
list = srv.getProducts();
Product product;
for (int i=0; i<list.size(); i++)
{
product = (Product) list.get(i);
%>
<product productId="<%= product.getProductId()%>">
Looking at an application
This topics shows sample code for an application that uses a WebService component to call
web service operations.
<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
WSDL document
The following example shows the WSDL document that defines the web service’s API:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://flexapp" xmlns:apachesoap="http:/
/xml.apache.org/xml-soap" xmlns:impl="http://flexapp" xmlns:intf="http:/
/flexapp" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns1="http://rpc.xml.coldfusion" xmlns:wsdl="http://
schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/
wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!--WSDL created by ColdFusion version 8,0,0,171651-->
<wsdl:types>
<schema targetNamespace="http://rpc.xml.coldfusion" xmlns="http://
www.w3.org/2001/XMLSchema">
<import namespace="http://flexapp"/>
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<complexType name="CFCInvocationException">
<sequence/>
</complexType>
<complexType name="QueryBean">
<sequence>
<element name="columnList" nillable="true"
type="impl:ArrayOf_xsd_string"/>
<element name="data" nillable="true"
type="impl:ArrayOfArrayOf_xsd_anyType"/>
</sequence>
</complexType>
</schema>
<schema targetNamespace="http://flexapp" xmlns="http://www.w3.org/2001/
XMLSchema">
<import namespace="http://rpc.xml.coldfusion"/>
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<complexType name="ArrayOf_xsd_string">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
</restriction>
</complexContent>
</complexType>
<complexType name="ArrayOfArrayOf_xsd_anyType">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:anyType[][]"/>
</restriction>
</complexContent>
</complexType>
</schema>
</wsdl:types>
<wsdl:message name="CFCInvocationException">
Tag Description
<binding> Specifies the protocol that clients, such as Flex applications, use to
communicate with a web service. Bindings exist for SOAP, HTTP GET, HTTP
POST, and MIME. Flex supports the SOAP binding only.
<fault> Specifies an error value that is returned as a result of a problem processing a
message.
<input> Specifies a message that a client, such as a Flex application, sends to a web
service.
<message> Defines the data that a web service operation transfers.
<operation> Defines a combination of <input>, <output>, and <fault> tags.
<output> Specifies a message that the web service sends to a web service client, such as
a Flex application.
<port> Specifies a web service endpoint, which specifies an association between a
binding and a network address.
<portType> Defines one or more operations that a web service provides.
<service> Defines a collection of <port> tags. Each service maps to one <portType> tag
and specifies different ways to access the operations in that <portType> tag.
<types> Defines data types that a web service's messages use.
The style property of the associated <soap:binding> tag determines the operation style. In
this example, the style is document.
To create the QName object in the first parameter of the SOAPHeader() method, you use the
following constructor:
QName(uri:String, localName:String)
The addSimpleHeader() method is a shortcut for a single name-value SOAP header. When
you use the addSimpleHeader() method, you create SOAPHeader and QName objects in
parameters of the method. The addSimpleHeader() method has the following signature:
addSimpleHeader(qnameLocal:String, qnameNamespace:String,
headerName:String, headerValue:Object):void
<!-- The value of the destination property is for demonstration only and
is not a real destination. -->
<mx:Script>
<![CDATA[
import mx.rpc.*;
import mx.rpc.soap.SOAPHeader;
</mx:Application>
// Redirect all service operations to the URL received in the login result.
serviceName.endpointURI=newServiceURL;
}
...
A web service that requires you to pass security credentials, might also return an identifier that
you must attach in a SOAP header for subsequent requests; for more information, see
“Working with SOAP headers” on page 1443.
Looking at an application
This topics shows sample code for an application that uses a RemoteObject component.
MXML code
The Flex application in the following example uses a RemoteObject component to call a
ColdFusion Component. The ColdFusion Component queries a MySQL database table
called users. It returns the query result to the Flex application where it is bound to the
dataProvider property of a DataGrid control and displayed in the DataGrid control. The
Flex application also sends the username and email address of new users to the ColdFusion
Component, which performs an insert into the user database table.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*"
layout="absolute"
creationComplete="userRequest.returnRecords()">
<mx:Form x="22" y="10" width="493">
<mx:HBox>
<mx:Label text="Username"/>
<mx:TextInput id="username"/>
</mx:HBox>
<mx:HBox>
<mx:Label text="Email Address"/>
<mx:TextInput id="emailaddress"/>
</mx:HBox>
<mx:Button label="Submit" click="clickHandler()"/>
</mx:Form>
<mx:DataGrid id="dgUserRequest" x="22" y="128">
<mx:columns>
<mx:DataGridColumn headerText="User ID" dataField="userid"/>
<mx:DataGridColumn headerText="User Name" dataField="username"/>
</mx:columns>
</mx:DataGrid>
<mx:TextInput x="22" y="292" id="selectedemailaddress"
text="{dgUserRequest.selectedItem.emailaddress}"/>
<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
</mx:Application>
In this application, the RemoteObject component’s destination property is set to
Coldfusion and the source property is set to the fully qualified name of the ColdFusion
Component.
In contrast, when working with LiveCycle Data Services ES, you specify a fully qualified class
name in the source property of a Remoting Service destination in a LiveCycle Data Services
ES configuration file, which by default is the remoting-config.xml file. You specify the name
of the destination in the RemoteObject component’s destination property. The destination
class also must have a no-args constructor. You can optionally configure a destination this way
when working with ColdFusion instead of using the the source property on the
RemoteObject component.
[Bindable]
public var empList:Object;
public var employeeRO:RemoteObject;
On the Java side, the getHelloData() method could easily encapsulate everything necessary
to call a business method on an EJB. The Java method in the following example performs the
following actions:
■ Creates new initial context for calling the EJB
■ Performs a JNDI lookup that gets an EJB home object
■ Calls the EJB home object's create() method
■ Calls the EJB's sayHello() method
...
public void getHelloData() {
try{
InitialContext ctx = new InitialContext();
PortableRemoteObject.narrow(obj, HelloHome.class);
<mx:RemoteObject
id="employeeRO"
destination="SalaryManager"
result="empList=event.result"
fault="Alert.show(event.fault.faultString, 'Error');"/>
<mx:Script>
<![CDATA[
public function callService():void {
// Cancel all previous pending calls.
myService.cancel();
<mx:HTTPService
id="myService"
destination="Dest"
useProxy="true"/>
<!-- HTTP service call with a send() method that takes a variable as its
parameter. The value of the variable is an Object. -->
<mx:Button click="myService.send({param1: 'val1'});"/>
<!-- HTTP service call with an object as a send() method parameter that
provides query parameters. -->
<mx:Button click="callService();"/>
</mx:Application>
If argument tags inside an <mx:arguments> tag have the same name, service calls fail if
the remote method is not expecting an Array as the only input source. There is no
warning about this when the application is compiled.
You can bind data to a RemoteObject component’s method parameters. You reference the tag
names of the parameters for data binding and validation.
The following example shows a method with two parameters bound to the text properties of
TextInput controls. A PhoneNumberValidator validator is assigned to arg1, which is the
name of the first argument tag.
<?xml version="1.0"?>
<!-- fds\rpc\ROParamBind1.mxml. -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:RemoteObject
id="ro"
destination="roDest">
<mx:method name="setData">
<mx:arguments>
<arg1>{text1.text}</arg1>
<arg2>{text2.text}</arg2>
</mx:arguments>
</mx:method>
</mx:RemoteObject>
<mx:TextInput id="text1"/>
<mx:TextInput id="text2"/>
<mx:PhoneNumberValidator source="{ro.setData.arguments}"
property="arg1"/>
</mx:Application>
Flex sends the argument tag values to the method in the order that the MXML tags specify.
<mx:HBox>
<mx:Label text="Select a department:"/>
<mx:ComboBox id="dept" width="150">
<mx:dataProvider>
<mx:ArrayCollection>
<mx:source>
<mx:Object label="Engineering" data="ENG"/>
<mx:Object label="Product Management" data="PM"/>
<mx:Object label="Marketing" data="MKT"/>
</mx:source>
</mx:ArrayCollection>
</mx:dataProvider>
</mx:ComboBox>
<mx:Button label="Get Employee List"
click="employeeRO.getList.send()"/>
</mx:HBox>
<mx:DataGrid dataProvider="{employeeAC}" width="100%">
<mx:columns>
<mx:DataGridColumn dataField="name" headerText="Name"/>
<mx:DataGridColumn dataField="phone" headerText="Phone"/>
<mx:DataGridColumn dataField="email" headerText="Email"/>
<mx:HTTPService
id="employeeSrv"
url="employees.jsp">
<mx:request>
<deptId>{dept.selectedItem.data}</deptId>
</mx:request>
</mx:HTTPService>
<mx:ArrayCollection
id="employeeAC"
source=
"{ArrayUtil.toArray(employeeSrv.lastResult.employees.employee)}"/>
<mx:HBox>
<mx:Label text="Select a department:"/>
<mx:ComboBox id="dept" width="150">
<mx:dataProvider>
<mx:ArrayCollection>
<mx:source>
<mx:Object label="Engineering" data="ENG"/>
<mx:Object label="Product Management" data="PM"/>
<mx:Object label="Marketing" data="MKT"/>
</mx:source>
</mx:ArrayCollection>
</mx:dataProvider>
</mx:ComboBox>
<mx:Button label="Get Employee List" click="employeeSrv.send();"/>
</mx:HBox>
<mx:WebService
id="employeeWS"
destination="wsDest"
showBusyCursor="true"
fault="Alert.show(event.fault.faultString)">
<mx:operation name="getList">
<mx:request>
<deptId>{dept.selectedItem.data}</deptId>
</mx:request>
</mx:operation>
</mx:WebService>
<mx:ArrayCollection
id="employeeAC"
source="{ArrayUtil.toArray(employeeWS.getList.lastResult)}"/>
<mx:HBox>
<mx:Label text="Select a department:"/>
<mx:ComboBox id="dept" width="150">
<mx:dataProvider>
<mx:ArrayCollection>
<mx:source>
<mx:Object label="Engineering" data="ENG"/>
<mx:Object label="Product Management" data="PM"/>
<mx:Object label="Marketing" data="MKT"/>
</mx:source>
</mx:ArrayCollection>
</mx:dataProvider>
</mx:ComboBox>
<mx:Button label="Get Employee List"
click="employeeWS.getList.send()"/>
</mx:HBox>
<mx:DataGrid dataProvider="{employeeAC}" width="100%">
If you want to use E4X syntax on service results, you must set the resultFormat property
of your HTTPService or WebService component to e4x. The default value is object.
Because this soap:Body contains namespace information, if you set the resultFormat
property of the WebService operation to e4x, you must create a namespace object for the
http://ws.invesbot.com/ namespace. The following example shows an application that does
that:
<?xml version="1.0"?>
<!-- fds\rpc\WebServiceE4XResult1.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*"
pageTitle="Test" >
<mx:Script>
<![CDATA[
import mx.controls.Alert;
private namespace invesbot = "http://ws.invesbot.com/";
use namespace invesbot;
]]>
</mx:Script>
<mx:WebService
id="WS"
wsdl="http://server.com/stockservice?wsdl"
fault="Alert.show(event.fault.faultString), 'Error'">
<mx:operation name="GetQuote" resultFormat="e4x">
<mx:request>
<symbol>ADBE</symbol>
</mx:request>
</mx:operation>
</mx:WebService>
<mx:HBox>
<mx:Button label="Get Quote" click="WS.GetQuote.send()"/>
<mx:Text
text="{WS.GetQuote.lastResult.GetQuoteResult.StockQuote.Price}"
/>
</mx:HBox>
</mx:Application>
text="{WS.GetQuote.lastResult.invesbot::GetQuoteResult.StockQuote.Price}"
/>
</mx:HBox>
</mx:Application>
You use E4X syntax to access elements and attributes of the XML that is returned in a
lastResult object. You use different syntax, depending on whether there is a namespace or
namespaces declared in the XML.
The previous code returns xxx for the following XML document:
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<Description>
<value>xxx</value>
</Description>
</RDF>
Any namespace
The following example shows how to get an element or attribute value when any namespace is
specified on the element or attribute:
var attributes:XMLList = XML(event.result).*::Description.*::value;
The previous code returns xxx for either one of the following XML documents:
XML document one:
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description>
<rdf:value>xxx</rdf:xxx>
</rdf:Description>
</rdf:RDF>
XML document two:
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cm="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<cm:Description>
<rdf:value>xxx</rdf:xxx>
</cm:Description>
</rdf:RDF>
Specific namespace
The following example shows how to get an element or attribute value when the declared rdf
namespace is specified on the element or attribute:
var rdf:Namespace = new Namespace("http://www.w3.org/1999/02/22-rdf-syntax-
ns#");
var attributes:XMLList = XML(event.result).rdf::Description.rdf::value;
The following example shows an alternate way to get an element or attribute value when the
declared rdf namespace is specified on an element or attribute:
namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
use namespace rdf;
var attributes:XMLList = XML(event.result).rdf::Description.rdf::value;
The previous code also returns xxx for the following XML document:
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description>
<rdf:value>xxx</rdf:xxx>
</rdf:Description>
</rdf:RDF>
CHAPTER 41
Representing Data 41
This topic describes data representation, which is a combination of features that provides a
powerful way to validate, format, and store data, and pass data between objects.
Contents
About data representation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1473
1473
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The following steps describe a simple scenario in which a user provides input data and
requests information in an Adobe Flex application:
1. The user enters data in input fields and submits a request by clicking a Button control.
2. (Optional) Data binding passes data to a data model object, which provides intermediate
data storage. This allows data to be manipulated and passed to other objects in the
application.
3. (Optional) One or more data validator objects validate the request data. Validator objects
check whether the data meets specific criteria.
4. The data is passed to a server-side object.
5. The server-side object processes the request and returns data or a fault object if a valid result
cannot be returned.
6. (Optional) Data binding passes data to a data model object, which provides intermediate
data storage. This allows data to be manipulated and passed to other objects in the
application.
7. (Optional) One or more data formatter objects format result data for display in the user
interface.
8. Data binding passes data into user interface controls for display.
Client tier
1 User interface 9
UI controls UI controls
input data/send request display result data
3 7
Data validators Data model object
Ex: Check if ZIP code is valid. Intermediate data storage.
4 6
Request Result
Client-side data service object
5
RPC service implementation
Resource tier
Server tier
For more information, see Chapter 42, “Binding Data,” on page 1481.
Data models
The data model feature lets you store data in client-side objects. A data model is an
ActionScript object that contains properties for storing data, and that optionally contains
methods for additional functionality. Data models are useful for partitioning the user interface
and data in an application.
You can use the data binding feature to bind user interface data into a data model. You can
also use the data binding feature to bind data from a data service to a data model.
You can define a simple data model in an MXML tag. When you require functionality beyond
storage of untyped data, you can use an ActionScript class as a data model.
Data validation
The data validation feature lets you ensure that data meets specific criteria before the
application uses the data. Data validators are ActionScript objects that check whether data in a
component is formatted correctly. You can apply a data validator to a property of any
component. For models in a remote procedure call (RPC) component declaration, properties
to which a validator component is applied are validated just before the request is sent to an
RPC service destination. Only valid requests are sent.
<mx:Model id="zipModel">
<root>
<zip>{input.text}</zip>
</root>
</mx:Model>
Data formatting
The data formatting feature lets you change the format of data before displaying it in a user
interface control. For example, when a data service returns a string that you want to display in
the (xxx)xxx-xxxx phone number format, you can use a formatter component to ensure that
the string is reformatted before it is displayed.
A data formatter component is an object that formats raw data into a customized string. You
can use data formatter components with data binding to reformat data that is returned from a
data service.
<!-- Trigger the formatter while populating a string with data. -->
<mx:TextInput
text="Your order shipped on
{StandardDateFormat.format(myService.purchase.result.date)}"/>
</mx:Application>
For more information about data formatters, see Chapter 45, “Formatting Data,” on
page 1575.
CHAPTER 42
Binding Data 42
This topic describes data binding, which lets you pass data between client-side objects in an
Adobe Flex application. Binding automatically copies the value of a property of a source
object to a property of a destination object when the source property changes. Binding lets
you pass data between the different layers of the application, such as the user interface, data
models, and data services.
Contents
About data binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1481
Data binding examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1486
Binding to functions, Objects and arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1489
Using ActionScript in data binding expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . .1499
Using an E4X expression in a data binding expression . . . . . . . . . . . . . . . . . . . . . .1502
Defining data bindings in ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1506
Using the Bindable metadata tag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1509
Considerations for using the binding feature . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1514
1481
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Adobe Flex provides three ways to specify data binding: the curly braces ({}) syntax in
MXML, the <mx:Binding> tag in MXML, and the BindingUtils methods in ActionScript.
The following example uses the curly braces ({}) syntax to show a Text control that gets its
data from a TextInput control’s text property:
<?xml version="1.0"?>
<!-- binding/BasicBinding.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:TextInput id="myTI"/>
<mx:Text id="myText" text="{myTI.text}"/>
</mx:Application>
The property name inside the curly braces is the source property of the binding expression.
When the value of the source property changes, Flex copies the current value of the source
property, myTI.text, to the destination property, the Text control’s text property.
You can include ActionScript code and E4X expressions as part of the data binding
expressions, as the following example shows:
<?xml version="1.0"?>
<!-- binding/BasicBindingWithAS.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:TextInput id="myTI"/>
<mx:Text id="myText" text="{myTI.text.toUpperCase()}"/>
</mx:Application>
In this example, you use the ActionScript method String.toUpperCase() to convert the
text in the source property to upper case when Flex copies it to the destination property. For
more information, see “Using ActionScript in data binding expressions” on page 1499 and
“Using an E4X expression in a data binding expression” on page 1502.
You can use the <mx:Binding> tag as an alternative to the curly braces syntax. When you use
the <mx:Binding> tag, you provide a source property in the <mx:Binding> tag’s source
property and a destination property in its destination property. The following example uses
the <mx:Binding> tag to define a data binding from a TextInput control to a Text control:
<?xml version="1.0"?>
<!-- binding/BasicBindingMXML.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:TextInput id="myTI"/>
<mx:Text id="myText"/>
<mx:Script>
<![CDATA[
import mx.binding.utils.*;
<mx:TextInput id="myTI"/>
<mx:Text id="myText" preinitialize="initBindingHandler();"/>
</mx:Application>
In this example, you use the static BindingUtils.bindProperty() method to define the
binding. You can also use the BindingUtils.bindSetter() method to define a binding to a
function. For more information, see “Defining data bindings in ActionScript” on page 1506.
Notice in this example that you use the preinitialize event to define the data biding. This
is necessary because Flex triggers all data bindings at application startup when the source
object dispatches the initialize event. For more information, see “When data binding
occurs” on page 1483.
If you omit the event name, Flex automatically creates an event named propertyChange, and
Flex dispatches that event when the property changes to trigger any data bindings that use the
property as a data-binding source. If you specify the event name, it is your responsibility to
dispatch the event when the source property changes. For more information and examples of
using the [Bindable] metadata tag, see “Using the Bindable metadata tag” on page 1509.
The following example makes the maxFontSize and minFontSize properties that you
defined as variables usable as the sources for data bindings expressions:
<?xml version="1.0"?>
<!-- binding/PropertyBinding.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
// Define public vars for tracking font size.
[Bindable]
public var maxFontSize:Number = 15;
[Bindable]
public var minFontSize:Number = 5;
]]>
</mx:Script>
<mx:Text text="{maxFontSize}"/>
<mx:Text text="{minFontSize}"/>
If you omit the [Bindable] metadata tag, the Flex compiler issues a warning stating that
the data binding mechanism cannot detect changes to the property.
<!-- Data model stores registration data that user enters. -->
<mx:Model id="reg">
<registration>
<name>{fullname.text}</name>
<email>{email.text}</email>
<phone>{phone.text}</phone>
<zip>{zip.text}</zip>
<ssn>{ssn.text}</ssn>
</registration>
</mx:Model>
<mx:Model id="mod1">
<data>
<part>{input1.text}</part>
</data>
</mx:Model>
<mx:Model id="mod2">
<data>
<part>{input1.text}</part>
</data>
</mx:Model>
<mx:Label text="{mod1.part}"/>
<mx:Label text="{mod2.part}"/>
</mx:Application>
<mx:TextInput id="input1"/>
<mx:TextInput id="input2"/>
<mx:Script>
<![CDATA[
import flash.events.Event;
<!-- Use the function as the source of a data binding expression. -->
<mx:TextArea id="myTA" text="{isEnabled()}"/>
Binding to Objects
When you make an Object the source of a data binding expression, the data binding occurs
when the Object is updated, or when a reference to the Object is updated, but not when an
individual field of the Object is updated.
In the following example, you create subclass of Object that defines two properties, stringProp
and intProp, but does not make the properties bindable:
package myComponents
{
// binding/myComponents/NonBindableObject.as
<mx:Script>
<![CDATA[
import myComponents.NonBindableObject;
[Bindable]
public var myObj:NonBindableObject = new NonBindableObject();
[Bindable]
public var anotherObj:NonBindableObject =
new NonBindableObject();
<mx:Script>
<![CDATA[
import myComponents.BindableObject;
[Bindable]
public var myObj:BindableObject = new BindableObject();
[Bindable]
public var anotherObj:BindableObject =
new BindableObject();
When defining a data binding expression that uses an array as the source of a data
binding expression, the array should be of type ArrayCollection because the
ArrayCollection class dispatches an event when the array or the array elements change
to trigger data binding. For example, a call to ArrayCollection.addItem(),
ArrayCollection.addItemAt(), ArrayCollection.removeItem(), and
ArrayCollection.removeItemAt() all trigger data binding.
The Array class does not dispatch an event when it changes and, therefore, does not
trigger data binding.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var myAC:ArrayCollection = new ArrayCollection([
"One", "Two", "Three", "Four"]);
[Bindable]
public var myAC2:ArrayCollection = new ArrayCollection([
"Uno", "Dos", "Tres", "Quatro"]);
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var myAC:ArrayCollection = new ArrayCollection([
"One", "Two", "Three", "Four"]);
[Bindable]
public var myAC2:ArrayCollection = new ArrayCollection([
"Uno", "Dos", "Tres", "Quatro"]);
]]>
</mx:Script>
<mx:Button id="button1"
label="Change Element"
click="myAC[0]='new One'"/>
<mx:Button id="button2"
label="Change ArrayCollection"
click="myAC=myAC2"/>
</mx:Application>
<mx:Model id="myModel">
<myModel>
<!-- Perform simple property binding. -->
<a>{nameInput.text}</a>
<!-- Perform string concatenation. -->
<b>This is {nameInput.text}</b>
<!-- Perform a calculation. -->
<c>{(Number(numberInput.text)) * 6 / 7}</c>
<!-- Perform a conditional operation using a ternary operator. -->
<d>{(isMale.selected) ? "Mr." : "Ms."} {nameInput.text}</d>
</myModel>
</mx:Model>
<mx:Form>
<mx:FormItem label="Last Name:">
<mx:TextInput id="nameInput"/>
</mx:FormItem>
<mx:FormItem label="Select sex:">
<mx:RadioButton id="isMale"
label="Male"
groupName="gender"
selected="true"/>
<mx:RadioButton id="isFemale"
label="Female"
groupName="gender"/>
</mx:FormItem>
<mx:FormItem label="Enter a number:">
<mx:TextInput id="numberInput" text="0"/>
</mx:FormItem>
</mx:Form>
<mx:Text
text="{'Calculation: '+numberInput.text+' * 6 / 7 = '+myModel.c}"/>
<mx:Text text="{'Conditional: '+myModel.d}"/>
</mx:Application>
<mx:Script>
<![CDATA[
public function whatDogAte():String {
return "homework";
}
]]>
</mx:Script>
<mx:Binding
source="'The dog ate my '+ whatDogAte()"
destination="field1.text"/>
<mx:Binding
source="{'The dog ate my '+ whatDogAte()}"
destination="field2.text"/>
<mx:Binding
source="The dog ate my {whatDogAte()}"
destination="field3.text"/>
<mx:TextArea id="field1"/>
<mx:TextArea id="field2"/>
<mx:TextArea id="field3"/>
</mx:Application>
The source property in the following example is not valid because it is not an ActionScript
expression:
<mx:Binding source="The dog ate my homework" destination="field1.text"/>
<mx:Script>
<![CDATA[
[Bindable]
public var xdata:XML = <order>
<item id = "3456">
<description>Big Screen Television</description>
<price>1299.99</price><quantity>1</quantity>
</item>
<item id = "56789">
<description>DVD Player</description>
<price>399.99</price>
<quantity>1</quantity>
</item>
</order>;
]]>
</mx:Script>
dataProvider="{xdata.item.(@id=='3456'||@id=='56789').description}"/>
</mx:Application>
<mx:Script>
<![CDATA[
[Bindable]
public var xdata:XML =
<order>
<item id = "3456">
<description>Big Screen Television</description>
<price>1299.99</price><quantity>1</quantity>
</item>
<item id = "56789">
<description>DVD Player</description>
<price>399.99</price>
<quantity>1</quantity>
</item>
</order>;
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.binding.utils.*;
import mx.events.FlexEvent;
<mx:Script>
<![CDATA[
import mx.binding.utils.*;
import mx.events.FlexEvent;
import mx.events.PropertyChangeEvent;
If you omit the event name, Flex automatically creates an event named propertyChange.
You can use the [Bindable] metadata tag in three places:
■ Before a public class definition.
The [Bindable] metadata tag makes usable as the source of a binding expression all
public properties that you defined as variables, and all public properties that are defined
by using both a setter and a getter method. In this case, [Bindable] takes no parameters,
as the following example shows:
[Bindable]
public class TextAreaFontControl extends TextArea {}
The Flex compiler automatically generates an event named propertyChange for all public
properties so that the properties can be used as the source of a data binding expression. In
this case, specifying the [Bindable] metadata tag with no event is the same as specifying
the following:
[Bindable(event="propertyChange")]
If the property value remains the same on a write, Flex does not dispatch the event or
update the property.
NOTE
When you use the [Bindable] metadata tag before a public class definition, it only
applies to public properties; it does not apply to private or protected properties, or to
properties defined in any other namespace. You must insert the [Bindable] metadata
tag before a nonpublic property to make it usable as the source for a data binding
expression.
■ Before a public, protected, or private property defined as a variable to make that specific
property support binding.
The Flex compiler automatically generates an event named propertyChange for the
property. If the property value remains the same on a write, Flex does not dispatch the
event or update the property.
You can also specify the event name, as the following example shows:
[Bindable(event="fooChanged")]
public var foo:String;
In this case, you are responsible for generating and dispatching the event, typically as part
of some other method of your class. You can specify a [Bindable] tag that includes the
event specification if you want to name the event, even when you already specified the
[Bindable] tag at the class level.
■ Before a public, protected, or private property defined by a getter or setter method.
You must define both a setter and a getter method to use the [Bindable] tag with the
property. If you define just a setter method, you create a write-only property that you
cannot use as the source of a data-binding expression. If you define just a getter method,
you create a read-only property that you can use as the source of a data-binding expression
without inserting the [Bindable] metadata tag. This is similar to the way that you can
use a variable, defined by using the const keyword, as the source for a data binding
expression.
The tag can have the following forms:
[Bindable]
public function set shortNames(val:Boolean):void {
...
}
The Flex compiler automatically generates an event named propertyChange for the
property. If the property value remains the same on a write, Flex does not dispatch the
event or update the property. To determine if the property value changes, Flex calls the
getter method to obtain the current value of the property.
// Get method.
public function get shortNames():Boolean {
...
}
In this case, you are responsible for generating and dispatching the event, typically in the
setter method, and Flex does not check to see if the old value and the new value are
different. You can specify a [Bindable] tag that includes the event specification to name
the event, even when you already specified the [Bindable] tag at the class level.
The following example makes the maxFontSize and minFontSize properties that you
defined as variables that can be used as the sources for data bindings:
// Define public vars for tracking font size.
[Bindable]
public var maxFontSize:Number = 15;
[Bindable]
public var minFontSize:Number = 5;
In the following example, you make a public property that you defined by using a setter and a
getter method that is usable as the source for data binding The [Bindable] metadata tag
includes the name of the event broadcast by the setter method when the property changes:
// Define private variable.
private var _maxFontSize:Number = 15;
[Bindable(event="maxFontSizeChanged")]
// Define public getter method.
public function get maxFontSize():Number {
return _maxFontSize;
}
In this example, the setter updates the value of the property, and then creates and dispatches
an event to invoke an update of the destination of the data binding.
In an MXML file, you can make all public properties that you defined as variables usable as
the source for data binding by including the [Bindable] metadata tag in an <mx:Metadata>
block, as the following example shows:
<mx:Metadata>
[Bindable]
</mx:Metadata>
You can also use the [Bindable] metadata tag in an <mx:Script> block in an MXML file to
make individual properties that you defined as variables usable as the source for a data binding
expression. Alternatively, you can use the [Bindable] metadata tag with properties that you
defined by using setter and getter methods.
<mx:Script>
<![CDATA[
You can have a fairly long bindable property chain, as the following example shows:
<mx:Text id="myText" text="{user.name.firstName.text}"/>
For the data binding mechanism to detect changes to the text property, only the text
property has to be bindable. However, if you want to assign a new value to any part of the
chain at runtime, every element in the chain must be bindable. Otherwise, modifying the
user, name, or firstName property at runtime results in the data binding mechanism no
longer being able to detect changes to the text property.
The host and chain arguments specify the source of the data binding expression. You can
define a data binding expression by using the bindProperty() method, as the following
example shows:
bindProperty(myText, ’text’, user, ["name","firstName","text"]);
■ Array elements cannot function as binding sources at run time. Arrays that are bound do
not stay updated if individual fields of a source Array change. Binding copies values
during instantiation after variables are declared in an <mx:Script> tag, but before event
listeners execute.
CHAPTER 43
Storing Data 43
This topic describes the data model feature, which you use to store data in an application.
Contents
About data models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1517
Defining a data model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1518
Specifying an external source for an <mx:Model> tag or <mx:XML> tag. . . . . . . . . 1522
Using validators with a data model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1524
Using a data model as a value object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1525
Binding data into an XML data model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1527
1517
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Defining a data model
You can define a data model in an MXML tag, an ActionScript function, or an ActionScript
class. In general, you should use MXML-based models for simple data structures, and use
ActionScript for more complex structures and client-side business logic.
NO TE
The <mx:Model> and <mx:XML> tags are Flex compiler tags and do not correspond directly
to ActionScript classes. The Adobe Flex Language Reference contains information about
these tags and other compiler tags. Click the Appendixes link on the main page in the
Adobe Flex Language Reference.
You can place an <mx:Model> tag or an <mx:XML> tag in a Flex application file or in an
MXML component file. The tag should have an id value, and it cannot be the root tag of an
MXML component.
You currently cannot use a node within an <mx:XML> data model as a binding source.
Class-based models
Using an ActionScript class as a model is a good option when you want to store complex data
structures with typed properties, or when you want to execute client-side business logic using
application data. Also, the type information in a class-based model is retained on the server
when the model is passed to a server-side data service.
The following example shows a model defined in an ActionScript class. This model is used to
store shopping cart items in an e-commerce application. It also provides business logic in the
form of methods for adding and removing items, getting an item count, and getting the total
price. For more information on ActionScript components, see Creating and Extending Flex
Components.
package
{
[Bindable]
public class ShoppingCart {
You can use properties of any recognized type in a class-based model. For example, you
could create an Employee class, and then define properties of type Employee in another
class that imports Employee.
You declare a class-based model as an ActionScript component tag in an MXML file, as the
following example shows:
<local:ShoppingCart id="cart" xmlns:local="*"/>
This component is in the same directory as the MXML file, as indicated by the XML
namespace value *. For more information about specifying the location of components, see
Creating and Extending Flex Components.
<?xml version="1.0"?>
<employees>
<employee>
<name>John Doe</name>
<phone>555-777-66555</phone>
<email>[email protected]</email>
<active>true</active>
</employee>
<employee>
<name>Jane Doe</name>
<phone>555-777-66555</phone>
<email>[email protected]</email>
<active>true</active>
</employee>
</employees>
<mx:Script>
<![CDATA[
[Bindable]
public var tent:Object;
]]>
</mx:Script>
<mx:Style>
.title{fontFamily:Arial;fontWeight:bold;color:#3D3D3D;fontSize:16pt;}
.flabelColor
{fontFamily:Arial;fontWeight:bold;color:#3D3D3D;fontSize:11pt}
.productSpec{fontFamily:Arial;color:#5B5B5B;fontSize:10pt}
</mx:Style>
<mx:HRule width="209"/>
CHAPTER 44
Validating Data 44
This topic describes the Adobe Flex data validation mechanism, which lets you validate the
data in an application. Flex provides predefined validators for many common types of user-
supplied data, such as date, number, and currency values.
You often use Flex validators with data models. For more information about data models, see
Chapter 43, “Storing Data,” on page 1517.
Contents
Validating data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1529
Using validators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1534
General guidelines for validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1552
Working with validation errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1555
Working with validation events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1559
Using standard validators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1562
Validating data
The data that a user enters in a user interface might or might not be appropriate to the
application. In Flex, you use a validator to ensure the values in the fields of an object meet
certain criteria. For example, you can use a validator to ensure that a user enters a valid phone
number value, to ensure that a String value is longer than a set minimum length, or ensure
that a ZIP code field contains the correct number of digits.
1529
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
In typical client-server environments, data validation occurs on the server after data is
submitted to it from the client. One advantage of using Flex validators is that they execute on
the client, which lets you validate input data before transmitting it to the server. By using Flex
validators, you eliminate the need to transmit data to and receive error messages back from the
server, which improves the overall responsiveness of your application.
N OTE
Flex validators do not eliminate the need to perform data validation on the server, but
provide a mechanism for improving performance by performing some data validation on
the client.
Flex includes a set of validators for common types of user input data, such as ZIP codes,
phone numbers, and credit card numbers. Flex includes the following validators:
■ Using the CreditCardValidator class
■ Using the CurrencyValidator class
■ Using the DateValidator class
■ Using the EmailValidator class
■ Using the NumberValidator class
■ Using the PhoneNumberValidator class
■ Using the RegExpValidator class
■ Using the SocialSecurityValidator class
■ Using the StringValidator class
■ Using the ZipCodeValidator class
About validators
You define validators using MXML or ActionScript. You declare a validator in MXML using
the <mx:Validator> tag or the tag for the appropriate validator type. For example, to declare
the standard PhoneNumberValidator validator, you use the <mx:PhoneNumberValidator>
tag, as the following example shows:
<?xml version="1.0"?>
<!-- validators\PNValidator.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<!-- Define the TextInput control for entering the phone number. -->
<mx:TextInput id="phoneInput"/>
<mx:TextInput id="zipCodeInput"/>
</mx:Application>
<mx:Script>
<![CDATA[
// Import PhoneNumberValidator.
import mx.validators.PhoneNumberValidator;
<!-- Define the TextInput control for entering the phone number. -->
<mx:TextInput id="phoneInput" creationComplete="createValidator();"/>
<mx:TextInput id="zipCodeInput"/>
</mx:Application>
<mx:ZipCodeValidator id="zipV"
source="{myZip}"
property="text"/>
<mx:TextInput id="phoneInput"/>
<mx:TextInput id="myZip"/>
</mx:Application>
In this example, you use the Flex ZipCodeValidator to validate the data entered in a TextInput
control. The TextInput control stores the input data in its text property.
Using validators
This section describes the basic process for using Flex validators. For information on specific
validator classes, see “Using standard validators” on page 1562.
<mx:ZipCodeValidator id="zipV"
source="{myZip}"
property="text"
trigger="{mySubmit}"
triggerEvent="click"/>
<mx:TextInput id="myZip"/>
<mx:Button id="mySubmit" label="Submit"/>
</mx:Application>
This example uses the trigger and triggerEvent properties of the ZipCodeValidator class
to associate an event with the validator. These properties have the following values:
trigger Specifies the component generating the event that triggers the validator. If omitted,
by default Flex uses the value of the source property.
<mx:ZipCodeValidator id="zipV"
source="{myZip}"
property="text"/>
<mx:TextInput id="myZip"/>
<mx:Button id="mySubmit" label="Submit"/>
</mx:Application>
By omitting the trigger and triggerEvent properties, Flex triggers the validator when the
TextInput control dispatches the valueCommit event. Flex controls dispatch the
valueCommit event when its values changes by user interaction or programmatically.
<!-- Define a data model for storing the phone number. -->
<mx:Model id="userInfo">
<phoneInfo>
<phoneNum>{phoneInput.text}</phoneNum>
</phoneInfo>
</mx:Model>
<!-- Define the TextInput control for entering the phone number. -->
<mx:TextInput id="phoneInput"/>
<mx:TextInput id="zipCodeInput"/>
</mx:Application>
You can use a validator along with a data binding to validate either the source or destination
of the data binding, as the following example shows:
<?xml version="1.0"?>
<!-- validators\ValTriggerWithDataBinding.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<!-- Define a data model for storing the phone number. -->
<mx:Model id="userInfo">
<phoneInfo>
<phoneNum>{phoneInput.text}</phoneNum>
</phoneInfo>
</mx:Model>
<!-- Define the TextInput control for entering the phone number. -->
<mx:TextInput id="phoneInput"/>
<mx:TextInput id="zipCodeInput"/>
</mx:Application>
This example uses a PhoneNumberValidator to validate the data entered in the TextInput
control. In this example, the following occurs:
■ You assign the validator to the source of the data binding.
■ You use the default event, valueCommit, on the TextInput control to trigger the validator.
This means the validator executes when the user removes focus from the TextInput
control by selecting the TextInput control for the ZIP code.
<!-- Define a data model for storing the phone number. -->
<mx:Model id="userInfo">
<phoneInfo>
<phoneNum>{phoneInput.text}</phoneNum>
</phoneInfo>
</mx:Model>
<!-- Define the TextInput control for entering the phone number. -->
<mx:TextInput id="phoneInput"/>
<mx:TextInput id="zipCodeInput"/>
</mx:Application>
In this example, you trigger the data validator using the valueCommit event of the TextInput
control, but assign the validator to a field of the data model, rather than to a property of the
TextInput control.
<!-- Define a data model for storing the phone number. -->
<mx:Model id="userInfo">
<user>
<phoneInfo>
<homePhoneNum>{homePhoneInput.text}</homePhoneNum>
<cellPhoneNum>{cellPhoneInput.text}</cellPhoneNum>
</phoneInfo>
</user>
</mx:Model>
<!-- Define the TextInput controls for entering the phone number. -->
<mx:Label text="Home Phone:"/>
<mx:TextInput id="homePhoneInput"/>
<mx:Script>
<![CDATA[
// Import ZipCodeValidator.
import mx.validators.ZipCodeValidator;
<mx:TextInput id="myZip"/>
<mx:Button label="Submit" click="performValidation();"/>
</mx:Application>
Notice that you are still using an event to trigger the performValidation() function that
creates and invokes the validator, but the event itself does not automatically invoke the
validator.
Any errors in the validator are shown on the associated component, just as if you had triggered
the validation directly by using an event.
<mx:Script>
<![CDATA[
if (vResult.type==ValidationResultEvent.VALID) {
// Validation succeeded.
myTA.text='OK';
}
else {
// Validation failed.
myTA.text='Fail';
}
}
]]>
</mx:Script>
<mx:TextInput id="myZip"/>
<mx:Button label="Submit" click="performValidation();"/>
<mx:TextArea id="myTA"/>
</mx:Application>
The ValidationResultEvent class has additional properties that you can use when processing
validation events. For more information, see “Working with validation events” on page 1559.
<mx:Script>
<![CDATA[
<mx:Model id="person">
<userInfo>
<zipCode>{zipCodeInput.text}</zipCode>
<phoneNumber>{phoneNumberInput.text}</phoneNumber>
</userInfo>
<mx:Form>
<!-- Collect input data -->
<mx:TextInput id="zipCodeInput"/>
<mx:TextInput id="phoneNumberInput"/>
</mx:Form>
<mx:Button label="Validate"
click="validateZipPhone();"/>
</mx:Application>
In this example, you use the predefined ZipCodeValidator and PhoneNumberValidator to
validate user information as the user enters it. Then, when the user clicks the Submit button
to submit the form, you validate that the ZIP code is actually within the specified area code of
the phone number.
<mx:Script>
<![CDATA[
import mx.validators.Validator;
<mx:Model id="person">
<userInfo>
<zipCode>{zipCodeInput.text}</zipCode>
<phoneNumber>{phoneNumberInput.text}</phoneNumber>
</userInfo>
</mx:Model>
<mx:Form>
<!-- Collect input data -->
<mx:TextInput id="zipCodeInput"/>
<mx:TextInput id="phoneNumberInput"/>
</mx:Form>
<mx:Button label="Validate"
click="Validator.validateAll(myValidators);"/>
</mx:Application>
<mx:Script>
<![CDATA[
import flash.events.Event;
<mx:ZipCodeValidator id="zipV"
triggerEvent=""/>
<mx:TextInput id="shippingZip"
focusOut="performValidation(event);"/>
<mx:TextInput id="billingZip"
focusOut="performValidation(event);"/>
</mx:Application>
In this example, you have two address areas for a customer: one for a billing address and one
for a shipping address. Both addresses have a ZIP code field, so you can reuse a single
ZipCodeValidator for both fields. The event listener for the focusOut event passes the field to
validate to the validate() method.
<mx:Script>
<![CDATA[
import flash.events.Event;
<mx:ZipCodeValidator id="zipV"
triggerEvent=""/>
<mx:TextInput id="shippingZip"
focusOut="performValidation(event);"/>
<mx:TextInput id="billingZip"
focusOut="performValidation(event);"/>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.events.ValidationResultEvent;
<mx:ZipCodeValidator id="zipUS"
domain="US Only"
listener="{zipInput}"/>
<mx:ZipCodeValidator id="zipCN"
domain="US or Canada"
listener="{zipInput}"/>
<mx:RadioButtonGroup id="country"/>
<mx:RadioButton groupName="country" label="US"/>
<mx:RadioButton groupName="country" label="Canada"/>
<mx:TextInput id="zipInput"/>
<mx:StringValidator id="reqV"
source="{inputA}"
property="text"
required="true"/>
<mx:TextInput id="inputA"/>
<mx:Button label="Submit"
click="reqV.validate();"/>
</mx:Application>
In this example, the StringValidator executes when the following occurs:
■ The TextInput control dispatches the valueCommit event. However, to dispatch that
event, the user must give the TextInput control focus, and then remove focus. If the user
never gives the TextInput control focus, the validator does not trigger, and Flex does not
recognize that the control is empty. Therefore, you must call the validate() method to
ensure that the validator checks for missing data.
■ The user clicks the Button control. The validator issues a validation error when the user
does not enter any data into the TextInput control. It also issues a validation error if the
user enters an invalid String value.
<mx:ZipCodeValidator id="zcVal"
source="{inputA}"
property="text"
required="true"
enabled="{enableV.selected}"/>
<mx:TextInput id="inputA"/>
<mx:TextInput/>
<mx:CheckBox id="enableV"
label="Validate input?"/>
</mx:Application>
In this example, you enable the validator only when the user selects the CheckBox control.
<mx:NumberValidator
source="{inputA}"
property="text"
minValue="{Number(inputMin.text)}"
maxValue="{Number(inputMax.text)}"/>
<mx:TextInput id="inputA"/>
<mx:TextInput id="inputMin" text="1"/>
<mx:TextInput id="inputMax" text="10"/>
</mx:Application>
In this example, you use data binding to configure the properties of the validators.
<mx:Script>
<![CDATA[
import mx.events.ValidationResultEvent;
vResult = lNameV.validate();
if (vResult.type==ValidationResultEvent.INVALID)
return;
<!-- Define the TextInput control for entering the phone number. -->
<mx:TextInput id="phoneInput"/>
<mx:TextInput id="zipCodeInput"/>
</mx:Application>
<!-- Define the TextInput control for entering the phone number. -->
<mx:TextInput id="phoneInput"/>
<mx:TextInput id="zipCodeInput"/>
</mx:Application>
In this example, the error message appears as light green.
Writing a value to the UIComponent.errorString property does not trigger the valid or
invalid events; it only changes the border color and displays the validation error
message.
For information on writing custom ToolTip controls, see Chapter 25, “Using ToolTips,” on
page 1033.
<mx:Script>
<![CDATA[
import mx.events.ValidationResultEvent;
private var vResult:ValidationResultEvent;
<mx:ZipCodeValidator id="zipV"
source="{zipInput}"
property="text"/>
<mx:Form>
<mx:FormItem label="Enter ZIP code">
<mx:TextInput id="zipInput"/>
</mx:FormItem>
<mx:FormItem label="Enter Country">
<mx:TextInput id="cntryInput"/>
</mx:FormItem>
</mx:Form>
<mx:ZipCodeValidator id="zipV"
source="{zipCodeInput}"
property="text"
listener="{errorMsg}"/>
<mx:TextInput id="zipCodeInput"/>
<mx:TextArea id="errorMsg"/>
</mx:Application>
<mx:Script>
<![CDATA[
<mx:TextInput id="phoneInput"
initialize="myCreationComplete(event);"
invalid="handleInvalidVal(event);"
valid="handleValidVal(event);"/>
<mx:TextInput id="zipInput"/>
</mx:Application>
<mx:Script>
<![CDATA[
]]>
</mx:Script>
<mx:ZipCodeValidator
source="{inputZip}" property="text"
valid="handleValid(event);"
invalid="handleValid(event);"/>
<mx:TextInput id="inputZip"/>
<mx:TextInput id="inputPn"/>
<mx:Button id="submitButton"
label="Submit"
enabled="false"
click="submitForm();"/>
</mx:Application>
In this example, the Button control is disabled until the TextInput field contains a valid ZIP
code. The type property of the event object is either ValidationResultEvent.VALID or
ValidationResultEvent.INVALID , based on the result of the validation.
Within the event listener, you can use all the properties of the ValidationResultEvent class,
including the following:
■ "American Express"
■ "Diners Club"
■ "Discover"
■ "MasterCard"
■ "Visa"
In ActionScript, you can use the following constants to set the cardTypeProperty property:
■ CreditCardValidatorCardType.AMERICAN_EXPRESS
■ CreditCardValidatorCardType.DINERS_CLUB
■ CreditCardValidatorCardType.DISCOVER
■ CreditCardValidatorCardType.MASTER_CARD
■ CreditCardValidatorCardType.VISA
<mx:CreditCardValidator id="ccV"
cardTypeSource="{cardTypeCombo.selectedItem}"
cardTypeProperty="data"
cardNumberSource="{cardNumberInput}"
cardNumberProperty="text"/>
<mx:Form id="creditCardForm">
<mx:FormItem label="Card Type">
<mx:ComboBox id="cardTypeCombo">
<mx:dataProvider>
<mx:Object label="American Express"
data="American Express"/>
<mx:Object label="Diners Club"
data="Diners Club"/>
<mx:Object label="Discover"
data="Discover"/>
<mx:Object label="MasterCard"
data="MasterCard"/>
<mx:Object label="Visa"
data="Visa"/>
</mx:dataProvider>
</mx:ComboBox>
</mx:FormItem>
<mx:FormItem label="Credit Card Number">
<mx:TextInput id="cardNumberInput"/>
</mx:FormItem>
<mx:FormItem>
<mx:Button label="Check Credit" click="ccV.validate();"/>
</mx:FormItem>
</mx:Form>
</mx:Application>
Object or multiple fields Use all of the following Flex associates error messages with
containing the day, properties to specify the the field specified by the daySource,
month, and year day, month, and year monthSource, and yearSource
inputs: daySource, properties, depending on the field that
dayProperty, monthSource, caused the validation error.
monthProperty, yearSource,
and yearProperty.
<mx:DateValidator id="dateV"
daySource="{dayInput}" dayProperty="text"
monthSource="{monthInput}" monthProperty="text"
yearSource="{yearInput}" yearProperty="text"/>
<mx:Form >
<mx:FormItem label="Month">
<mx:TextInput id="monthInput"/>
</mx:FormItem>
<mx:FormItem label="Day">
<mx:TextInput id="dayInput"/>
</mx:FormItem>
<mx:FormItem label="Year">
<mx:TextInput id="yearInput"/>
</mx:FormItem>
<mx:FormItem>
<mx:Button label="Check Date" click="dateV.validate();"/>
</mx:FormItem>
</mx:Form>
<!-- Alternate method for a single field containing the date. -->
<mx:Model id="alternateDate">
<dateInfo>
<date>{dateInput.text}</date>
</dateInfo>
</mx:Model>
<mx:DateValidator id="stringDateV"
source="{dateInput}" property="text"
inputFormat="dd/mm/yyyy"
allowedFormatChars="*#~/"/>
<mx:Form>
<mx:FormItem label="Date of Birth (dd/mm/yyyy)">
<mx:TextInput id="dateInput"/>
</mx:FormItem>
<mx:FormItem>
<mx:Button label="Check Date" click="stringDateV.validate();"/>
</mx:FormItem>
</mx:Form>
</mx:Application>
<mx:Form id="contactForm">
<mx:FormItem id="homePhoneItem" label="Home Phone">
<mx:TextInput id="homePhoneInput"/>
</mx:FormItem>
<mx:FormItem id="cellPhoneItem" label="Cell Phone">
<mx:TextInput id="cellPhoneInput"/>
</mx:FormItem>
<mx:FormItem id="emailItem" label="Email">
<mx:TextInput id="emailInput"/>
</mx:FormItem>
</mx:Form>
<mx:PhoneNumberValidator id="pnVHome"
source="{homePhoneInput}" property="text"/>
<mx:PhoneNumberValidator id="pnVCell"
source="{cellPhoneInput}" property="text"/>
<mx:EmailValidator id="emV"
source="{emailInput}" property="text"/>
</mx:Application>
The following example uses the NumberValidator class to ensure that an integer is between 1
and 10:
<?xml version="1.0"?>
<!-- validators\NumberExample.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Form >
<mx:FormItem
label="Number of Widgets (max 10 per customer)">
<mx:TextInput id="quantityInput"/>
</mx:FormItem>
<mx:FormItem >
<mx:Button label="Submit"/>
</mx:FormItem>
</mx:Form>
<mx:NumberValidator id="numV"
source="{quantityInput}" property="text"
minValue="1" maxValue="10" domain="int"/>
</mx:Application>
<mx:Form id="contactForm">
<mx:FormItem id="homePhoneItem" label="Home Phone">
<mx:TextInput id="homePhoneInput"/>
</mx:FormItem>
<mx:FormItem id="cellPhoneItem" label="Cell Phone">
<mx:TextInput id="cellPhoneInput"/>
</mx:FormItem>
<mx:FormItem id="emailItem" label="Email">
<mx:TextInput id="emailInput"/>
</mx:FormItem>
</mx:Form>
<mx:PhoneNumberValidator id="pnVHome"
source="{homePhoneInput}" property="text"/>
<mx:PhoneNumberValidator id="pnVCell"
source="{cellPhoneInput}" property="text"/>
<mx:EmailValidator id="emV"
source="{emailInput}" property="text"/>
</mx:Application>
<mx:Script>
<![CDATA[
import mx.events.ValidationResultEvent;
import mx.validators.*;
<mx:RegExpValidator id="regExpV"
source="{exp}" property="text"
flags="g"
expression="{source.text}"
valid="handleResult(event);"
invalid="handleResult(event);"/>
<mx:Form>
<mx:FormItem label="Search string">
<mx:TextInput id="exp"/>
</mx:FormItem>
<mx:FormItem label="Regular expression">
<mx:TextInput id="source" text="ABC\d"/>
</mx:FormItem>
<mx:FormItem label="Results">
<mx:TextArea id="myTA"/>
</mx:FormItem>
</mx:Form>
</mx:Application>
In this example, you specify the regular expression in the TextInput control named source,
and bind it to the expression property of the validator. You can modify the regular
expression by entering a new expression in the TextInput control. A value of g for the flags
property specifies to find multiple matches in the input field.
The event handler for the valid event writes to the TextArea control the index in the input
String and matching substring of all matches of the regular expression. The invalid event
handler clears the TextArea control.
<mx:Form id="identityForm">
<mx:FormItem id="ssnItem" label="Social Security Number">
<mx:TextInput id="ssnField"/>
</mx:FormItem>
<mx:FormItem id="licenseItem" label="Driver's License Number">
<mx:TextInput id="licenseInput"/> <!-- Not validated -->
</mx:FormItem>
</mx:Form>
<mx:SocialSecurityValidator id="ssV"
source="{ssnField}" property="text"/>
</mx:Application>
<mx:Form id="membershipForm">
<mx:FormItem id="fullNameItem" label="Full Name">
<!-- Not validated -->
<mx:TextInput id="fullNameInput"/>
</mx:FormItem>
<mx:FormItem id="userNameItem" label="Username">
<mx:TextInput id="userNameInput"/>
</mx:FormItem>
</mx:Form>
<mx:Form id="addressForm">
<mx:FormItem id="zipCodeItem" label="Zip Code">
<mx:TextInput id="zipInput"/>
</mx:FormItem>
<mx:FormItem id="submitArea">
<mx:Button label="Submit"/>
</mx:FormItem>
</mx:Form>
<mx:ZipCodeValidator id="zipV"
source="{zipInput}" property="text"
domain="US or Canada"/>
</mx:Application>
CHAPTER 45
Formatting Data 45
This topic describes how to use data formatters, user-configurable objects that format raw
data into a customized string. You often use formatters with data binding to create a
meaningful display of the raw data bound to a component. This can save you time by
automating data formatting tasks and by letting you easily change the formatting of fields
within your applications.
Contents
Using formatters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1575
Writing an error handler function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1577
Using the standard formatters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1579
Using formatters
Adobe Flex formatters are components that you use to format data into strings. Formatters
perform a one-way conversion of raw data to a formatted string. You typically trigger a
formatter just before displaying data in a text field. Flex includes standard formatters that let
you format currency, dates, numbers, phone numbers, and ZIP codes.
All Flex formatters are subclasses of the mx.formatters.Formatter class. The Formatter class
declares a format() method that takes a value and returns a String value.
For most formatters, when an error occurs, an empty string is returned and a string describing
the error is written to the formatter’s error property. The error property is inherited from
the Formatter class.
The following steps describe the general process for using a formatter:
1. Declare a formatter in your MXML code, specifying the appropriate formatting properties.
2. Call the formatter’s format() method within the curly braces ({ }) syntax for binding data,
and specify the value to be formatted as a parameter to the format() method.
1575
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The following example formats a phone number that a user inputs in an application using the
TextInput control:
<?xml version="1.0"?>
<!-- formatters\Formatter2TextFields.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
When a number is provided to the format() method as a String value, a negative sign is
recognized if it is a dash (-) immediately preceding the first number in the sequence. A
dash, space, and then a first number are not interpreted as a negative sign.
<mx:Script>
<![CDATA[
// Define variable to hold the price.
[Bindable]
private var todaysPrice:Number=4025;
]]>
</mx:Script>
The following examples show some of the ways strings can be parsed:
"12/31/98" or "12-31-98" or "1998-12-31" or "12/31/1998"
"Friday, December 26, 2005 8:35 am"
"Jan. 23, 1989 11:32:25"
The DateFormatter class parses strings from left to right. A date value should appear before
time and must be included. The time value is optional. A time signature of 0:0:0 is the Date
object’s default for dates that are defined without a time. Time zone offsets are not parsed.
D Day in month. While a single-letter pattern string for day is valid, you
typically use a two-letter pattern string.
Examples:
D=4
DD=04
DD=10
A am/pm indicator.
N Minute in hour.
Examples:
N=3
NN = 03
S Second in minute.
Examples:
SS = 30
Other text You can add other text into the pattern string to further format the string.
You can use punctuation, numbers, and all lowercase letters. You should
avoid uppercase letters because they may be interpreted as pattern letters.
Example:
EEEE, MMM. D, YYYY at L:NN A = Tuesday, Sept. 8, 2005 at 1:26 PM
The following table shows sample pattern strings and the resulting presentation:
Pattern Result
YYYY.MM.DD at HH:NN:SS 2005.07.04 at 12:08:56
EEE, MMM D, 'YY Wed, Jul 4, '05
H:NN A 12:08 PM
HH o'clock A 12 o'clock PM
K:NN A 0:08 PM
YYYYY.MMMM.DD. JJ:NN A 02005.July.04. 12:08 PM
EEE, D MMM YYYY HH:NN:SS Wed, 4 Jul 2005 12:08:56
<mx:Script>
<![CDATA[
// Define variable to hold the date.
[Bindable]
private var today:Date = new Date();
]]>
</mx:Script>
The format() method recognizes a dash (-) immediately preceding the first number in
the sequence as a negative number. A dash, space, and then number sequence are not
interpreted as a negative number.
The rounding and precision properties of the NumberFormatter class affect the formatting
of the decimal in a number. If you use both rounding and precision properties, rounding is
applied first, and then the decimal length is set using the specified precision value. This lets
you round a number and still have a trailing decimal; for example, 303.99 = 304.00.
<mx:Script>
<![CDATA[
// Define variable to hold the number.
[Bindable]
private var bigNumber:Number = 6000000000.65;
]]>
</mx:Script>
A shortcut is provided for the United States seven-digit format. If the areaCode property
contains a value and you use the seven-digit format string, a seven-digit format entry
automatically adds the area code to the string returned. The default format for the area
code is (###). You can change this using the areaCodeFormat property. You can format the
area code any way you want as long as it contains three number placeholders.
<mx:Script>
<![CDATA[
// Define variable to hold the phone number.
[Bindable]
private var newNumber:Number = 1234567;
]]>
</mx:Script>
For United States ZIP codes, if a nine-digit format is requested and a five-digit value is
supplied, -0000 is appended to the value to make it compliant with the nine-digit format.
Inversely, if a nine-digit value is supplied for a five-digit format, the number is truncated to
five digits.
For United States ZIP codes, only numeric characters are valid. For Canadian postal
codes, alphanumeric characters are allowed. Alphabetic characters must be in
uppercase.
<mx:Script>
<![CDATA[
// Define variable to hold the ZIP code.
[Bindable]
private var storedZipCode:Number=123456789;
]]>
</mx:Script>
Invalid format • One or more of the characters in the formatString do not match the
allowed characters specified in the validFormatChars property.
• The number of numeric placeholders does not equal 9, 5, or 6.
6
PART 6
Charting Components
This part describes how to use Flex Charting components with Adobe Flex
2.
The following topics are included:
Chapter 46: Introduction to Charts. . . . . . . . . . . . . . . . . . . . . . . . 1593
Chapter 47: Chart Types. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1645
Chapter 48: Formatting Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1707
Chapter 49: Displaying Data and Labels . . . . . . . . . . . . . . . . . . .1795
Chapter 50: Using Events and Effects in Charts. . . . . . . . . . . . . 1881
1591
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
CHAPTER 46
Introduction to Charts 46
Displaying data in a chart or graph can make data interpretation much easier for users of the
applications that you develop with the Adobe Flex product line. Rather than present a simple
table of numeric data, you can display a bar, pie, line, or other type of chart using colors,
captions, and a two-dimensional representation of your data.
This topic introduces you to the concepts for using the Adobe Flex Charting controls.
Contents
About charting. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1593
Using the charting controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1595
About the axis classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1604
About charting events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1605
Creating charts in ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1606
Defining chart data. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1613
About charting
Data visualization lets you present data in a way that simplifies data interpretation and data
relationships. Charting is one type of data visualization in which you create two-dimensional
representations of your data. Flex supports some of the most common types of two-
dimensional charts (such as bar, column, and pie charts) and gives you a great deal of control
over the appearance of charts.
1593
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
A simple chart shows a single data series, where a series is a group of related data points. For
example, a data series might be monthly sales revenues or daily occupancy rates for a hotel.
The following chart shows a single data series that corresponds to sales over several months.
Another chart might add a second data series. For example, you might include the percentage
growth of profits over the same four business quarters. The following chart shows two data
series—one for sales and one for profit.
For information about installing Flex Charting, see the readme.txt file included with the Flex
Charting installer.
All chart controls, except the PieChart class, are subclasses of the CartesianChart class.
Cartesian charts are charts that typically represent a set of data points in rectangular-shaped,
two-dimensional space. The PieChart class is a subclass of the PolarChart class, which
represents data in circular space.
All chart controls inherit basic charting characteristics from the ChartBase class.
A chart control typically has the following structure in MXML:
<mx:ChartName>
<!-- Define one or more series. -->
<mx:SeriesName/>
<mx:SecondSeriesName/>
<!-- Add grid lines and other elements to the chart. -->
<mx:annotationElements>
<mx:Array/>
</mx:annotationElements>
<mx:backgroundElements>
<mx:Array/>
</mx:backgroundElements/>
</mx:ChartName>
The following table describes the parts of the chart in more detail:
Part Description
Chart (Required) Defines one or two data providers for the chart. Also defines the
chart type and sets data tips, mouse sensitivity, gutter styles, and axis styles.
This is the top-level tag for a chart control. All other tags are child tags of this
tag.
Series (Required) Defines one or more data series to be displayed on the chart. Also
sets the strokes, fills, and renderers (or skins) of the data series, as well as the
strokes and fills used by the chart’s legend for each series.
You can also define a second set of series for each chart, to show multiple
data series in a single chart.
Each series in a chart can have its own data provider.
Axes Sets the axis type (numeric or category). Also defines the axis labels, titles,
and style properties such as padding.
You can also define axes for the second set of series, if there is one.
Axes renderer (Optional) Sets tick placement and styles, enables or disables labels, and
defines axis lines, label rotation, and label gap.
You can also define an axis renderer for a second series, if there is one.
Elements (Optional) Defines grid lines and extra elements to appear on the chart.
For each chart type, Flex supplies a corresponding chart control and chart series. The chart
control defines the chart type, the data provider that supplies the chart data, the grid lines, the
text for the chart axes, and other properties specific to the chart type. The dataProvider
property of the chart control determines what data the chart uses.
You can customize data labels by using a labelFunction. This callback function takes
arguments that define the series item and returns a String that is then rendered on the series
item.
For information about adding data labels to your charts, see “Using data labels” on page 1829.
Series also let you set a minField value. This property lets you specify a minimum value that
the series displays. For more information, see “Using the minField property” on page 1865.
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500},
{Month:"Feb", Profit:1000, Expenses:200},
{Month:"Mar", Profit:1500, Expenses:500}
]);
myChart.series = mySeries;
// Create a legend.
legend1 = new Legend();
legend1.dataProvider = myChart;
[Bindable]
public var profit04:ArrayCollection = new ArrayCollection([
{Month: "Jan", Profit: 2000},
{Month: "Feb", Profit: 1000},
{Month: "Mar", Profit: 1500}
]);
[Bindable]
public var profit05:ArrayCollection = new ArrayCollection([
{Month: "Jan", Profit: 2200},
{Month: "Feb", Profit: 1200},
{Month: "Mar", Profit: 1700}
]);
[Bindable]
public var profit06:ArrayCollection = new ArrayCollection([
{Month: "Jan", Profit: 2400},
{Month: "Feb", Profit: 1400},
{Month: "Mar", Profit: 1900}
]);
myChart.series = currentSeries;
}
}
]]></mx:Script>
<mx:Panel title="Column Chart">
<mx:ColumnChart id="myChart" dataProvider="{profit04}">
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="Month"/>
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries dataProvider="{profit04}"
yField="Profit"
xField="Month"
displayName="2004"
/>
</mx:series>
</mx:ColumnChart>
<mx:Legend dataProvider="{myChart}"/>
</mx:Panel>
<mx:Button id="b1" label="Add More Series To Chart" click=
"addMoreSeries()"/>
</mx:Application>
By using ActionScript, you can also define a variable number of series for your charts. The
following example uses E4X syntax to extract an Array of unique names from the data. It then
iterates over this Array and builds a new LineSeries for each name.
<?xml version="1.0"?>
<!-- charts/VariableSeries.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp();">
<mx:Script><![CDATA[
import mx.charts.series.LineSeries;
import mx.charts.DateTimeAxis;
[Bindable]
private var myXML:XML =
<dataset>
<item>
<who>Tom</who>
<when>08/22/2006</when>
<hours>5.5</hours>
</item>
<item>
<who>Tom</who>
<when>08/23/2006</when>
<hours>6</hours>
</item>
You can use the Profit and Expenses fields and ignore the Month field by mapping the
xField property of the series object to one field and the yField property of the series object
to another field, as the following example shows:
<mx:PlotSeries xField="Profit" yField="Expenses"/>
The result is that each data point is the intersection of the Profit and Expenses fields from
the data provider.
To place the data points into a meaningful grouping, you can choose a separate property of
the data provider as the categoryField. In this case, to sort each data point by month, you
map the Month field to the categoryField property of the horizontal axis:
<mx:horizontalAxis>
<mx:CategoryAxis dataProvider="{expenses}" categoryField="Month"/>
</mx:horizontalAxis>
In some cases, depending on the type of chart and the type of data you are representing, you
use either the xField property or the yField property to define the data series. In a
ColumnChart control, for example, the yField property defines the height of the column.
You do not have to specify an xField property. To get an axis label for each column, you
specify a categoryField property for the horizontalAxis.
When you use chart data, keep the following in mind:
■ Some series use only one field from the data provider, while others can use two or more.
For example, you specify only a field property for a PieSeries object, but you can specify
an xField and a yField for a PlotSeries object and an xField, yField, and
radiusField for a BubbleSeries object.
■ Most of the series can determine suitable defaults for their nonprimary dimensions if no
field is specified. For example, if you do not explicitly set an xField for the
ColumnSeries, LineSeries, and AreaSeries, Flex maps the data to the chart’s categories in
the order in which the data appears in the data provider. Similarly, a BarSeries maps the
data to the categories if you do not set a yField.
For a complete list of the fields that each data series can take, see the data series’ entry in Adobe
Flex Language Reference. For more information on data providers, see “Using data provider
controls” on page 270.
]]></mx:Script>
<mx:Panel title="Column Chart">
<mx:ColumnChart id="myChart" dataProvider="{expenses}">
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"
/>
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Profit"
displayName="Profit"
/>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
/>
</mx:series>
</mx:ColumnChart>
<mx:Legend dataProvider="{myChart}"/>
</mx:Panel>
</mx:Application>
[Bindable]
private var expenses:ArrayCollection = new ArrayCollection([
{Month:"January", Profit:2000, Expenses:1500, Amount:450},
{Month:"February", Profit:1000, Expenses:200, Amount:600},
{Month:"March", Profit:1500, Expenses:500, Amount:300},
{Month:"April", Profit:500, Expenses:300, Amount:500},
{Month:"May", Profit:1000, Expenses:450, Amount:250},
{Month:"June", Profit:2000, Expenses:500, Amount:700}
]);
]]></mx:Script>
<mx:Panel title="Column Chart">
<mx:ColumnChart id="myChart" dataProvider="{expenses}">
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"
/>
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Profit"
displayName="Profit"
/>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
/>
</mx:series>
</mx:ColumnChart>
<mx:Legend dataProvider="{myChart}"/>
</mx:Panel>
</mx:Application>
[Bindable]
public var expensesAC:ArrayCollection =
new ArrayCollection(expenses);
]]></mx:Script>
[Bindable]
private var expenses:Array = [
{Month:"January", Profit:2000, Expenses:1500, Amount:450},
{Month:"February", Profit:1000, Expenses:200, Amount:600},
{Month:"March", Profit:1500, Expenses:500, Amount:300},
{Month:"April", Profit:500, Expenses:300, Amount:500},
{Month:"May", Profit:1000, Expenses:450, Amount:250},
{Month:"June", Profit:2000, Expenses:500, Amount:700}
];
]]></mx:Script>
[Bindable]
public var memoryUsage:ArrayCollection = new ArrayCollection();
<mx:HTTPService
id="srv"
url="../assets/data.xml"
useProxy="false"
result="myData=ArrayCollection(srv.lastResult.data.result)"
/>
<mx:Panel title="Line Chart">
<mx:LineChart id="chart" dataProvider="{myData}">
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="month"/>
</mx:horizontalAxis>
<mx:series>
<mx:LineSeries yField="apple" name="Apple"/>
<mx:LineSeries yField="orange" name="Orange"/>
<mx:LineSeries yField="banana" name="Banana"/>
</mx:series>
</mx:LineChart>
</mx:Panel>
</mx:Application>
<mx:HTTPService id="srv"
url="../assets/data.xml"
resultFormat="e4x"
/>
<mx:XMLListCollection id="myAC"
source="{srv.lastResult.result}"
/>
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500, Amount:450},
{Month:"Feb", Profit:1000, Expenses:200, Amount:600},
{Month:"Mar", Profit:1500, Expenses:500, Amount:300}
]);
[Bindable]
public var expenses2:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2400, Expenses:1509, Amount:950},
{Month:"Feb", Profit:3000, Expenses:2200, Amount:400},
{Month:"Mar", Profit:3500, Expenses:1200, Amount:200}
]);
[Bindable]
public var dp:ArrayCollection = expenses;
[Bindable]
public var dataSet:ArrayCollection;
[Bindable]
public var revenue:Number = 100;
<mx:SeriesInterpolate id="interp"
elementOffset="0"
duration="300"
minimumElementDuration="0"
/>
[Bindable]
public var memoryUsage:ArrayCollection = new ArrayCollection();
<mx:LineChart id="chart"
dataProvider="{memoryUsage}"
showDataTips="true"
>
<mx:horizontalAxis>
<mx:LinearAxis/>
</mx:horizontalAxis>
<mx:verticalAxis>
<mx:LinearAxis minimum="5000000"/>
</mx:verticalAxis>
<mx:series>
<mx:Array>
<mx:LineSeries yField="memory"/>
</mx:Array>
</mx:series>
</mx:LineChart>
</mx:Application>
CHAPTER 47
Chart Types 47
Adobe Flex provides different types of charting controls.
Contents
Using area charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1646
Using bar charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1649
Using bubble charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1651
Using candlestick charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1657
Using column charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1662
Using HighLowOpenClose charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1669
Using line charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1673
Using pie charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1684
Using plot charts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1692
Using multiple data series . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1696
Using multiple axes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1698
1645
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Using area charts
You use the AreaChart control to represent data as an area bounded by a line connecting the
values in the data. The area underneath the line is filled in with a color or pattern. You can use
an icon or symbol to represent each data point along the line, or you can show a simple line
without icons.
The following image shows an example of an area chart:
Property Description
yField Specifies the field of the data provider that determines the y-axis location of
each data point.
xField Specifies the field of the data provider that determines the x-axis location of
each data point. If you omit this field, Flex arranges the data points in the
order of the data in the data provider.
minField Specifies the field of the data provider that determines the y-axis location of
the bottom of an area. This property is optional. If you omit it, the bottom of
the area is aligned with the x-axis. This property has no effect on overlaid,
stacked, or 100% stacked charts. For more information on using the
minField property, see “Using the minField property” on page 1865.
form Specifies the way in which the data series is shown in the chart. The
following values are valid:
• segment Draws lines as connected segments that are angled to connect
at each data point in the series. This is the default.
• step Draws lines as horizontal and vertical segments. At the first data
point, draws a horizontal line, and then a vertical line to the second point.
Repeats this action for each data point.
• reverseStep Draws lines as horizontal and vertical segments. At the first
data point, draws a vertical line, and then a horizontal line to the second
point. Repeats this action for each data point.
• vertical Draws only the vertical line from the y-coordinate of the first
point to y-coordinate of the second point at the x-coordinate of the second
point. Repeats this action for each data point.
• horizontal Draws only the horizontal line from the x-coordinate of the
first point to x-coordinate of the second point at the y-coordinate of the
first point. Repeats this action for each data point.
• curve Draws curves between data points.
You can use the type property of the AreaChart control to represent a number of chart
variations, including overlaid, stacked, 100% stacked, and high-low areas. For more
information, see “Stacking charts” on page 1867.
Property Description
yField Specifies the field of the data provider that determines the y-axis location of
the base of each bar in the chart. If you omit this property, Flex arranges the
bars in the order of the data in the data provider.
Property Description
yField Specifies the field of the data provider that determines the y-axis location
of each data point. This property is required.
xField Specifies the field of the data provider that determines the x-axis location
of each data point. This property is required.
radiusField Specifies the field of the data provider that determines the radius of each
symbol, relative to the other data points in the chart. This property is
required.
The following example draws a BubbleChart control and sets the maximum radius of bubble
elements to 50:
<?xml version="1.0"?>
<!-- charts/BasicBubble.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:120, Amount:45},
{Month:"Feb", Profit:1000, Expenses:200, Amount:60},
{Month:"Mar", Profit:1500, Expenses:500, Amount:30}
]);
]]></mx:Script>
<mx:Panel title="Bubble Chart">
<mx:BubbleChart id="myChart"
maxRadius="50"
dataProvider="{expenses}"
showDataTips="true"
>
<mx:series>
<mx:BubbleSeries
xField="Profit"
yField="Expenses"
radiusField="Amount"
displayName="Profit"
/>
</mx:series>
</mx:BubbleChart>
<mx:Legend dataProvider="{myChart}"/>
</mx:Panel>
</mx:Application>
[Bindable]
private var s2:ArrayCollection = new ArrayCollection( [
{"x": 20, "y": 50, "r":2 },
{"x": 40, "y": 75, "r":4 },
{"x": 60, "y": 100, "r":8 } ]);
]]>
</mx:Script>
[Bindable]
private var s2:ArrayCollection = new ArrayCollection( [
{"x": 20, "y": 50, "r":2 },
{"x": 40, "y": 75, "r":4 },
{"x": 60, "y": 100, "r":8 } ]);
]]>
</mx:Script>
The following table describes the properties of the CandlestickSeries chart series that you
commonly use to define your chart:
Property Description
closeField Specifies the field of the data provider that determines the y-axis location
of the closing value of the element. This property defines the top or bottom
of the candlestick.
highField Specifies the field of the data provider that determines the y-axis location
of the high value of the element. This property defines the top of the line
inside the candlestick.
lowField Specifies the field of the data provider that determines the y-axis location
of the low value of the element. This property defines the bottom of the line
inside the candlestick.
If the closeField is lower than the openField, Flex applies a solid fill to the candle. The
color of this solid fill defaults to the color of the box’s outline. It is defined by the
declineFill style property. If the closeField is higher than the openField, Flex fills the
candle with white by default.
The following image shows these properties. As you can see, the location of the closeField
property can be either the top or the bottom of the candlestick, depending on whether it is
higher or lower than the openField property:
highField closeField
openField
openField
closeField
lowField
[Bindable]
public var TICKER:ArrayCollection = new ArrayCollection([
{date:"1-Aug-05",open:42.57,high:43.08,low:42.08,close:42.75},
{date:"2-Aug-05",open:42.89,high:43.5,low:42.61,close:43.19},
{date:"3-Aug-05",open:43.19,high:43.31,low:42.77,close:43.22},
{date:"4-Aug-05",open:42.89,high:43,low:42.29,close:42.71},
{date:"5-Aug-05",open:42.49,high:43.36,low:42.02,close:42.99},
{date:"8-Aug-05",open:43,high:43.25,low:42.61,close:42.65},
{date:"9-Aug-05",open:42.93,high:43.89,low:42.91,close:43.82},
{date:"10-Aug-05",open:44,high:44.39,low:43.31,close:43.38},
{date:"11-Aug-05",open:43.39,high:44.12,low:43.25,close:44},
{date:"12-Aug-05",open:43.46,high:46.22,low:43.36,close:46.1}
]);
]]></mx:Script>
<mx:series>
<mx:CandlestickSeries
dataProvider="{TICKER}"
openField="open"
highField="high"
lowField="low"
closeField="close"
displayName="TICKER"
>
<mx:fill>
Property Description
yField Specifies the field of the data provider that determines the y-axis location of
the top of a column. This field defines the height of the column.
xField Specifies the field of the data provider that determines the x-axis location of
the column. If you omit this property, Flex arranges the columns in the order
of the data in the data provider.
minField Specifies the field of the data provider that determines the y-axis location of
the bottom of a column. This property has no effect on overlaid, stacked, or
100% stacked charts. For more information on using the minField property,
see “Using the minField property” on page 1865.
The following table describes the properties of the HLOCChart control’s series that you
commonly use to define your chart:
Property Description
closeField Specifies the field of the data provider that determines the y-axis
location of the closing value of the element. This property defines the
position of the right tick mark on the vertical line.
highField Specifies the field of the data provider that determines the y-axis
location of the high value of the element. This property defines the top
of the vertical line.
highField
openField
closeField
lowField
[Bindable]
public var TICKER:ArrayCollection = new ArrayCollection([
{date:"1-Aug-05",open:42.57,high:43.08,low:42.08,close:42.75},
{date:"2-Aug-05",open:42.89,high:43.5,low:42.61,close:43.19},
{date:"3-Aug-05",open:43.19,high:43.31,low:42.77,close:43.22},
{date:"4-Aug-05",open:42.89,high:43,low:42.29,close:42.71},
{date:"5-Aug-05",open:42.49,high:43.36,low:42.02,close:42.99},
{date:"8-Aug-05",open:43,high:43.25,low:42.61,close:42.65},
{date:"9-Aug-05",open:42.93,high:43.89,low:42.91,close:43.82},
{date:"10-Aug-05",open:44,high:44.39,low:43.31,close:43.38},
{date:"11-Aug-05",open:43.39,high:44.12,low:43.25,close:44},
{date:"12-Aug-05",open:43.46,high:46.22,low:43.36,close:46.1}
]);
]]></mx:Script>
[Bindable]
public var TICKER:ArrayCollection = new ArrayCollection([
{date:"1-Aug-05",open:42.57,high:43.08,low:42.08,close:42.75},
{date:"2-Aug-05",open:42.89,high:43.5,low:42.61,close:43.19},
{date:"3-Aug-05",open:43.19,high:43.31,low:42.77,close:43.22},
{date:"4-Aug-05",open:42.89,high:43,low:42.29,close:42.71},
{date:"5-Aug-05",open:42.49,high:43.36,low:42.02,close:42.99},
{date:"8-Aug-05",open:43,high:43.25,low:42.61,close:42.65},
{date:"9-Aug-05",open:42.93,high:43.89,low:42.91,close:43.82},
{date:"10-Aug-05",open:44,high:44.39,low:43.31,close:43.38},
{date:"11-Aug-05",open:43.39,high:44.12,low:43.25,close:44},
{date:"12-Aug-05",open:43.46,high:46.22,low:43.36,close:46.1},
]);
]]></mx:Script>
Property Description
yField Specifies the field of the data provider that determines the y-axis
location of each data point. This is the height of the line at that
location along the axis.
xField Specifies the field of the data provider that determines the x-axis
location of each data point. If you omit this field, Flex arranges the
data points in the order of the data in the data provider.
interpolateValues Specifies how to represent missing data. If you set the value of this
property to false, the chart breaks the line at the missing value. If you
specify a value of true, Flex draws a continuous line by interpolating
the missing value. The default value is false.
form Specifies the way in which the data series is shown in the chart. The
following values are valid:
• segment Draws lines as connected segments that are angled to
connect at each data point in the series. This is the default.
• step Draws lines as horizontal and vertical segments. At the first
data point, draws a horizontal line, and then a vertical line to the
second point. Repeats this for each data point.
• reverseStep Draws lines as horizontal and vertical segments. At
the first data point, draws a vertical line, and then a horizontal line to
the second point. Repeats this for each data point.
• vertical Draws the vertical line only from the y-coordinate of the
first point to the y-coordinate of the second point at the x-
coordinate of the second point. Repeats this for each data point.
• horizontal Draws the horizontal line only from the x-coordinate of
the first point to the x-coordinate of the second point at the y-
coordinate of the first point. Repeats this for each data point.
• curve Draws curves between data points.
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500, Amount:450},
{Month:"Feb", Profit:1000, Expenses:200, Amount:600},
{Month:"Mar", Profit:1500, Expenses:500, Amount:300}
]);
]]></mx:Script>
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500, Amount:450},
{Month:"Feb", Profit:1000, Expenses:200, Amount:600},
{Month:"Mar", Profit:1500, Expenses:500, Amount:300}
]);
]]></mx:Script>
To make lines in a LineChart control display vertically rather than horizontally, you must do
the following:
■ Explicitly define the xField and yField properties for the LineSeries object.
■ Set the sortOnXField property of the LineSeries object to false.
By default, data points in a series are sorted from left to right (on the x-axis) before rendering.
This causes the LineSeries to draw horizontally. When you disable the xField sort and
explicitly define a yField property, Flex draws the lines vertically rather than horizontally.
You use the PieSeries chart series with the PieChart control to define the data for the chart.
The PieSeries can create standard pie charts or doughnut charts. PieChart controls also
support labels that identify data points.
The following table describes the properties of the PieChart control’s PieSeries chart series
that you commonly use to define your chart:
Property Description
field Specifies the field of the data provider that determines the data for
each wedge of the pie chart.
labelPosition Specifies how to render data labels for the wedges.
nameField Specifies the field of the data provider to use as the name for the
wedge in DataTips and legends.
Value Description
callout Draws labels in two vertical stacks on either side of the PieChart
control. Shrinks the PieChart if necessary to make room for the
labels. Draws key lines from each label to the associated wedge.
Shrinks labels as necessary to fit the space provided.
This property can only be used with a PieSeries object. You cannot
use callouts with BarSeries and ColumnSeries objects.
inside Draws labels inside the chart. Shrinks labels to ensure that they do
not overlap each other. Any label that must be drawn too small, as
defined by the insideLabelSizeLimit property, is hidden from view.
insideWithCallout Draws labels inside the pie, but if labels are shrunk below a legible
size, Flex converts them to callout labels. This is a common value to
set labelPosition to when the actual size of your chart is flexible and
users might resize it.
This property can only be used with a PieSeries object. You cannot
use callouts with BarSeries and ColumnSeries objects.
none Does not draw labels. This is the default value.
outside Draws labels around the boundary of the PieChart control.
The following table describes the properties of the PieSeries object that you can use to
manipulate the appearance of labels:
Property Description
calloutGap Defines how much space, in pixels, to insert between the edge of the
pie and the data labels when rendering callouts. The default value is
10 pixels.
calloutStroke Defines the line style used to draw the lines to callouts. For more
information on defining line data points, see “Using strokes”
on page 1730.
insideLabelSizeLimit Defines the size threshold, expressed in points, below which inside
data labels are considered illegible. Below this threshold, data labels
are either removed entirely or turned into callouts based on the
setting of the series labelPosition property.
You can change the value of the data labels by using the labelFunction property of the
PieSeries object to specify a callback function. For more information, see “Customizing data
labels for PieSeries objects” on page 1841.
The following table describes the properties that support exploding pie charts:
Property Description
explodeRadius A value from 0 to 1, representing the percentage of the
available pie radius to use when exploding the wedges of the
pie.
perWedgeExplodeRadius An array of values from 0 to 1. The Nth value in this array is
added to the value of explodeRadius to determine the explode
amount of each individual wedge of the pie. Individual values
can be left undefined, in which case the wedge will only
explode according to the explodeRadius property.
reserveExplodeRadius A value from 0 to 1, representing an amount of the available pie
radius to reserve for animating an exploding wedge.
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Expense:"Taxes", Amount:2000},
{Expense:"Rent", Amount:1000},
{Expense:"Bills", Amount:100},
{Expense:"Car", Amount:450},
{Expense:"Gas", Amount:100},
{Expense:"Food", Amount:200}
]);
]]></mx:Script>
<mx:Panel title="Exploding Pie Chart">
<mx:PieChart id="pie"
dataProvider="{expenses}"
showDataTips="true"
>
<mx:series>
<!--explodeRadius is a number between 0 and 1.-->
<mx:PieSeries
field="Amount"
nameField="Expense"
explodeRadius=".12"
/>
</mx:series>
</mx:PieChart>
<mx:Legend dataProvider="{pie}"/>
</mx:Panel>
</mx:Application>
You use the PlotSeries class with the PlotChart control to define the data for the chart. The
following table describes the properties of the PlotSeries chart series that you commonly use
to define your chart:
Property Description
yField Specifies the field of the data provider that determines the y-axis
location of each data point.
xField Specifies the field of the data provider that determines the x-axis
location of each data point.
radius Specifies the radius, in pixels, of the symbol at each data point. The
default value is 5 pixels.
N OTE
Both the xField and yField properties are required for each PlotSeries in a PlotChart
control.
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"January", Profit:2000, Expenses:1500, Amount:450},
{Month:"February", Profit:1000, Expenses:200, Amount:600},
{Month:"March", Profit:1500, Expenses:500, Amount:300},
{Month:"April", Profit:500, Expenses:300, Amount:500},
{Month:"May", Profit:1000, Expenses:450, Amount:250},
{Month:"June", Profit:2000, Expenses:500, Amount:700}
]);
]]></mx:Script>
<mx:Panel title="Plot Chart">
<mx:PlotChart id="myChart" dataProvider="{expenses}"
showDataTips="true">
<mx:series>
<mx:PlotSeries
xField="Expenses"
yField="Profit"
displayName="Plot 1"
/>
<mx:PlotSeries
xField="Amount"
yField="Expenses"
displayName="Plot 2"
/>
<mx:PlotSeries
xField="Profit"
yField="Amount"
displayName="Plot 3"
/>
</mx:series>
</mx:PlotChart>
<mx:Legend dataProvider="{myChart}"/>
</mx:Panel>
</mx:Application>
By default, Flex displays the first data series in the chart as a diamond at each point. When
you define multiple data series in a chart, Flex rotates the shape for the series (starting with a
diamond, then a circle, then a square). If you have more series than there are default renderers,
Flex begins again with the diamond.
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"January", Profit:2000, Expenses:1500, Amount:450},
{Month:"February", Profit:1000, Expenses:200, Amount:600},
{Month:"March", Profit:1500, Expenses:500, Amount:300},
{Month:"April", Profit:500, Expenses:300, Amount:500},
{Month:"May", Profit:1000, Expenses:450, Amount:250},
{Month:"June", Profit:2000, Expenses:500, Amount:700}
]);
]]>
</mx:Script>
You can use any combination of the following series objects in a CartesianChart control:
■ AreaSeries
■ BarSeries
■ BubbleSeries
■ CandlestickSeries
■ ColumnSeries
■ HLOCSeries
■ LineSeries
■ PlotSeries
By default, all charts that are subclasses of CartesianChart display a single set of data, and
single horizontal and vertical axes. Setting any of the secondary properties, such as
secondDataProvider, secondSeries, secondVerticalAxis /secondHorizontalAxis, or
secondVerticalAxisRenderer/secondHorizontalAxisRenderer, has the following effect
on the chart:
ColumnChart, LineChart, and AreaChart controls Primary and secondary series share the
horizontalAxis by default, but each get a separate LinearAxis for their verticalAxis. A
second verticalAxisRenderer is created by default when using multiple axes.
BarChart controls Primary and secondary series share the verticalAxis, but by default,
each has a separate horizontalAxis. Two horizontalAxisRenderers are created by
default.
PlotChart and BubbleChart controls Primary and secondary series have separate
horizontal and vertical axes, and all four axis renderers. Bubble charts continue to share a
single radialAxis among all series.
CartesianChart controls Cartesian charts have no extra axes or axis renderers by default.
PieChart controls Secondary series are not supported.
Use the <mx:secondSeries> tag to specify an Array of series objects that are rendered by
using other scales. Any fields applied to series in this array refer to fields on the
secondDataProvider.
You use the secondDataProvider property for the data provider used by any series provided
in the secondSeries property.
[Bindable]
public var SMITH:ArrayCollection = new ArrayCollection([
{date:"22-Aug-05", close:41.87},
{date:"23-Aug-05", close:45.74},
{date:"24-Aug-05", close:42.77},
{date:"25-Aug-05", close:48.06},
]);
[Bindable]
public var DECKER:ArrayCollection = new ArrayCollection([
{date:"22-Aug-05", close:157.59},
{date:"23-Aug-05", close:160.3},
{date:"24-Aug-05", close:150.71},
{date:"25-Aug-05", close:156.88},
]);
]]></mx:Script>
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{SMITH}"
categoryField="date"
/>
</mx:horizontalAxis>
<mx:verticalAxis>
<mx:LinearAxis minimum="40" maximum="50"/>
</mx:verticalAxis>
<mx:series>
<mx:secondVerticalAxis>
<mx:LinearAxis minimum="150" maximum="170"/>
</mx:secondVerticalAxis>
<mx:secondSeries>
<mx:LineSeries id="cs2"
dataProvider="{DECKER}"
xField="date"
yField="close"
displayName="DECKER"
/>
</mx:secondSeries>
</mx:ColumnChart>
</mx:Panel>
</mx:Application>
This example does not include a legend. When you create a chart with multiple axes, you
cannot use the standard <mx:Legend> tag to create a legend for that chart. You must create a
custom legend. For more information, see “Creating a custom Legend control” on page 1878.
For more information on formatting axes, see “Working with axes” on page 1795
<mx:verticalAxis>
<mx:LinearAxis minimum="30" maximum="50"/>
</mx:verticalAxis>
<mx:series>
<mx:ColumnSeries
dataProvider="{SMITH}"
xField="date"
yField="close"
displayName="SMITH"
/>
</mx:series>
<mx:secondVerticalAxis>
<mx:LinearAxis minimum="150" maximum="170"/>
</mx:secondVerticalAxis>
<mx:verticalAxisRenderer>
<mx:AxisRenderer
placement="right"
tickPlacement="inside"
>
<mx:axisStroke>
<mx:Stroke color="#CC6699" weight="1"/>
</mx:axisStroke>
<mx:tickStroke>
<mx:Stroke color="#CC0099" weight="1"/>
</mx:tickStroke>
<mx:minorTickStroke>
<mx:Stroke color="#990066" weight="1"/>
</mx:minorTickStroke>
</mx:AxisRenderer>
</mx:verticalAxisRenderer>
<mx:secondVerticalAxisRenderer>
<mx:AxisRenderer
placement="left"
tickPlacement="inside"
>
<mx:axisStroke>
<mx:Stroke color="#000080" weight="1"/>
</mx:axisStroke>
<mx:tickStroke>
<mx:Stroke color="#000160" weight="1"/>
</mx:tickStroke>
<mx:minorTickStroke>
<mx:Stroke color="#100040" weight="1"/>
</mx:minorTickStroke>
</mx:AxisRenderer>
</mx:secondVerticalAxisRenderer>
<mx:secondSeries>
<mx:LineSeries
dataProvider="{DECKER}"
xField="date"
yField="close"
displayName="DECKER"
/>
</mx:secondSeries>
</mx:ColumnChart>
</mx:Panel>
CHAPTER 48
Formatting Charts 48
You can customize the look and feel of your Adobe Flex Charting components. You can
format the appearance of almost all chart elements, from the font properties of an axis label to
the width of the stroke in a legend.
To set style properties in your chart controls, you can use Cascading Style Sheets (CSS) syntax
or set the style properties inline as tag attributes. As with all styles, you can call the
setStyle() method to set any style on your chart elements. For more information on using
the setStyle() method, see “Using the setStyle() and getStyle() methods” on page 807.
Contents
Applying chart styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1708
Setting padding properties. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1720
Formatting tick marks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1725
Formatting axis lines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1727
Using strokes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1730
Using fills . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1738
Using filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1758
Using grid lines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1767
Skinning ChartItem objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1779
Formatting Legend controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1787
1707
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
Applying chart styles
You can apply styles to charts by using CSS or inline syntax. You can also apply styles to chart
elements by using binding.
Essentially, you are defining a new style for each series in your chart. For example, if you have
a ColumnChart control with two series, you can apply a different style to each series without
having to explicitly set the styles on each series.
The following example defines the colors for two series in the ColumnChart control:
<?xml version="1.0"?>
<!-- charts/SeriesStyles.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Style>
ColumnChart {
chartSeriesStyles: PCCSeries1, PCCSeries2;
}
.PCCSeries1 {
fill: #CCFF66;
<mx:Script>
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month: "Jan", Profit: 2000, Expenses: 1500},
{Month: "Feb", Profit: 1000, Expenses: 200},
{Month: "Mar", Profit: 1500, Expenses: 500}
]);
</mx:Script>
<mx:Panel>
<mx:ColumnChart id="column" dataProvider="{expenses}">
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"
/>
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Profit"
displayName="Profit"
/>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
/>
</mx:series>
</mx:ColumnChart>
<mx:Legend dataProvider="{column}"/>
</mx:Panel>
</mx:Application>
Flex sets the styleName property of each series to the corresponding selector in the
chartSeriesStyles Array. You do not have to explicitly set styles for each series. If you have
more series than available chartSeriesStyles selectors, the chart begins again with the first
style.
If you manually set the value of the styleName property on a particular series, that style takes
priority over the styles that the chartSeriesStyles property specifies.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Expense:"Taxes", Amount:2000},
{Expense:"Rent", Amount:1000},
{Expense:"Bills", Amount:100},
{Expense:"Car", Amount:450},
{Expense:"Gas", Amount:100},
{Expense:"Food", Amount:200}
]);
]]>
</mx:Script>
<mx:Panel>
<mx:PieChart id="pie"
dataProvider="{expenses}"
showDataTips="true"
>
<mx:series>
<mx:PieSeries
field="Amount"
nameField="Expense"
labelPosition="callout"
/>
</mx:series>
</mx:PieChart>
<mx:Legend dataProvider="{pie}"/>
</mx:Panel>
</mx:Application>
.myAxisStyles {
tickPlacement:none;
}
</mx:Style>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500},
{Month:"Feb", Profit:1000, Expenses:200},
{Month:"Mar", Profit:1500, Expenses:500}
]);
]]>
</mx:Script>
<mx:Panel>
<mx:ColumnChart id="column" dataProvider="{expenses}">
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"
/>
<mx:Style>
.myStyle {
fontSize:7;
color:red;
}
</mx:Style>
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan",Profit:2000,Expenses:1500},
{Month:"Feb",Profit:1000,Expenses:200},
{Month:"Mar",Profit:1500,Expenses:500}
]);
]]></mx:Script>
<mx:Panel>
<mx:ColumnChart id="column" dataProvider="{expenses}">
<mx:horizontalAxisRenderer>
<mx:AxisRenderer styleName="myStyle"/>
</mx:horizontalAxisRenderer>
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"
/>
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Profit"
displayName="Profit"
/>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
/>
</mx:series>
</mx:ColumnChart>
<mx:Legend dataProvider="{column}"/>
</mx:Panel>
</mx:Application>
Most charting-specific style properties are not inheritable, which means that if you set the
property on a parent object, the child object does not inherit its value.
For more information on using CSS, see “About styles” on page 767.
You can also access the properties of renderers in ActionScript so that you can change their
appearance at run time. For additional information about axis renderers, see “Working with
axes” on page 1795.
<mx:HLOCChart id="mychart"
dataProvider="{aapl}"
showDataTips="true"
>
<mx:horizontalAxisRenderer>
<mx:AxisRenderer
axisStroke="{axis}"
placement="bottom"
minorTickPlacement="inside"
minorTickLength="2"
tickLength="5"
tickPlacement="inside"
>
<mx:tickStroke>{ticks}</mx:tickStroke>
<mx:minorTickStroke>{mticks}</mx:minorTickStroke>
<mx:verticalAxis>
<mx:LinearAxis minimum="30" maximum="50"/>
</mx:verticalAxis>
<mx:series>
<mx:HLOCSeries
dataProvider="{aapl}"
openField="open"
highField="high"
lowField="low"
closeField="close"
displayName="AAPL"
>
</mx:HLOCSeries>
</mx:series>
</mx:HLOCChart>
<mx:Legend dataProvider="{mychart}"/>
</mx:Application>
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500},
{Month:"Feb", Profit:1000, Expenses:200},
{Month:"Mar", Profit:1500, Expenses:500}
]);
[Embed(source="../assets/bird.gif")]
public var bird:Class;
myChart.annotationElements = [bgi]
myChart.backgroundElements = [ b ];
}
]]></mx:Script>
<mx:Panel>
<mx:ColumnChart id="myChart" dataProvider="{expenses}">
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"
/>
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Profit"
displayName="Profit"
/>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
/>
</mx:series>
<mx:annotationElements>
<mx:GridLines>
<mx:horizontalStroke>
<mx:Stroke
color="#191970"
weight="2"
alpha=".3"
/>
</mx:horizontalStroke>
</mx:GridLines>
</mx:annotationElements>
<mx:backgroundElements>
<mx:Image
source="@Embed('../assets/bird.gif')"
alpha=".2"
/>
</mx:backgroundElements>
</mx:ColumnChart>
<mx:Legend dataProvider="{myChart}"/>
<mx:Button id="b1"
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500},
{Month:"Feb", Profit:1000, Expenses:200},
{Month:"Mar", Profit:1500, Expenses:500}
]);
[Embed(source="../assets/bird.gif")]
public var bird:Class;
Padding
area
Gutter
Axis
Label gap
Axis label 0 20 40 60 80 100
The default value of the gutter styles is undefined, which means that the chart determines
appropriate values. Overriding the default value and explicitly setting gutter values can
improve the speed of rendering charts, because Flex does not have to dynamically calculate the
gutter size. However, it can also cause clipping of axis labels or other undesirable effects.
You set gutter styles on the chart control. The following example creates a region that is 50
pixels wide for the axis labels, titles, and tick marks, by explicitly setting the values of the
gutterLeft, gutterRight, and gutterBottom style properties. It also sets the paddingTop
property to 20.
<?xml version="1.0"?>
<!-- charts/GutterStyles.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Style>
ColumnChart {
gutterLeft:50;
gutterRight:50;
gutterBottom:50;
paddingTop:20;
}
</mx:Style>
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500},
Value Description
cross Places tick marks across the axis.
inside Places tick marks on the inside of the axis line.
none Hides tick marks.
outside Places tick marks on the outside of the axis line.
You can align the tick marks with labels by using the tickAlignment property.
Property Description
tickLength The length, in pixels, of the major tick mark from the axis.
minorTickLength The length, in pixels, of the minor tick mark from the axis.
The minor tick marks overlap the placement of major tick marks. So, if you hide major tick
marks but still show minor tick marks, the minor tick marks appear at the regular tick-mark
intervals.
The following example sets tick marks to the inside of the axis line, sets the tick mark’s length
to 12 pixels, and hides minor tick marks:
<?xml version="1.0"?>
<!-- charts/TickStyles.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
[Bindable]
public var aapl:Array = [
{date:"1-Aug-05",open:42.57,high:43.08,low:42.08,close:42.75},
{date:"2-Aug-05",open:42.89,high:43.5,low:42.61,close:43.19},
{date:"3-Aug-05",open:43.19,high:43.31,low:42.77,
close:43.22},
{date:"4-Aug-05",open:42.89,high:43,low:42.29,close:42.71},
{date:"5-Aug-05",open:42.49,high:43.36,low:42.02,
close:42.99},
{date:"8-Aug-05",open:43,high:43.25,low:42.61,close:42.65},
{date:"9-Aug-05",open:42.93,high:43.89,low:42.91,
close:43.82},
{date:"10-Aug-05",open:44,high:44.39,low:43.31,close:43.38},
{date:"11-Aug-05",open:43.39,high:44.12,low:43.25,close:44},
{date:"12-Aug-05",open:43.46,high:46.22,low:43.36,
close:46.1},
];
]]></mx:Script>
<mx:Style>
.myAxisStyle {
placement:bottom;
minorTickPlacement:none;
tickLength:12;
tickPlacement:inside;
}
</mx:Style>
<mx:HLOCChart id="mychart"
<mx:verticalAxis>
<mx:LinearAxis minimum="30" maximum="50"/>
</mx:verticalAxis>
<mx:series>
<mx:HLOCSeries
dataProvider="{aapl}"
openField="open"
highField="high"
lowField="low"
closeField="close"
displayName="AAPL"
/>
</mx:series>
</mx:HLOCChart>
<mx:Legend dataProvider="{mychart}"/>
</mx:Application>
<mx:Stroke id="axisStroke"
color="#884422"
weight="8"
alpha=".75"
caps="square"
/>
Using strokes
You use the Stroke class with the chart series and grid lines to control the properties of the
lines that Flex uses to draw chart elements.
The following table describes the properties that you use to control the appearance of strokes:
Property Description
color Specifies the color of the line as a hexadecimal value. The default value
is 0x000000, which corresponds to black.
weight Specifies the width of the line, in pixels. The default value is 0, which
corresponds to a hairline.
<mx:HLOCChart id="myChart"
dataProvider="{aapl}"
showDataTips="true"
>
<mx:horizontalAxisRenderer>
<mx:AxisRenderer
placement="bottom"
canDropLabels="true"
tickPlacement="inside"
tickLength="10"
minorTickPlacement="inside"
minorTickLength="5"
>
<mx:axisStroke>
<mx:Stroke color="#000080" weight="1"/>
</mx:axisStroke>
<mx:tickStroke>
<mx:Stroke color="#000060" weight="1"/>
</mx:tickStroke>
<mx:minorTickStroke>
<mx:Stroke color="#100040" weight="1"/>
</mx:minorTickStroke>
</mx:AxisRenderer>
</mx:horizontalAxisRenderer>
<mx:verticalAxis>
<mx:series>
<mx:HLOCSeries
dataProvider="{aapl}"
openField="open"
highField="high"
lowField="low"
closeField="close"
displayName="AAPL"
>
</mx:HLOCSeries>
</mx:series>
</mx:HLOCChart>
<mx:Legend dataProvider="{myChart}"/>
</mx:Application>
You can define a stroke object using an MXML tag, and then bind that stroke object to the
chart’s renderer properties. For an example, see “Applying styles by binding tag definitions”
on page 1715.
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month: "Jan", Profit: 2000, Expenses: 1500},
{Month: "Feb", Profit: 1000, Expenses: 200},
{Month: "Mar", Profit: 1500, Expenses: 500}
]);
<mx:Stroke id="baseAxisStroke"
color="0x884422"
weight="10"
alpha=".25"
caps="square"
/>
<mx:horizontalAxisRenderer>
<mx:AxisRenderer id="har1">
<mx:axisStroke>{baseAxisStroke}</mx:axisStroke>
</mx:AxisRenderer>
</mx:horizontalAxisRenderer>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Profit"
displayName="Profit"
/>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
/>
</mx:series>
</mx:ColumnChart>
<mx:Legend dataProvider="{myChart}"/>
</mx:Panel>
<mx:Button id="b1"
click="changeStroke(event)"
label="Change Stroke"
/>
</mx:Application>
Using fills
When charting multiple data series, or just to improve the appearance of your charts, you can
control the fill for each series in the chart or each item in a series. The fill lets you specify a
pattern that defines how Flex draws the chart element. You can also use fills to specify the
background colors of the chart or bands of background colors defined by the grid lines. Fills
can be solid or can use linear and radial gradients. A gradient specifies a gradual color
transition in the fill color.
You can use fills in the following ways:
■ fill — Set the value of the fill property on a series to a single fill. This applies that fill
to all chart items in that series. For example, all columns in a single series will have the
same fill.
■ fills — Set the value of the fills property on a series to an Array of fills. This applies a
different fill from the Array to each chart item in the series. For example, each column in
a series will have a different fill. The LineSeries and LineRenderer objects are not affected
by the fill property’s settings.
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
>
<mx:fill>
<mx:SolidColor color="0xFF99FF"/>
</mx:fill>
</mx:ColumnSeries>
</mx:series>
</mx:ColumnChart>
<mx:Legend dataProvider="{myChart}"/>
</mx:Panel>
</mx:Application>
]]>
</mx:Script>
<mx:Panel title="Column Chart">
<mx:ColumnChart id="myChart" dataProvider="{expenses}">
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"
/>
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Profit"
displayName="Profit"
fills="{warmColorsArray}"
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
fills="{coolColorsArray}"
>
</mx:ColumnSeries>
</mx:series>
</mx:ColumnChart>
</mx:Panel>
</mx:Application>
This example does not have a legend. If you use the fills property or the fillFunction to
define the fills of chart items, and you want a legend, you must manually create the Legend
object for that chart. For more information on creating Legend objects, see “Using Legend
controls” on page 1873.
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Expense:"Taxes", Amount:2000},
{Expense:"Rent", Amount:1000},
{Expense:"Bills", Amount:100}
]);
]]></mx:Script>
<mx:Panel title="Background Fill">
<mx:BarChart
dataProvider="{expenses}"
showDataTips="true"
>
<mx:verticalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Expense"
/>
</mx:verticalAxis>
<mx:fill>
<mx:SolidColor
color="0x66CCFF"
alpha=".5"
/>
</mx:fill>
<mx:series>
<mx:BarSeries xField="Amount"/>
</mx:series>
</mx:BarChart>
</mx:Panel>
</mx:Application>
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Expense:"Taxes", Amount:2000},
{Expense:"Rent", Amount:1100},
{Expense:"Bills", Amount:100}
]);
]]></mx:Script>
<mx:Style>
.myBarChartStyle {
fill:#FF0000;
}
</mx:Style>
]]>
</mx:Script>
<mx:Style>
.myRedColumnSeries {
fill:#FF0033;
}
.myGreenColumnSeries {
fill:#33FF00;
}
</mx:Style>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
]]>
</mx:Script>
<mx:Style>
.myRedColumnSeries {
fills: #FF0033, #FF3333, #FF6633;
}
.myGreenColumnSeries {
fills: #33FF00, #33FF33, #33FF66;
}
</mx:Style>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
Class Description
LinearGradient Defines a gradient fill that starts at a boundary of the chart element.
You specify an array of GradientEntry objects to control gradient
transitions with the LinearGradient object.
RadialGradient Defines a gradient fill that radiates from the center of a chart element.
You specify an array of GradientEntry objects to control gradient
transitions with the RadialGradient object.
GradientEntry Defines the objects that control the gradient transition. Each
GradientEntry object contains the following properties:
• color Specifies a color value.
• alpha Specifies the transparency. Valid values are 0 (invisible)
through 1 (opaque). The default value is 1.
• ratio Specifies where in the chart, as a percentage, Flex starts the
transition to the next color. For example, if you set the ratio
property to .33, Flex begins the transition 33% of the way through
the chart. If you do not set the ratio property, Flex tries to evenly
apply values based on the ratio properties for the other
GradientEntry objects. Valid values range from 0 to 1.
The following example uses a LinearGradient class with three colors for a gradient fill of the
chart’s background:
<?xml version="1.0"?>
<!-- charts/GradientFills.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Expense:"Taxes", Amount:2000},
{Expense:"Rent", Amount:1000},
{Expense:"Bills", Amount:100}
]);
]]></mx:Script>
<mx:Panel title="Background Fill">
<mx:BarChart
dataProvider="{expenses}"
showDataTips="true"
>
<mx:verticalAxis>
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Expense:"Taxes", Amount:2000},
{Expense:"Rent", Amount:1000},
{Expense:"Bills", Amount:100}
]);
]]></mx:Script>
<mx:Panel title="Background Fill">
<mx:BarChart dataProvider="{expenses}" showDataTips="true">
<mx:verticalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Expense"
/>
</mx:verticalAxis>
<mx:fill>
<mx:LinearGradient angle="90">
<mx:entries>
<mx:GradientEntry
color="0xC5C551"
ratio="0"
alpha="1"
/>
<mx:GradientEntry
color="0xFEFE24"
ratio=".33"
alpha="1"
/>
<mx:GradientEntry
color="0xECEC21"
ratio=".66"
alpha="1"
/>
</mx:entries>
</mx:LinearGradient>
</mx:fill>
<mx:series>
<mx:BarSeries xField="Amount"/>
</mx:series>
</mx:BarChart>
</mx:Panel>
Using filters
You can add filters such as drop shadows to your charts by using the classes in the flash.filters
package. These filters include:
■ BevelFilter
■ BitmapFilter
■ BlurFilter
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500},
{Month:"Feb", Profit:1000, Expenses:200},
{Month:"Mar", Profit:1500, Expenses:500}
]);
]]></mx:Script>
<mx:Panel>
<mx:ColumnChart id="column" dataProvider="{expenses}">
<!-- Add a custom drop shadow filter to the
ColumnChart control. -->
<mx:filters>
<flash:DropShadowFilter
distance="10"
color="0x666666"
alpha=".8"
/>
</mx:filters>
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"
/>
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Profit"
displayName="Profit"
/>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
/>
</mx:series>
</mx:ColumnChart>
<mx:Legend dataProvider="{column}"/>
</mx:Panel>
For more information on using filters, see “Using filters in Flex” on page 823.
Adding a drop shadow filter to some chart controls can have unexpected consequences. For
example, if you add a drop shadow filter to a PieChart control, Flex renders that drop shadow
filter in addition to the drop shadow filter that it applies to the PieSeries by default.
You can remove filters by setting the filters Array to an empty Array, as the following example
shows:
<?xml version="1.0"?>
<!-- charts/ClearFilters.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500, Amount:450},
{Month:"Feb", Profit:1000, Expenses:200, Amount:600},
{Month:"Mar", Profit:1500, Expenses:500, Amount:300}
]);
]]></mx:Script>
<mx:LineChart id="myChart" dataProvider="{expenses}">
<mx:seriesFilters>
<mx:Array/>
</mx:seriesFilters>
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"
/>
</mx:horizontalAxis>
<mx:series>
<mx:LineSeries
yField="Profit"
displayName="Profit"
/>
<mx:LineSeries
yField="Expenses"
displayName="Expenses"
/>
<mx:LineSeries
yField="Amount"
displayName="Amount"
/>
</mx:series>
applyFilters();
}
]]></mx:Script>
<mx:Panel>
<mx:ColumnChart id="myChart" dataProvider="{expenses}">
<mx:backgroundElements>
<mx:GridLines id="myGridlines"
horizontalChangeCount="1"
verticalChangeCount="1"
direction="both"
>
</mx:GridLines>
</mx:backgroundElements>
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"
/>
</mx:horizontalAxis>
<mx:horizontalAxisRenderer>
<mx:AxisRenderer id="myAxisRenderer"
placement="bottom"
canDropLabels="true"
>
<mx:axisStroke>
<mx:Stroke color="#000080" weight="10"/>
</mx:axisStroke>
<mx:tickStroke>
<mx:Stroke color="#000060" weight="5"/>
</mx:tickStroke>
<mx:minorTickStroke>
<mx:Stroke color="#100040" weight="5"/>
</mx:minorTickStroke>
</mx:AxisRenderer>
</mx:horizontalAxisRenderer>
<mx:series>
<mx:ColumnSeries id="s1"
xField="Month"
yField="Profit"
displayName="Profit"
/>
<mx:ColumnSeries id="s2"
xField="Month"
yField="Expenses"
displayName="Expenses"
/>
</mx:series>
</mx:ColumnChart>
<mx:Legend id="myLegend" dataProvider="{myChart}"/>
</mx:Panel>
You can include horizontal, vertical, or both grid lines in your chart with the GridLines
object. You can set these behind the data series by using the chart’s backgroundElements
property or in front of the data series by using the annotationElements property.
The following example turns on grid lines in both directions and applies them to the chart:
<?xml version="1.0"?>
<!-- charts/GridLinesBoth.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500},
{Month:"Feb", Profit:1000, Expenses:200},
{Month:"Mar", Profit:1500, Expenses:500}
]);
]]></mx:Script>
<mx:Array id="bge">
<mx:GridLines direction="both"/>
</mx:Array>
The annotationElements property refers to any chart elements that appear in the
foreground of your chart, and the backgroundElements property refers to any chart
elements that appear behind the chart’s data series.
You can also define the grid lines inside each chart control’s definition, as the following
example shows:
<?xml version="1.0"?>
<!-- charts/GridLinesBothInternal.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500},
{Month:"Feb", Profit:1000, Expenses:200},
{Month:"Mar", Profit:1500, Expenses:500}
]);
]]></mx:Script>
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"
/>
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Profit"
displayName="Profit"
/>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
/>
</mx:series>
For information on working with strokes, see “Using strokes” on page 1730. For more
information on using the backgroundElements and annotationElements properties, see
“Using ChartElement objects” on page 1717.
You can manipulate the appearance of the grid lines directly in MXML, with ActionScript, or
with CSS. The following sections describe techniques for formatting grid lines for Flex
Charting objects.
<mx:Array id="bge">
<mx:GridLines
horizontalChangeCount="1"
verticalChangeCount="1"
direction="both"
>
<mx:horizontalStroke>
<mx:Stroke weight="3"/>
</mx:horizontalStroke>
<mx:verticalStroke>
<mx:Stroke weight="3"/>
</mx:verticalStroke>
<mx:horizontalFill>
<mx:SolidColor color="0x99033" alpha=".66"/>
</mx:horizontalFill>
</mx:GridLines>
</mx:Array>
]]>
</mx:Script>
<mx:Array id="bge">
</mx:Array>
<mx:BubbleChart id="bc"
showDataTips="true"
backgroundElements="{bge}"
>
<mx:series>
<mx:BubbleSeries
dataProvider="{s1}"
displayName="series1"
xField="x"
yField="y"
radiusField="r1"
/>
</mx:series>
</mx:BubbleChart>
</mx:Application>
You can also change the appearance of grid lines by using filters such as a drop shadow, glow,
or bevel. For more information, see “Using filters” on page 1758.
<mx:Style>
.myStyle {
direction:"both";
horizontalShowOrigin:true;
horizontalTickAligned:false;
horizontalChangeCount:1;
verticalShowOrigin:false;
verticalTickAligned:true;
verticalChangeCount:1;
horizontalFill:#990033;
horizontalAlternateFill:#00CCFF;
}
</mx:Style>
<mx:Array id="bge">
<mx:GridLines styleName="myStyle">
<mx:horizontalStroke>
<mx:Stroke weight="3"/>
</mx:horizontalStroke>
<mx:verticalStroke>
<mx:Stroke weight="3"/>
</mx:verticalStroke>
</mx:GridLines>
</mx:Array>
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500},
{Month:"Feb", Profit:1000, Expenses:200},
{Month:"Mar", Profit:1500, Expenses:500}
]);
[Bindable]
public var bge:GridLines;
myChart.backgroundElements = [bge];
}
]]></mx:Script>
To rotate axis labels, you must embed the font in the Flex application. If you rotate the the
axis labels without embedding a font, they are rendered horizontally.
<mx:Style>
@font-face{
src: url("../assets/MyriadWebPro.ttf");
fontFamily: myMyriad;
}
ColumnChart {
fontFamily: myMyriad;
fontSize: 20;
}
</mx:Style>
<mx:Panel>
<mx:ColumnChart id="column" dataProvider="{expenses}">
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"
title="FY 2006"
/>
</mx:horizontalAxis>
<mx:horizontalAxisRenderer>
<mx:AxisRenderer labelRotation="45"/>
</mx:horizontalAxisRenderer>
<mx:verticalAxisRenderer>
<mx:AxisRenderer labelRotation="45"/>
</mx:verticalAxisRenderer>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Profit"
displayName="Profit"
BarChart BoxItemRenderer
BubbleChart CircleItemRenderer
ColumnChart CrossItemRenderer
PlotChart DiamondItemRenderer
ShadowBoxItemRenderer
TriangleItemRenderer
CandlestickChart CandlestickItemRenderer
HLOCChart HLOCItemRenderer
LineChart LineRenderer
ShadowLineRenderer
PieChart WedgeItemRenderer
The other series type that requires two renderers is the AreaSeries. The areaRenderer
property specifies the appearance of the area, and the itemRenderer specifies the appearance
of the data items.
You can also specify the renderer to use for the legend marker. The default is the class that the
series’ itemRenderer property specifies. For more information, see “Formatting Legend
controls” on page 1787.
You can use multiple types of data series in a single chart. For example, you can use a
ColumnSeries and a LineSeries to show something like a moving average over a stock price. In
this case, you can use all the renderers supported by those series in the same chart. For more
information on using multiple series, see “Using multiple data series” on page 1696.
[Bindable]
[Embed(source="../assets/bird.gif")]
public var myBird:Class;
[Bindable]
public var myBirdFactory:ClassFactory =
new ClassFactory(myBird);
]]></mx:Script>
<mx:Panel title="Plot Chart">
<mx:PlotChart id="myChart"
dataProvider="{expenses}"
showDataTips="true"
>
<mx:series>
import mx.charts.series.items.ColumnSeriesItem;
import mx.skins.ProgrammaticSkin;
import mx.core.IDataRenderer;
import flash.display.Graphics;
<mx:Panel>
<mx:ColumnChart id="column" dataProvider="{expenses}">
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"
/>
</mx:horizontalAxis>
<mx:series>
<mx:Array>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
itemRenderer="CycleColorRenderer"
/>
</mx:Array>
</mx:series>
</mx:ColumnChart>
</mx:Panel>
</mx:Application>
For more information on overriding the updateDisplayList() method, see “Implementing
the updateDisplayList() method” on page 908.
<mx:Style>
Legend {
labelPlacement:left;
markerHeight:30;
markerWidth:30;
}
</mx:Style>
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Expense:"Taxes", Amount:2000, Cost:321, Discount:131},
{Expense:"Rent", Amount:1000, Cost:95, Discount:313},
{Expense:"Bills", Amount:100, Cost:478, Discount:841}
]);
]]></mx:Script>
<mx:Script>
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Expense:"Taxes", Amount:2000, Cost:321, Discount:131},
{Expense:"Rent", Amount:1000, Cost:95, Discount:313},
{Expense:"Bills", Amount:100, Cost:478, Discount:841}
]);
</mx:Script>
</mx:Application>
[Bindable]
[Embed(source="../assets/bird.gif")]
public var myBird:Class;
[Bindable]
public var myBirdFactory:ClassFactory =
new ClassFactory(myBird);
]]></mx:Script>
<mx:Panel title="Plot Chart">
<mx:PlotChart id="myChart" dataProvider="{expenses}"
showDataTips="true">
<mx:series>
<!--
Each series uses the default renderer for
the ChartItems, but uses the same renderer
for legend markers.
-->
<mx:PlotSeries
xField="Expenses"
yField="Profit"
displayName="Plot 1"
legendMarkerRenderer=
"mx.charts.renderers.DiamondItemRenderer"
/>
<mx:PlotSeries
xField="Amount"
yField="Expenses"
displayName="Plot 2"
legendMarkerRenderer=
<mx:PlotSeries
xField="Profit"
yField="Amount"
displayName="Plot 3"
legendMarkerRenderer=
"mx.charts.renderers.DiamondItemRenderer"
/>
</mx:series>
</mx:PlotChart>
<mx:Legend dataProvider="{myChart}"/>
</mx:Panel>
</mx:Application>
If you do not explicitly set the legendMarkerRenderer property, the property uses the
default class that the series’s itemRenderer style property specifies. Each series has a default
renderer that is used if neither of these style properties is specified.
You can create your own custom legend marker class. Classes used as legend markers must
implement the IFlexDisplayObject interface and, optionally, the ISimpleStyleClient and
IDataRenderer interfaces.
For more information on available renderer classes, see “Skinning ChartItem objects”
on page 1779.
CHAPTER 49
Contents
Working with axes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1795
About the CategoryAxis class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1796
About the NumericAxis class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1799
Adding axis titles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1818
Defining axis labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1822
Using data labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1829
Using DataTips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1844
Using per-item fills . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1856
Using the minField property . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1865
Stacking charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1867
Using Legend controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1873
1795
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
About the CategoryAxis class
The CategoryAxis class maps discrete categorical data (such as states, product names, or
department names) to an axis and spaces them evenly along it. This axis accepts any data type
that can be represented by a String.
The dataProvider property of the CategoryAxis object defines the data provider that
contains the text for the labels. In most cases, this can be the same data provider as the chart’s
data provider. A CategoryAxis object used in a chart inherits its dataProvider property from
the containing chart, so you are not required to explicitly set the dataProvider property on a
CategoryAxis object.
[Bindable]
public var months:Array = [
{Month:"January", monthAbbrev:"Jan"},
{Month:"February", monthAbbrev:"Feb"},
{Month:"March", monthAbbrev:"Mar"}
];
]]></mx:Script>
<mx:Panel title="Line Chart">
<mx:AreaChart
dataProvider="{expenses}"
showDataTips="true"
>
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{months}"
categoryField="Month"
/>
</mx:horizontalAxis>
<mx:series>
<mx:AreaSeries
yField="Profit"
displayName="Profit"
/>
<mx:AreaSeries
yField="Expenses"
displayName="Expenses"
/>
</mx:series>
</mx:AreaChart>
</mx:Panel>
</mx:Application>
[Bindable]
public var stocks:ArrayCollection = new ArrayCollection([
{date:"2005/8/4", SMITH:37.23},
{date:"2005/8/5", SMITH:56.53},
{date:"2005/8/6", SMITH:17.67},
{date:"2005/8/7", SMITH:27.72},
{date:"2005/8/8", SMITH:85.23}
]);
]]>
</mx:Script>
<mx:LineChart id="mychart"
dataProvider="{stocks}"
showDataTips="true"
height="300"
width="400"
>
<mx:verticalAxis>
<mx:LinearAxis
title="linear axis"
minimum="10"
maximum="100"
interval="10"
/>
</mx:verticalAxis>
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="date"/>
</mx:horizontalAxis>
<mx:series>
<mx:LineSeries
yField="SMITH"
displayName="SMITH close"
/>
[Bindable]
public var stocks:ArrayCollection = new ArrayCollection([
{date:"2005/8/4", SMITH:37.23, DECKER:1500},
{date:"2005/8/5", SMITH:56.53, DECKER:1210},
{date:"2005/8/6", SMITH:17.67, DECKER:1270},
{date:"2005/8/7", SMITH:27.72, DECKER:1370},
{date:"2005/8/8", SMITH:85.23, DECKER:1530}
]);
]]>
</mx:Script>
<mx:LineChart id="mychart"
dataProvider="{stocks}"
showDataTips="true"
height="300"
width="400"
>
<mx:verticalAxis>
<mx:LogAxis title="log axis"
interval="10"
minimum="10"
maximum="10000"
/>
</mx:verticalAxis>
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="date"/>
</mx:horizontalAxis>
<mx:series>
<mx:LineSeries yField="DECKER" displayName="DECKER close"/>
<mx:LineSeries yField="SMITH" displayName="SMITH close" />
</mx:series>
</mx:LineChart>
</mx:Application>
Valid values for the dataUnits property are milliseconds, seconds, minutes, hours, days,
weeks, months , and years.
When assigning appropriate label units, a DateTimeAxis object does not assign any unit
smaller than the units represented by the data. If the dataUnits property is set to days, the
chart does not render labels for every hour, no matter what the minimum or maximum range
is. To achieve this, you must set the value explicitly.
When using the DateTimeAxis class, you can filter out units when you set the dataUnits
property to days. This lets you create a chart that shows a "work week" or some other
configuration that omits certain days of the week. For more information, see “Omitting days
on a DateTimeAxis” on page 1810.
Some series use the value of the dataUnits property to affect their rendering. Specifically,
most columnar series (such as Column, Bar, Candlestick, and HLOC controls) use the value
of dataUnits to determine how wide to render their columns. If, for example, the
ColumnChart control’s horizontal axis has its dataUnits set to weeks and dataUnits set to
days, the ColumnChart control renders each column at one-seventh the distance between
labels.
You can restrict the list of valid units for a particular chart instance to a subset that makes
sense for the use case. As with a LinearAxis object, you can specify minimum, maximum, and
interval values for a DateTimeAxis object.
When rounding off values, the DateTimeAxis object determines if values passed to it should
be displayed in the local time zone or UTC. You can set the displayLocalTime property to
true to instruct the DateTimeAxis object to treat values as local time values. The default
value is false.
To change the values of the labels, use the labelFunction property of the DateTimeAxis
object. This property is inherited from the NumericAxis class and is described in “Defining
axis labels” on page 1822.
]]></mx:Script>
<mx:Panel title="DateTimeAxis" width="100%" height="100%">
<mx:ColumnChart id="mychart"
dataProvider="{myData}"
showDataTips="true"
>
<mx:horizontalAxis>
<mx:DateTimeAxis
dataUnits="months"
minimum="{minDate}"
maximum="{maxDate}"
/>
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries
yField="amt"
xField="date"
displayName="My Data"
/>
</mx:series>
</mx:ColumnChart>
]]></mx:Script>
<mx:Panel title="DateTimeAxis" width="100%" height="100%">
<mx:LineChart id="mychart"
[Bindable]
private var offRanges:Array = new Array ([]);
]]></mx:Script>
<mx:Panel title="DateTimeAxis" width="100%" height="100%">
<mx:LineChart id="mychart"
dataProvider="{aapl}"
showDataTips="true"
>
<mx:horizontalAxis>
<mx:DateTimeAxis
dataUnits="days"
parseFunction="myParseFunction"
disabledRanges="{offRanges}"
/>
</mx:horizontalAxis>
<mx:series>
<mx:LineSeries
id="mySeries"
yField="close"
xField="date"
displayName="AAPL"
/>
</mx:series>
</mx:LineChart>
</mx:Panel>
</mx:Application>
[Bindable]
public var aapl:ArrayCollection = new ArrayCollection([
{date:"08/01/2007", close:42},
{date:"08/02/2007", close:43},
{date:"08/03/2007", close:43},
{date:"08/06/2007", close:42},
{date:"08/07/2007", close:38},
{date:"08/08/2007", close:37},
{date:"08/09/2007", close:39},
{date:"08/10/2007", close:41},
{date:"08/13/2007", close:45},
{date:"08/14/2007", close:47},
{date:"08/15/2007", close:48},
{date:"08/16/2007", close:42},
{date:"08/17/2007", close:43},
{date:"08/20/2007", close:45},
{date:"08/21/2007", close:50},
{date:"08/22/2007", close:51},
{date:"08/23/2007", close:55},
{date:"08/24/2007", close:51},
{date:"08/27/2007", close:49},
{date:"08/28/2007", close:51},
{date:"08/29/2007", close:50},
{date:"08/30/2007", close:49},
{date:"08/31/2007", close:54}
]);
[Bindable]
private var dateChooserDisabledRanges:Array = [];
[Bindable]
private var offRanges:Array = new Array([]);
]]></mx:Script>
<mx:Panel title="DateTimeAxis" width="100%" height="100%">
<mx:HBox>
<mx:LineChart id="mychart"
dataProvider="{aapl}"
showDataTips="true"
>
<mx:horizontalAxis>
<mx:DateTimeAxis
id="dtAxis"
dataUnits="days"
disabledDays="{offDays}"
disabledRanges="{offRanges}"
/>
<mx:verticalAxis>
<mx:LinearAxis minimum="30" maximum="60"/>
</mx:verticalAxis>
<mx:series>
<mx:LineSeries
id="series1"
yField="close"
xField="date"
displayName="AAPL"
/>
</mx:series>
</mx:LineChart>
<mx:DateChooser id="dc1"
showToday="false"
click="onDateChange(event)"
displayedMonth="7"
displayedYear="2007"
disabledRanges="{dateChooserDisabledRanges}"
/>
</mx:HBox>
<mx:Button id="b1" label="Refresh" click="clearAllDisabledDates()"/>
<mx:TextArea id="ta1" width="600" height="400"/>
</mx:Panel>
</mx:Application>
]]></mx:Script>
<mx:Style>
.myStyle {
fontFamily:Verdana;
fontSize:12;
color:#4691E1;
fontWeight:bold;
fontStyle:italic;
}
</mx:Style>
<mx:Panel>
<mx:ColumnChart id="myChart"
axisTitleStyleName="myStyle"
dataProvider="{expenses}"
>
<mx:verticalAxis>
<mx:LinearAxis id="la1"/>
</mx:verticalAxis>
<mx:horizontalAxis>
<mx:Style>
@font-face{
src:url("../assets/MyriadWebPro.ttf");
fontFamily:myMyriad;
}
.myEmbeddedStyle {
fontFamily:myMyriad;
fontSize:20;
}
</mx:Style>
<mx:Panel>
<mx:ColumnChart id="column"
<mx:Style>
.axisTitles {
color:red;
fontWeight:bold;
fontFamily:Arial;
fontSize:20;
}
ColumnChart {
axisTitleStyleName:axisTitles;
}
</mx:Style>
<mx:Panel>
<mx:ColumnChart id="column" dataProvider="{expenses}">
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month" title="FY 2006"
/>
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Profit"
displayName="Profit"
/>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
/>
</mx:series>
</mx:ColumnChart>
<mx:horizontalAxisRenderer>
<mx:AxisRenderer showLabels="false"/>
</mx:horizontalAxisRenderer>
<mx:verticalAxisRenderer>
<mx:AxisRenderer showLabels="false"/>
</mx:verticalAxisRenderer>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Profit"
displayName="Profit"
/>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
/>
</mx:series>
</mx:ColumnChart>
<mx:Legend dataProvider="{column}"/>
</mx:Panel>
</mx:Application>
Parameter Description
labelValue The value of the current label.
previousLabelValue The value of the label preceding this label. If this is the first label, the
value of previousLabelValue is null.
axis The axis object, such as CategoryAxis or NumericAxis.
labelItem A reference to the label object. This argument is only passed in for a
CategoryAxis object. For NumericAxis subclasses such as LogAxis,
DateTimeAxis, and LinearAxis objects, you omit this argument.
This object contains a name/value pair for the chart data. For
example, if the data provider defines the Month, Profit, and Expenses
fields, this object might look like the following:
Profit:1500
Month:Mar
Expenses:500
You can access the values in this object by using dot-notation for
dynamic objects, as the following example shows:
return "$" + labelItem.Profit;
return_type The type of object that the callback function returns. This can be any
object type, but is most commonly a String for CategoryAxis axes, a
Number for NumericAxis objects, or a Date object for DateTimeAxis
objects.
When you use the labelFunction, you must be sure to import the class of the axis or the
entire charts package; for example:
import mx.charts.*;
The following example defines a labelFunction for the horizontal CategoryAxis object. In
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month: "Jan", Income: 2000, Expenses: 1500},
{Month: "Feb", Income: 1000, Expenses: 200},
{Month: "Mar", Income: 1500, Expenses: 500}
]);
]]></mx:Script>
<mx:Panel>
<mx:ColumnChart id="column" dataProvider="{expenses}">
<mx:horizontalAxis>
<mx:CategoryAxis
categoryField="Month"
title="Expenses"
labelFunction="defineLabel"
/>
</mx:horizontalAxis>
<mx:verticalAxis>
<mx:LinearAxis
title="Income"
minimum="0"
maximum="2500"
labelFunction="defineVerticalLabel"
/>
</mx:verticalAxis>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Income"
displayName="Income"
/>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
/>
</mx:series>
</mx:ColumnChart>
</mx:Panel>
</mx:Application>
In the previous example, if you use a CategoryAxis but do not specify the value of the
categoryField property on the axis, the label format function receives an object rather than
a value for the first argument. In that case, you must drill down into the object to return a
formatted String.
Another way to customize the labels on an axis is to set a custom data provider for the labels.
This can be done if you are using the CategoryAxis and not the NumericAxis class for the axis
values. For more information, see “About the CategoryAxis class” on page 1796.
Property Description
minimum The lowest value of the axis.
maximum The highest value of the axis.
interval The number of units between values along the axis.
[Bindable]
public var stocks:ArrayCollection = new ArrayCollection([
{date:"2005/8/4", SMITH:37.23},
{date:"2005/8/5", SMITH:56.53},
{date:"2005/8/6", SMITH:17.67},
{date:"2005/8/7", SMITH:27.72},
{date:"2005/8/8", SMITH:85.23}
]);
]]>
</mx:Script>
<mx:LineChart id="mychart"
dataProvider="{stocks}"
showDataTips="true"
height="300"
width="400"
>
<mx:verticalAxis>
<mx:LinearAxis
title="linear axis"
minimum="10"
maximum="100"
interval="10"
/>
</mx:verticalAxis>
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="date"/>
</mx:horizontalAxis>
<mx:series>
<mx:LineSeries
yField="SMITH"
displayName="SMITH close"
/>
</mx:series>
</mx:LineChart>
</mx:Application>
In this example, the minimum value displayed along the y-axis is 10, the maximum value is
100, and the interval is 10. Therefore, the label text is 10, 20, 30, 40, and so on.
To set the minimum and maximum values on a DateTimeAxis, you must use Date objects
rather than Strings or Numbers in the axis’s tag. For more information, see “Setting minimum
and maximum values on a DateTimeAxis” on page 1808.
For information about setting the length and location of tick marks, see “Formatting tick
marks” on page 1725.
DataTip
Data labels
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Income:2000, Expenses:1500},
{Month:"Feb", Income:1000, Expenses:200},
{Month:"Mar", Income:1500, Expenses:500}
]);
]]></mx:Script>
<mx:verticalAxis>
<mx:LinearAxis minimum="0" maximum="2500"/>
<mx:series>
<mx:ColumnSeries
id="cs1"
xField="Month"
yField="Income"
displayName="Income"
/>
<mx:ColumnSeries
id="cs2"
xField="Month"
yField="Expenses"
displayName="Expenses"
/>
</mx:series>
</mx:ColumnChart>
<mx:Button id="b1"
label="Change Label Location"
click="changeLabelLocation()
/>
</mx:Panel>
</mx:Application>
The contents of the data label is determined by several factors, in order of precedence:
■ labelField — Specifies a field in the data provider that sets the contents of the data
label. This overrides any method specified by the labelFunction property.
■ labelFunction — Specifies a method that takes several arguments and returns a String
that the chart series uses for the data label’s contents. For more information, see
“Customizing data label values” on page 1838.
If you set the labelPosition property to inside, you cannot rotate data labels.
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Income:2000, Expenses:1500},
{Month:"Feb", Income:1000, Expenses:200},
{Month:"Mar", Income:1500, Expenses:500}
]);
/*
Style properties on series that affect data labels:
fontFamily; fontSize; fontStyle; fontWeight;
labelPosition; labelRotation; labelSizeLimit
*/
]]></mx:Script>
<mx:Style>
.incomeSeries {
fontSize:9;
fontWeight:bold;
labelPosition:inside;
labelAlign:top;
}
.expensesSeries {
fontSize:8;
labelPosition:inside;
labelAlign:middle;
}
</mx:Style>
<mx:verticalAxis>
<mx:LinearAxis minimum="0" maximum="2500"/>
</mx:verticalAxis>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Income"
displayName="Income"
styleName="incomeSeries"
/>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
styleName="expensesSeries"
/>
</mx:series>
</mx:ColumnChart>
</mx:Panel>
</mx:Application>
Labels are scaled and possibly truncated if they are too big for the area. Labels will never
overlap each other or other chart elements.
For PieSeries objects, you can also specify the gap and stroke of callout lines that associate a
data label with a particular wedge in the pie. For more information, see “Using data labels
with PieChart controls” on page 1685.
You can only set the labelAlign style is the labelPosition property is set to inside. Label
alignment is ignored if the labelPosition is outside.
You cannot change the alignment of data labels on a PieSeries object.
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Income:2000, Expenses:1500},
{Month:"Feb", Income:1000, Expenses:200},
{Month:"Mar", Income:1500, Expenses:500}
]);
]]></mx:Script>
<mx:Style>
@font-face{
src: url("../assets/MyriadWebPro.ttf");
fontFamily: myMyriad;
}
ColumnSeries {
labelPosition:outside;
labelRotation:45;
}
ColumnChart {
fontFamily: myMyriad;
}
</mx:Style>
<mx:horizontalAxisRenderer>
<mx:AxisRenderer labelRotation="45"/>
</mx:horizontalAxisRenderer>
<mx:verticalAxis>
<mx:LinearAxis minimum="0" maximum="2500"/>
</mx:verticalAxis>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Income"
displayName="Income"
/>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
/>
</mx:series>
</mx:ColumnChart>
</mx:Panel>
</mx:Application>
You can only rotate data labels if the series’s labelPosition property is set to outside. You
cannot rotate data labels if the labelPosition property of the series is set to inside.
If by rotating labels, you cause them to overlap each other or overlap chart elements, then Flex
repositions them. If there is not enough space to reposition the labels, flex then scales and
ultimately truncates the labels. Data labels will never overlap each other or the underlying
chart elements.
For more information on embedding fonts, see “Using embedded fonts” on page 838.
The following table describes the parameters of the labelFunction callback function for a
ColumnSeries or BarSeries object:
Parameter Description
element A reference to the ChartItem that this data label applies to. The
ChartItem represents a single data point in a series.
series A reference to the series that this data label is used on.
When you customize the value of the data label, you typically get a reference to the series
item. You do this by casting the element argument to a specific chart item type (BarSeriesItem
or ColumnSeriesItem). You then point to either the yNumber or xNumber property to get the
underlying data.
You can also get a reference to the current series by casting the series argument to the specific
series type (ColumnSeries or BarSeries). This lets you access properties such as the yField or
xField.
import mx.charts.ChartItem;
import mx.charts.chartClasses.Series;
import mx.charts.series.items.ColumnSeriesItem;
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Income:2000, Expenses:1500},
{Month:"Feb", Income:1000, Expenses:200},
{Month:"Mar", Income:1500, Expenses:500}
]);
]]></mx:Script>
<mx:verticalAxis>
<mx:LinearAxis minimum="0" maximum="3000"/>
<mx:series>
<mx:ColumnSeries
labelPosition="outside"
xField="Month"
yField="Income"
displayName="Income"
labelFunction="setCustomLabel"
/>
<mx:ColumnSeries
labelPosition="outside"
xField="Month"
yField="Expenses"
displayName="Expenses"
labelFunction="setCustomLabel"
/>
</mx:series>
</mx:ColumnChart>
</mx:Panel>
</mx:Application>
You can also access the specific field in the data provider that provides the data. For example,
in the previous example, you could get the value of the data item (in this case, the value of the
Income field) by using code similar to the following:
var data:ColumnSeriesItem = ColumnSeriesItem(element);
var s:String = data.item.Income;
return s;
This is not a recommended practice, however, because it makes the callback function less
reusable and can force you to use additional code to detect which column you are providing
data labels for.
The following table describes the parameters of the labelFunction callback function for a
PieSeries:
Parameter Description
data A reference to the data point that chart element represents; type
Object.
field The field name from the data provider; type String.
Using DataTips
DataTips are similar to Flex ToolTip objects in that they cause a small pop-up window to
appear that shows the data value for the data point under the mouse pointer. You use the
showDataTips property of chart controls to enable DataTip objects.
N OTE
DataTip controls and data labels are not the same, although they can show the same
information. Data labels are always visible regardless of the location of the user’s mouse
pointer. For more information about data labels, see “Using data labels” on page 1829.
<mx:horizontalAxis>
<mx:LinearAxis displayName="Amount"/>
</mx:horizontalAxis>
<mx:series>
<mx:BarSeries
yField="Month"
xField="Profit"
displayName="Profit"
/>
<mx:BarSeries
yField="Month"
xField="Expenses"
displayName="Expenses"
/>
</mx:series>
</mx:BarChart>
<mx:Legend dataProvider="{myChart}"/>
</mx:Panel>
</mx:Application>
The default value of dataTipMode depends on the chart type. Its setting is based on the
likelihood that there are overlapping DataTips in that chart type. The default value of the
dataTipMode property for the following chart types is single:
■ BarChart
■ CandlestickChart
■ ColumnChart
■ HLOCChart
■ PieChart
The default value is multiple for the dataTipMode property for all other chart types.
To determine the size of the interactive area around a data point, you set the
mouseSensitivity property. The mouseSensitivity property configures the distance, in
pixels, around the data points where Flex reacts to mouse events such as click and
mouseOver. With this property, you can trigger DataTips to appear when the user moves the
mouse pointer near the data point rather than onto the data point. For more information, see
“Changing mouse sensitivity” on page 1895.
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500},
{Month:"Feb", Profit:1000, Expenses:200},
{Month:"Mar", Profit:1500, Expenses:500}
]);
<mx:horizontalAxis>
<mx:LinearAxis displayName="Amount"/>
</mx:horizontalAxis>
<mx:series>
<mx:BarSeries
yField="Month"
xField="Profit"
displayName="Profit"
/>
<mx:BarSeries
yField="Month"
xField="Expenses"
displayName="Expenses"
[Bindable]
public var dataSet:ArrayCollection = new ArrayCollection([
{Month:"Jan", Expenses:1500, Income:1590},
{Month:"Feb", Expenses:1200, Income:1300},
{Month:"Mar", Expenses:750, Income:900}
]);
]]></mx:Script>
<mx:Panel title="Casting HitData Objects">
<mx:ColumnChart id="myChart"
dataProvider="{dataSet}"
showDataTips="true"
dataTipFunction="myDataTipFunction"
>
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="Month"/>
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries
yField="Expenses"
displayName="Expenses '06"
/>
[Bindable]
public var dataSet:ArrayCollection = new ArrayCollection([
{Month:"Jan", Income:1500, Profit:90},
{Month:"Feb", Income:1200, Profit:100},
{Month:"Mar", Income:750, Profit:150}
]);
var s:String;
s = "<B>" + ColumnSeries(e.element).displayName + "</B>\n";
Argument Description
element The chart item for which the fill is created.
index The index of the chart item in the series’s data provider.
The fillFunction returns a Fill object (an object that implements the IFill interface). This
object is typically an instance of the SolidColor class, but it can also be of type BitmapFill,
LinearGradient, or RadialGradient. For information on working with gradients, see “Using
gradient fills with chart controls” on page 1751.
The returned fill from a fillFunction takes precedence over fills that are set with traditional
style methods. For example, if you set the value of the fill or fills property of a series and
also specify a fillFunction, the fills are ignored and the fill returned by the fillFunction is
used when rendering the chart items in the series.
import mx.graphics.IFill;
import mx.graphics.SolidColor;
import mx.collections.ArrayCollection;
import mx.charts.ChartItem;
import mx.charts.series.items.ColumnSeriesItem;
[Bindable]
public var sales:ArrayCollection = new ArrayCollection([
{ Name:"Reiner", CurrentAmount:69000 },
{ Name:"Klaus", CurrentAmount:38000 },
{ Name:"Alan", CurrentAmount:44000 },
{ Name:"Wolfgang", CurrentAmount:33000 },
{ Name:"Francis", CurrentAmount:20000 },
{ Name:"Klaus-Jurgen", CurrentAmount:55000 },
{ Name:"Martin", CurrentAmount:70000 },
{ Name:"Mac", CurrentAmount:35000 },
{ Name:"Friedemann", CurrentAmount:38000 },
{ Name:"Bruno", CurrentAmount:40000 }
]);
]]>
</mx:Script>
<mx:series>
<mx:ColumnSeries id="currSalesSeries"
xField="Name"
yField="CurrentAmount"
fillFunction="myFillFunction"
displayName="Current Sales"
/>
</mx:series>
</mx:ColumnChart>
<mx:Legend>
<mx:LegendItem label="More than $50K" fontWeight="bold">
<mx:fill>
<mx:SolidColor color="0x00FF00"/>
</mx:fill>
<mx:stroke>
<mx:Stroke color="0x000000" weight="1"/>
</mx:stroke>
</mx:LegendItem>
<mx:LegendItem label="Less than $50K" fontWeight="bold">
<mx:fill>
<mx:SolidColor color="0xFF0000"/>
</mx:fill>
<mx:stroke>
<mx:Stroke color="0x000000" weight="1"/>
</mx:stroke>
</mx:LegendItem>
</mx:Legend>
</mx:Panel>
</mx:Application>
This example defines custom entries in the Legend. If you use the fillFunction to define
the fills of chart items, and you want a Legend control in your chart, then you must manually
create the Legend object and its LegendItem objects. For more information on creating
Legend and LegendItem objects, see “Using Legend controls” on page 1873.
import mx.graphics.IFill;
import mx.graphics.SolidColor;
import mx.collections.ArrayCollection;
import mx.charts.ChartItem;
import mx.charts.series.items.ColumnSeriesItem;
[Bindable]
public var sales:ArrayCollection = new ArrayCollection([
{ Name:"Reiner", CurrentAmount:69000 },
{ Name:"Klaus", CurrentAmount:38000 },
{ Name:"Alan", CurrentAmount:44000 },
{ Name:"Wolfgang", CurrentAmount:33000 },
{ Name:"Francis", CurrentAmount:20000 },
{ Name:"Klaus-Jurgen", CurrentAmount:55000 },
{ Name:"Martin", CurrentAmount:70000 },
{ Name:"Mac", CurrentAmount:35000 },
{ Name:"Friedemann", CurrentAmount:38000 },
{ Name:"Bruno", CurrentAmount:40000 }
]);
if (index == 0) {
// The first column should be green, no matter the value.
return c;
} else {
var prevVal:Number =
Number(currSalesSeries.items[index - 1].yValue);
var curVal:Number =
Number(currSalesSeries.items[index].yValue);
var diff:Number = curVal - prevVal;
if (diff >= 0) {
// Current column's value is greater than the previous.
return c;
]]>
</mx:Script>
<mx:series>
<mx:ColumnSeries id="currSalesSeries"
xField="Name"
yField="CurrentAmount"
fillFunction="myFillFunction"
displayName="Current Sales"
/>
</mx:series>
</mx:ColumnChart>
<mx:Legend>
<mx:LegendItem label="More than Previous" fontWeight="bold">
<mx:fill>
<mx:SolidColor color="0x00FF00"/>
</mx:fill>
<mx:stroke>
<mx:Stroke color="0x000000" weight="1"/>
</mx:stroke>
</mx:LegendItem>
<mx:LegendItem label="Less than Previous" fontWeight="bold">
<mx:fill>
<mx:SolidColor color="0xFF0000"/>
</mx:fill>
<mx:stroke>
<mx:Stroke color="0x000000" weight="1"/>
import mx.graphics.IFill;
import mx.graphics.SolidColor;
import mx.collections.ArrayCollection;
import mx.charts.ChartItem;
import mx.charts.series.items.ColumnSeriesItem;
[Bindable]
public var sales:ArrayCollection = new ArrayCollection([
{ Name:"Reiner", SalesGoal:65000, CurrentAmount:69000 },
{ Name:"Klaus", SalesGoal:40000, CurrentAmount:38000 },
{ Name:"Alan", SalesGoal:40000, CurrentAmount:44000 },
{ Name:"Wolfgang", SalesGoal:48000, CurrentAmount:33000 },
{ Name:"Francis", SalesGoal:22000, CurrentAmount:20000 },
{ Name:"Klaus-Jurgen", SalesGoal:50000, CurrentAmount:55000 },
{ Name:"Martin", SalesGoal:44000, CurrentAmount:70000 },
{ Name:"Mac", SalesGoal:40000, CurrentAmount:35000 },
{ Name:"Friedemann", SalesGoal:38000, CurrentAmount:38000 },
{ Name:"Bruno", SalesGoal:42000, CurrentAmount:40000 }
]);
trace("--------------------------------------------------");
trace("Item index: " + index);
trace("Sales Person: " + item.xValue);
trace("Current Amount: " + currSalesSeries.items[index].yValue);
trace("Sales Goal: " + item.yValue);
if (diff >= 0) {
// Sales person met their goal.
return c;
} else if (diff < 0) {
// Sales person did not meet their goal.
c.color = 0xFF0000;
c.alpha = .2;
}
return c;
}
]]>
</mx:Script>
<mx:series>
<mx:ColumnSeries id="currSalesSeries"
xField="Name"
yField="CurrentAmount"
displayName="Current Sales"
>
<mx:fill>
<mx:SolidColor color="0x00FF00"/>
</mx:fill>
</mx:ColumnSeries>
<mx:ColumnSeries id="salesGoalSeries"
xField="Name"
yField="SalesGoal"
fillFunction="myFillFunction"
Stacking charts
When you chart multiple data series using the AreaChart, BarChart, and ColumnChart
controls, you can control how Flex displays the series using the type property of the controls.
The following table describes the values that the type property supports:
Property Description
clustered Chart elements for each series are grouped by category. This is the
default value for BarChart and ColumnChart controls.
overlaid Chart elements for each series are rendered on top of each other, with the
element corresponding to the last series on top. This is the default value
for AreaChart controls.
The following example creates an AreaChart control that has four data series, stacked on top
of each other:
<?xml version="1.0"?>
<!-- charts/AreaStacked.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500, Amount:450},
{Month:"Feb", Profit:1000, Expenses:200, Amount:600},
{Month:"Mar", Profit:1500, Expenses:500, Amount:300}
]);
]]></mx:Script>
<mx:Panel title="Stacked AreaChart">
<mx:AreaChart
dataProvider="{expenses}"
showDataTips="true"
type="stacked"
>
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"
/>
</mx:horizontalAxis>
<mx:series>
<mx:AreaSeries
yField="Profit"
displayName="Profit"
/>
<mx:AreaSeries
yField="Expenses"
displayName="Expenses"
/>
</mx:series>
</mx:AreaChart>
</mx:Panel>
</mx:Application>
With an overlay, the last series appears on top, and can obscure the data series below it unless
you use the alpha property of the fill to make it transparent. For more information, see
“Using fills” on page 1738.
You can use the ColumnSet, BarSet, and AreaSet classes to combine groups of chart series,
and thereby use different types of series within the same chart. The following example uses
BarSet classes to combine clustered and stacked BarSeries in a single chart. The example
shows how to do this in MXML and ActionScript:
<?xml version="1.0"?>
<!-- charts/UsingBarSets.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp()">
<mx:Script><![CDATA[
import mx.charts.Legend;
import mx.charts.BarChart;
import mx.charts.series.BarSet;
import mx.charts.series.BarSeries;
import mx.collections.ArrayCollection;
[Bindable]
private var yearlyData:ArrayCollection = new ArrayCollection([
{month:"January", revenue:120, costs:45,
overhead:102, oneTime:23},
{month:"February", revenue:108, costs:42,
overhead:87, oneTime:47},
{month:"March", revenue:150, costs:82,
overhead:32, oneTime:21},
panel2.addChild(c);
panel2.addChild(l);
}
]]></mx:Script>
Marker Label
For information on styling Legend controls, see “Formatting Legend controls” on page 1787.
<mx:Script>
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Expense:"Taxes", Amount:2000, Cost:321, Discount:131},
{Expense:"Rent", Amount:1000, Cost:95, Discount:313},
{Expense:"Bills", Amount:100, Cost:478, Discount:841}
]);
</mx:Script>
</mx:Application>
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
import mx.charts.Legend;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Expense:"Taxes", Amount:2000, Cost:321, Discount:131},
{Expense:"Rent", Amount:1000, Cost:95, Discount:313},
{Expense:"Bills", Amount:100, Cost:478, Discount:841}
]);
</mx:Application>
The Legend control creates the legend using information from the chart control. It matches
the colors and names of the LegendItem markers to the fills and labels of the chart’s data
series. In the previous example, Flex uses the BarSeries control’s displayName property to
define the LegendItem label.
Legend controls require that elements of the charts are named. If they are not named, the
Legend markers appear, but without labels.
A Legend control for a PieChart control uses the nameField property of the data series to find
values for the legend. The values that the nameField property point to must be Strings.
The following example sets the nameField property of a PieChart control’s data series to
Expense. Flex uses the value of the Expense field in the data provider in the Legend control.
<?xml version="1.0"?>
<!-- charts/LegendNameField.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Expense:"Taxes", Amount:2000},
{Expense:"Rent", Amount:1000},
{Expense:"Food", Amount:200}
]);
</mx:Script>
</mx:Application>
The nameField property also defines the series for the DataTips and labels.
[Bindable]
public var SMITH:ArrayCollection = new ArrayCollection([
{date: "22-Aug-05", close: 41.87},
{date: "23-Aug-05", close: 45.74},
{date: "24-Aug-05", close: 42.77},
{date: "25-Aug-05", close: 48.06},
]);
[Bindable]
public var DECKER:ArrayCollection = new ArrayCollection([
{date: "22-Aug-05", close: 157.59},
{date: "23-Aug-05", close: 160.3},
{date: "24-Aug-05", close: 150.71},
{date: "25-Aug-05", close: 156.88},
]);
]]></mx:Script>
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{SMITH}"
categoryField="date"
/>
</mx:horizontalAxis>
<mx:verticalAxis>
<mx:LinearAxis minimum="40" maximum="50"/>
</mx:verticalAxis>
<mx:series>
<mx:ColumnSeries id="cs1"
<mx:secondVerticalAxis>
<mx:LinearAxis minimum="150" maximum="170"/>
</mx:secondVerticalAxis>
<mx:secondSeries>
<mx:LineSeries id="cs2"
dataProvider="{DECKER}"
xField="date"
yField="close"
displayName="DECKER"
/>
</mx:secondSeries>
</mx:ColumnChart>
<mx:Legend>
<mx:LegendItem label="SMITH" fontWeight="bold">
<mx:fill>
<mx:SolidColor color="0xFF9900"/>
</mx:fill>
<mx:stroke>
<mx:Stroke color="0x000000" weight="1"/>
</mx:stroke>
</mx:LegendItem>
<mx:LegendItem label="DECKER" fontWeight="bold">
<mx:fill>
<mx:SolidColor color="{0x999933}"/>
</mx:fill>
<mx:stroke>
<mx:Stroke color="0x000000" weight="1"/>
</mx:stroke>
</mx:LegendItem>
</mx:Legend>
</mx:Panel>
</mx:Application>
CHAPTER 50
Contents
Handling user interactions with charts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1881
Using effects with charts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1899
Drilling down into data. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1923
Selecting chart items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1930
1881
Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta 1 Flex 3 Beta
The chart controls support the mouse events that are inherited from the UIComponent class:
mouseMove, mouseOver, mouseUp, mouseDown, and mouseOut. These events are of type
MouseEvent. In addition, the base class for all chart controls, ChartBase, adds several chart
data events. The following table describes these events:
itemDoubleClick Broadcast when the user double-clicks the mouse button while over a
data point.
itemMouseDown Broadcast when the mouse button is down while over a data point.
itemMouseMove Broadcast when the user moves the mouse pointer while over a data
point.
itemRollOut Broadcast when the closest data point under the mouse pointer
changes.
itemRollOver Broadcast when the user moves the mouse pointer over a new data
point.
itemMouseUp Broadcast when the user releases the mouse button while over a data
point.
Chart data events are triggered only when the user moves the mouse pointer over a data point,
whereas the UIComponent events are triggered by any mouse interaction with a control.
The chart data events are of type ChartItemEvent. Because ChartItemEvent events are part of
the charts package, and not part of the events package, you must import the appropriate
classes in the mx.charts.events package to use a ChartItemEvent event.
[Bindable]
public var dataSet:ArrayCollection = new ArrayCollection([
{Month:"Jan", Expenses:1500},
{Month:"Feb", Expenses:200},
{Month:"Mar", Expenses:500}
]);
]]></mx:Script>
<mx:Panel title="Clickable Column Chart">
<mx:ColumnChart id="myChart"
itemClick="myHandler(event)"
dataProvider="{dataSet}"
>
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{dataSet}"
categoryField="Month"
/>
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries yField="Expenses"/>
</mx:series>
</mx:ColumnChart>
</mx:Panel>
</mx:Application>
<mx:Style>
ToolTip {
fontSize:24;
}
ColumnChart {
gutterLeft: 54;
}
</mx:Style>
<mx:Script><![CDATA[
import mx.core.IFlexDisplayObject;
import mx.charts.events.ChartItemEvent;
import mx.charts.series.items.ColumnSeriesItem;
import mx.charts.series.ColumnSeries;
import mx.effects.Move;
import mx.charts.HitData;
import mx.collections.ArrayCollection;
[Bindable]
private var dataSet:ArrayCollection = new ArrayCollection([
{month:"Jan", income:12300, expense:3210},
{month:"Feb", income:12450, expense:3100},
hitData = event.hitData;
chartItem = ColumnSeriesItem(hitData.chartItem);
renderer = chartItem.itemRenderer;
series = ColumnSeries(hitData.element);
]]></mx:Script>
<mx:Panel id="p1">
<mx:ColumnChart id="myChart"
<!-- Define the canvas control that will be used as a highlight -->
<mx:Canvas id="highlightBox"
y="0"
x="0"
backgroundColor="0xFFFF00"
alpha=".5"
/>
</mx:Application>
For information about changing the appearance of ChartItem objects, see “Skinning
ChartItem objects” on page 1779.
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"January", Profit:2000, Expenses:1500},
{Month:"February", Profit:1000, Expenses:200},
{Month:"March", Profit:1500, Expenses:500},
{Month:"April", Profit:500, Expenses:300},
{Month:"May", Profit:1000, Expenses:450},
{Month:"June", Profit:2000, Expenses:500}]);
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500},
{Month:"Feb", Profit:1000, Expenses:200},
{Month:"Mar", Profit:1500, Expenses:500}
]);
p = myChart.dataToLocal(d[0],d[1]);
dpos.text ="(" + Math.floor(p.x) + "," +
Math.floor(p.y) + ")";
}
]]></mx:Script>
<mx:Panel title="Column Chart">
<mx:ColumnChart id="myChart"
dataProvider="{expenses}"
mouseMove="updateDetails(event)"
>
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"
/>
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Profit"
displayName="Profit"
/>
<mx:ColumnSeries
<mx:Form width="300">
<mx:FormItem label="Mouse Position:">
<mx:Label id="mpos"/>
</mx:FormItem>
<mx:FormItem label="Data Position:">
<mx:Label id="dpos"/>
</mx:FormItem>
<mx:FormItem label="DATA:">
<mx:Label id="dval"/>
</mx:FormItem>
</mx:Form>
</mx:Application>
Individual chart types determine how coordinates are mapped, and how many values are
returned in the Array. The values returned are typically numeric values.
In a chart that is based on the CartesianChart class (for example, a BarChart or ColumnChart
control), the first item in the returned Array is the value of the x-coordinate along the
horizontal axis, and the second item is the value of the y-coordinate along the vertical axis.
In a chart based on the PolarChart class (such as PieChart), the returned Array maps the
coordinates to a set of polar coordinates—an angle around the center of the chart, and a
distance from the center. Those values are mapped to data values that use the first (angular)
and second (radial) axes of the chart.
The current data point is the nearest data point to the mouse pointer that is less than or equal
to the number of pixels that the mouseSensitivity property specifies.
The default value of the mouseSensitivity property is 3 pixels. If the mouse pointer is 4 or
more pixels away from a data point, Flex does not trigger a chart data event (such as
itemRollOver or itemClick). Flex still responds to events such as mouseOver and click by
generating an Event object.
]]></mx:Script>
<mx:Panel title="Mouse Sensitivity">
<mx:PlotChart id="chart"
dataProvider="{expenses}"
showDataTips="true"
mouseSensitivity="{mySlider.value}"
>
<mx:series>
<mx:PlotSeries
xField="Expenses"
yField="Profit"
displayName="P 1"
/>
<mx:PlotSeries
xField="Amount"
yField="Expenses"
displayName="P 2"
/>
<mx:PlotSeries
xField="Profit"
yField="Amount"
displayName="P 3"
/>
</mx:series>
</mx:PlotChart>
<mx:HSlider id="mySlider"
minimum="0"
maximum="300"
value="20"
dataTipPlacement="top"
tickColor="black"
</mx:Application>
You can use the mouseSensitivity property to increase the area that triggers DataTip events
or emits chart-related events. If the mouse pointer is within the range of multiple data points,
Flex chooses the closest data point. For DataTip events, if you have multiple DataTip controls
enabled, Flex displays all DataTip controls within range. For more information, see “Showing
multiple DataTips” on page 1850.
Disabling interactivity
You can make the series in a chart ignore all mouse events by setting the interactive
property to false for that series. The default value is true. This lets you disable mouse
interactions for one series while allowing it for another.
]]></mx:Script>
<mx:Panel title="Disable Interactivity">
<mx:PlotChart id="chart"
dataProvider="{expenses}"
showDataTips="true"
>
<mx:series>
<mx:PlotSeries
xField="Expenses"
yField="Profit"
displayName="P 1"
interactive="false"
/>
<mx:PlotSeries
xField="Amount"
yField="Expenses"
displayName="P 2"
/>
<mx:PlotSeries
xField="Profit"
yField="Amount"
displayName="P 3"
interactive="false"
/>
</mx:series>
</mx:PlotChart>
</mx:Panel>
</mx:Application>
Disabling the series interactivity has the following results:
■ The series does not show DataTip controls.
■ The series does not generate a hitData structure on any chart data event.
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"Jan", Profit:2000, Expenses:1500, Amount:450},
{Month:"Feb", Profit:1000, Expenses:200, Amount:600},
{Month:"Mar", Profit:1500, Expenses:500, Amount:300}
]);
]]></mx:Script>
<mx:Parallel id="hideEffects">
<mx:Fade alphaFrom="1" alphaTo="0" duration="2500"/>
<mx:WipeLeft duration="3000"/>
</mx:Parallel>
[Bindable]
public var expenses1:ArrayCollection = new ArrayCollection([
{Month:"Jan", Income:2000, Expenses:1500},
{Month:"Feb", Income:1000, Expenses:200},
{Month:"Mar", Income:1500, Expenses:500}
]);
[Bindable]
public var expenses2:ArrayCollection = new ArrayCollection([
{Month:"Jan", Income:1200, Expenses:800},
{Month:"Feb", Income:2500, Expenses:300},
{Month:"Mar", Income:575, Expenses:490}
]);
]]></mx:Script>
<mx:verticalAxis>
<mx:LinearAxis minimum="0" maximum="3000"/>
</mx:verticalAxis>
<mx:series>
<mx:ColumnSeries
xField="Month"
yField="Income"
displayName="Income"
showDataEffect="slideIn"
hideDataEffect="slideOut"
/>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
showDataEffect="slideIn"
hideDataEffect="slideOut"
/>
</mx:series>
</mx:ColumnChart>
<mx:Legend dataProvider="{myChart}"/>
</mx:Panel>
</mx:Application>
This example explicitly defines the minimum and maximum values of the vertical axis. If it
did not, Flex would recalculate these values when the new data provider was applied. The
result would be a change in the axis labels during the effect.
Changing a data provider first triggers the hideDataEffect effect on the original data
provider, which causes that data provider to “slide out,” and then triggers the
showDataEffect effect on the new data provider, which causes that data provider to “slide
in.”
N OTE
If you set the data provider on the series and not the chart control, you must change it
on the series and not the chart control.
[Bindable]
public var items:ArrayCollection = new ArrayCollection([
{item: 2000},
{item: 3300},
{item: 3000},
{item: 2100},
{item: 3200}
]);
<mx:Button id="b1"
click="addDataItem()"
label="Add Data Item"
/>
</mx:Application>
For more information about changing charting data at run time, see “Changing chart data at
run time” on page 1634.
The charting effects have several properties in common that traditional effects do not have.
All of these properties are optional. The following table lists the common properties of the
charting effects:
Property Description
duration The amount of time, in milliseconds, that Flex takes to complete
the entire effect. This property defines the speed with which the
effect executes.
The duration property acts as a minimum duration. The effect can
take longer based on the settings of other properties.
The default value is 500.
elementOffset The amount of time, in milliseconds, that Flex delays the effect on
each element in the series.
Set the elementOffset property to 0 to make all elements start at
the same time and end at the same time.
Set the elementOffset property to an integer such as 30 to
stagger the effect on each element by that amount of time. For
example, with a slide effect, the first element slides in immediately.
The next element begins 30 milliseconds later, and so on. The
amount of time for the effect to execute is the same for each
element, but the overall duration of the effect is longer.
Set the elementOffset property to a negative value to make the
effect display the last element in the series first.
The default value is 20.
[Bindable]
public var items:ArrayCollection = new ArrayCollection([
{item:2000},
{item:3300},
{item:3000},
{item:2100},
{item:3200}
]);
Property Description
horizontalFocus Defines the location of the focal point of the zoom.
verticalFocus
You combine the horizontalFocus and verticalFocus properties to
define the point from which the data series zooms in and out. For
example, set the horizontalFocus property to left and the
verticalFocus property to top to have the series data zoom to and from
the upper-left corner of either element or the chart (depending on the
setting of the relativeTo property).
Valid values of the horizontalFocus property are left, center, right, and
undefined.
Valid values of the verticalFocus property are top, center, bottom, and
undefined.
If you specify only one of these two properties, the focus is a horizontal
or vertical line rather than a point. For example, when you set the
horizontalFocus property to left, the element zooms to and from a
vertical line along the left edge of its bounding box. Setting the
verticalFocus property to center causes the element to zoom to and
from a horizontal line along the middle of its bounding box.
The default value for both properties is center.
relativeTo Controls the bounding box used to calculate the focal point of the
zooms. Valid values for relativeTo are series and chart.
Set the relativeTo property to series to zoom each element relative to
itself. For example, each column of a ColumnChart zooms from the
upper-left of the column.
Set the relativeTo property to chart to zoom each element relative to
the chart area. For example, each column zooms from the upper-left of
the axes, the center of the axes, and so on.
[Bindable]
public var items:ArrayCollection = new ArrayCollection([
{item: 2000},
{item: 3300},
{item: 3000},
{item: 2100},
{item: 3200}
]);
[Bindable]
public var items:ArrayCollection = new ArrayCollection([
{item: 2000},
{item: 3300},
{item: 3000},
{item: 2100},
{item: 3200}
]);
[Bindable]
public var items:ArrayCollection = new ArrayCollection([
{item: 2000},
{item: 3300},
{item: 3000},
{item: 2100},
{item: 3200}
]);
<mx:Button id="b1"
click="addDataItem()"
label="Add Data Item"
/>
</mx:Application>
When you define an effect in ActionScript, you must ensure that you import the appropriate
classes. If you define an effect by using MXML, the compiler imports the class for you.
<mx:Style>
ColumnSeries {
showDataEffect:slideDown;
hideDataEffect:slideDown;
}
</mx:Style>
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var items:ArrayCollection = new ArrayCollection([
{item:2000},
{item:3300},
{item:3000},
{item:2100},
{item:3200}
]);
[Bindable]
public var items:ArrayCollection = new ArrayCollection([
{item: 2000},
{item: 3300},
{item: 3000},
{item: 2100},
{item: 3200}
]);
<mx:Button id="b1"
click="addDataItem()"
label="Add Data Item"
/>
</mx:Application>
<mx:Button id="b1"
click="addDataItem()"
label="Add Data Item"
/>
<mx:Panel>
<mx:Form>
<mx:FormItem label="Duration">
<mx:HSlider id="durationSlider"
minimum="1"
maximum="10000"
value="1000"
dataTipPlacement="top"
tickColor="black"
snapInterval="500"
tickInterval="500"
labels="['0','10000']"
allowTrackClick="true"
liveDragging="true"
/>
</mx:FormItem>
<mx:FormItem label="Minimum Element Duration">
<mx:HSlider id="minimumElementDurationSlider"
minimum="0"
maximum="1000"
value="200"
dataTipPlacement="top"
tickColor="black"
snapInterval="50"
tickInterval="50"
labels="['0','1000']"
allowTrackClick="true"
liveDragging="true"
/>
</mx:FormItem>
<mx:FormItem label="Element Offset">
<mx:Button id="b2"
label="Reset Sliders"
click="resetSliders()"
/>
</mx:Application>
For more information about databinding in ActionScript, see “Defining data bindings in
ActionScript” on page 1506.
[Bindable]
public var dpac:ArrayCollection = new ArrayCollection ([
{ date:"01/01/2006", cash:50000,
stocks:198192, retirement:130101,
home:750000, other:19148 },
{ date:"02/01/2006", cash:50000,
stocks:210309, retirement:143707,
home:760000, other:19493 },
{ date:"03/01/2006", cash:50000,
stocks:238992, retirement:169529,
home:770000, other:19933 },
{ date:"04/01/2006", cash:50000,
stocks:292269, retirement:242596,
home:770000, other:21445 }]);
[Bindable]
public var dpac:ArrayCollection = new ArrayCollection ([
{ date:"01/01/2006", assets:1607441, cash:520000, stocks:98192,
retirement:130101, home:850000, other:9148 },
{ date:"02/01/2006", assets:1610509, cash:520000, stocks:97309,
retirement:133707, home:850000, other:9493 },
{ date:"03/01/2006", assets:1617454, cash:520000, stocks:97992,
retirement:139529, home:850000, other:9933 },
{ date:"04/01/2006", assets:1615310, cash:520000, stocks:92269,
retirement:142596, home:850000, other:10445 },
{ date:"05/01/2006", assets:1600304, cash:520000, stocks:80754,
retirement:139029, home:850000, other:10521 },
{ date:"06/01/2006", assets:1600416, cash:520000, stocks:80667,
retirement:139024, home:850000, other:10725 },
{ date:"07/01/2006", assets:1599340, cash:520000, stocks:78913,
retirement:139265, home:850000, other:11162 },
{ date:"08/01/2006", assets:1608965, cash:520000, stocks:84754,
retirement:142618, home:850000, other:11593 },
{ date:"09/01/2006", assets:1622719, cash:520000, stocks:91078,
retirement:149257, home:850000, other:12384 },
{ date:"10/01/2006", assets:1629806, cash:520000, stocks:86452,
retirement:160310, home:850000, other:13044 },
{ date:"11/01/2006", assets:1642285, cash:520000, stocks:92172,
retirement:166357, home:850000, other:13756 },
{ date:"12/01/2006", assets:1651009, cash:520000, stocks:95095,
retirement:171557, home:850000, other:14357 }]);
[Bindable]
public var drillDownDataSet:ArrayCollection;
[Bindable]
public var dp:ArrayCollection = dpac;
ca1.categoryField = "type";
ca1.categoryField = "date";
var o1:Object = {
type:"cash",
amount:e.hitData.item.cash
};
var o2:Object = {
type:"stocks",
amount:e.hitData.item.stocks
};
var o3:Object = {
type:"retirement",
amount:e.hitData.item.retirement
};
var o4:Object = {
type:"home",
amount:e.hitData.item.home
result.push(o1);
result.push(o2);
result.push(o3);
result.push(o4);
result.push(o5);
return result;
}
]]></mx:Script>
<mx:horizontalAxis>
<mx:CategoryAxis id="ca1" categoryField="date"/>
</mx:horizontalAxis>
</mx:ColumnChart>
You also toggle the series’s selectability by setting the value of the selectable property. As a
result, while you might set the selectionMode on the chart to multiple, you can make the
data points in some series selectable and others not selectable within the same chart by using
the series’ selectable property.
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{ Expense:"Taxes", Amount:2000 },
{ Expense:"Rent", Amount:1000 },
{ Expense:"Food", Amount:200 } ]);
[Bindable]
private var medalsAC:ArrayCollection = new ArrayCollection( [
{ Country: "A", Gold: 35, Silver:39, Bronze: 29 },
{ Country: "B", Gold: 32, Silver:17, Bronze: 14 },
{ Country: "C", Gold: 27, Silver:27, Bronze: 38 },
{ Country: "D", Gold: 15, Silver:15, Bronze: 10 },
{ Country: "E", Gold: 15, Silver:10, Bronze: 10 } ]);
[Bindable]
private var profitsAC:ArrayCollection = new ArrayCollection( [
{ Month: "Jan", Profit: 2000, Expenses: 1500, Amount: 450 },
{ Month: "Feb", Profit: 1000, Expenses: 200, Amount: 600 },
{ Month: "Mar", Profit: 1500, Expenses: 500, Amount: 300 },
{ Month: "Apr", Profit: 1800, Expenses: 1200, Amount: 900 },
{ Month: "May", Profit: 2400, Expenses: 575, Amount: 500 } ]);
]]>
</mx:Script>
<mx:HBox>
<mx:Panel title="Bar Chart">
<mx:BarChart id="myBarChart"
height="225"
showDataTips="true"
dataProvider="{medalsAC}"
Region selection
Users can select all data points in an area on a chart by drawing a rectangle (the region) on the
chart. Users define a rectangular region by clicking and holding the mouse button while they
move the mouse, drawing a rectangle on the chart. On the MOUSE_UP event, the items
inside the rectangular region are selected. The starting point for a rectangular range must be
over the chart. You cannot start the rectangle outside of the chart control’s bounds.
To select data points with region selection, the value of the chart’s selectionMode property
must be multiple. If it is single or none, then you cannot draw the selection rectangle on
the chart.
Mouse pointer
The default behavior of the mouse pointer is to select the data point under the mouse pointer
when you click the mouse button and de-select all other data points.
If you click the mouse button and drag it over a chart, you create a rectangular region that
defines a selection range. All data points inside that range are selected.
If you select a data point, then hold the shift key down and click on another data point, you
select the first point, the target point, and all points that appear inside the rectangular range
that you just created. If you select a data point, then hold the control key down and click
another data point, you select both data points, but not the data points in between. You can
add more individual data points by continuing to hold the control key down while you select
another data point.
If you click anywhere on the chart that does not have a data point without any keys held
down, then you clear the selection. Clicking outside of the chart control’s boundary does not
clear the selection.
Programmatic selection
You can use the chart selection APIs to programmatically select one or more data points in a
chart control. These APIs consist of methods and properties of the ChartBase, ChartItem, and
chart series objects.
Selections with multiple items include a caret and an anchor. You can access these items by
using the caretItem and anchorItem properties of the chart control.
The index properties refer to the index of the chart item in the series. This index is the same as
the index in the data provider, assuming you did not sort or limit the series items.
Programmatically setting the values of these properties does not trigger a change event.
[Bindable]
private var expensesAC:ArrayCollection = new ArrayCollection( [
{ Month: "Jan", Expenses: 1500, Amount: 450, Profit: 2000 },
{ Month: "Feb", Expenses: 200, Amount: 600, Profit: 1000 },
{ Month: "Mar", Expenses: 500, Amount: 300, Profit: 1500 },
{ Month: "Apr", Expenses: 1200, Amount: 900, Profit: 1800 },
{ Month: "May", Expenses: 575, Amount: 500, Profit: 2400 } ]);
]]>
</mx:Script>
<mx:Panel height="100%" width="100%">
<mx:ColumnChart id="myChart" height="207" width="350"
showDataTips="true" dataProvider="{expensesAC}" selectionMode="single">
<mx:series>
<mx:ColumnSeries id="series1" yField="Expenses"
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="Month"/>
</mx:horizontalAxis>
</mx:ColumnChart>
<mx:HBox>
<mx:Label id="label0" text="Value: "/>
<mx:Label id="label1"/>
</mx:HBox>
<mx:HBox>
<mx:Button label="|<" click="getFirst(event);" />
<mx:Button label="<" click="getPrev(event);" />
<mx:Button label=">" click="getNext(event);" />
<mx:Button label=">|" click="getLast(event);" />
</mx:HBox>
</mx:Panel>
</mx:Application>
To cycle through ChartItem objects in a series, you can use methods such as getNextItem()
and getPreviousItem(). For more information, see “Methods and properties of the
ChartBase class” on page 1942.
[Bindable]
private var expensesAC:ArrayCollection = new ArrayCollection( [
{ Month: "Jan", Profit: 2000, Expenses: 1500, Amount: 450 },
{ Month: "Feb", Profit: 1000, Expenses: 200, Amount: 600 },
{ Month: "Mar", Profit: 1500, Expenses: 500, Amount: 300 },
{ Month: "Apr", Profit: 1800, Expenses: 1200, Amount: 900 },
{ Month: "May", Profit: 2400, Expenses: 575, Amount: 500 } ]);
</mx:Panel>
</mx:Application>
[Bindable]
private var expensesAC:ArrayCollection = new ArrayCollection( [
{ Month: "Jan", Profit: 2000, Expenses: 1500, Amount: 450 },
{ Month: "Feb", Profit: 1000, Expenses: 200, Amount: 600 },
{ Month: "Mar", Profit: 1500, Expenses: 500, Amount: 300 },
{ Month: "Apr", Profit: 1800, Expenses: 1200, Amount: 900 },
{ Month: "May", Profit: 2400, Expenses: 575, Amount: 500 } ]);
</mx:Panel>
</mx:Application>
[Bindable]
private var expensesAC:ArrayCollection = new ArrayCollection( [
{ Month: "Jan", Expenses: 1500, Amount: 450, Profit: 2000 },
{ Month: "Feb", Expenses: 200, Amount: 600, Profit: 1000 },
{ Month: "Mar", Expenses: 500, Amount: 300, Profit: 1500 },
{ Month: "Apr", Expenses: 1200, Amount: 900, Profit: 1800 },
{ Month: "May", Expenses: 575, Amount: 500, Profit: 2400 } ]);
<mx:HBox>
<mx:Label id="label0" text="Value: "/>
<mx:Label id="label1"/>
</mx:HBox>
<mx:HBox>
<mx:Button label="|<"
click="getFirst(event, ChartBase.HORIZONTAL);" />
<mx:Button label="<"
click="getPrev(event, ChartBase.HORIZONTAL);" />
<mx:Button label=">"
click="getNext(event, ChartBase.HORIZONTAL);" />
<mx:Button label=">|"
click="getLast(event, ChartBase.HORIZONTAL);" />
</mx:HBox>
</mx:Panel>
</mx:Application>
These item getter methods do not have associated setters. You cannot set the selected
ChartItem objects in the same manner. Instead, you use the properties of the series, as
described in “Properties of the series” on page 1935.
ChartItem properties
You can set the value of the currentState property of a ChartItem object to make it appear
selected or deselected, or make it appear in some other state. The currentState property can
be set to none, rollOver, selected, disabled, focusSelected, and focused.
Setting the state of the item does not add it to the selectedItems array. It only changes the
appearance of the chart item. Setting the value of this property also does not trigger a change
event.
Defined range
You can use the getItemsInRange() method to define a rectangular range and select those
chart items that are within that range. The getItemsInRange() method takes an instance of
the Rectangle class as its only argument. This rectangle defines a region on the stage, in global
coordinates.
Getting an array of ChartItem objects with the getItemsInRange() method does not trigger
a change event. The state of the items does not change.
[Bindable]
private var expensesAC:ArrayCollection = new ArrayCollection( [
{ Month: "Jan", Expenses: 1500, Amount: 450, Profit: 2000 },
{ Month: "Feb", Expenses: 200, Amount: 600, Profit: 1000 },
{ Month: "Mar", Expenses: 500, Amount: 300, Profit: 1500 },
{ Month: "Apr", Expenses: 1200, Amount: 900, Profit: 1800 },
{ Month: "May", Expenses: 575, Amount: 500, Profit: 2400 } ]);
<mx:HBox>
<mx:Form>
<mx:FormItem label="x">
<mx:TextInput id="ti1" text="0"/>
</mx:FormItem>
<mx:FormItem label="y">
<mx:TextInput id="ti2" text="0"/>
</mx:FormItem>
</mx:Form>
<mx:Form>
<mx:FormItem label="Height">
<mx:TextInput id="ti3" text="0"/>
</mx:FormItem>
<mx:FormItem label="Width">
<mx:TextInput id="ti4" text="0"/>
</mx:FormItem>
</mx:Form>
</mx:HBox>
<mx:Button label="Get Items" click="getItems(event)" />
<mx:TextArea id="ta1" height="100" width="300"/>
</mx:Panel>
When you select an item programmatically, no change event is dispatched. When you change
the selectedState property of a chart item, no change event is dispatched.
[Bindable]
private var expensesAC:ArrayCollection = new ArrayCollection( [
{ Month: "Jan", Profit: 2000, Expenses: 1500, Amount: 450 },
{ Month: "Feb", Profit: 1000, Expenses: 200, Amount: 600 },
{ Month: "Mar", Profit: 1500, Expenses: 500, Amount: 300 },
{ Month: "Apr", Profit: 1800, Expenses: 1200, Amount: 900 },
{ Month: "May", Profit: 2400, Expenses: 575, Amount: 500 } ]);
// Clears all chart items selected when the user presses the ESC key.
private function keyHandler(event:KeyboardEvent):void {
var curKeyCode:int = event.keyCode;
if (curKeyCode == 27) { // 27 is the keycode value for ESC
myChart.clearChartSelection();
}
}
]]>
</mx:Script>
<mx:Panel height="100%" width="100%">
<mx:PlotChart id="myChart"
height="207"
width="350"
showDataTips="true"
dataProvider="{expensesAC}"
selectionMode="multiple"
>
<mx:series>
<mx:PlotSeries id="series1"
xField="Expenses"
yField="Profit"
displayName="Expenses/Profit"
selectable="true"
[Bindable]
public var newDataProviderAC:ArrayCollection;
[Bindable]
private var expensesAC:ArrayCollection = new ArrayCollection([
{ Month: "Jan", Expenses: 1500 },
{ Month: "Feb", Expenses: 200 },
{ Month: "Mar", Expenses: 500 },
{ Month: "Apr", Expenses: 1200 },
{ Month: "May", Expenses: 575 } ]);
expensesAC.getItemAt(series1.selectedIndices[i]).Expenses;
newDataProviderAC.addItem(o);
}
return newDataProviderAC;
}
[Bindable]
private var explodedPiece:Array;
newChart.addEventListener(ChartItemEvent.CHANGE, explodePiece);
p1.addChild(newChart);
}
<mx:SeriesInterpolate id="interpol"
duration="1000"
elementOffset="0"
minimumElementDuration="200"
/>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.charts.chartClasses.ChartBase;
import mx.charts.ChartItem;
import mx.charts.PieChart;
import mx.charts.series.PieSeries;
import mx.charts.events.ChartItemEvent;
import mx.events.DragEvent;
import mx.controls.List;
import mx.managers.DragManager;
import mx.core.DragSource;
[Bindable]
public var newDataProviderAC:ArrayCollection;
[Bindable]
private var expensesAC:ArrayCollection = new ArrayCollection([
{ Month: "Jan", Expenses: 1500 },
{ Month: "Feb", Expenses: 200 },
{ Month: "Mar", Expenses: 500 },
{ Month: "Apr", Expenses: 1200 },
{ Month: "May", Expenses: 575 } ]);
[Bindable]
private var explodedPiece:Array;
newChart.height = 350;
newChart.width = 350;
newChart.addEventListener("dragEnter", doDragEnter);
newChart.addEventListener("dragDrop", doDragDrop);
newChart.dataProvider = newDataProviderAC;
newChart.addEventListener(ChartItemEvent.CHANGE, explodePiece);
p2.addChild(newChart);
}
// Get the dragged items from the drag initiator. When getting
// items from chart controls, you must use the 'chartitems'
<mx:SeriesInterpolate id="interpol"
duration="1000"
elementOffset="0"
minimumElementDuration="200"
/>
<!-- This will be the parent of the soon-to-be created chart. -->
<mx:Panel id="p2" title="Target Chart" height="400" width="400">
</mx:Panel>
</mx:Application>
Chart controls also support the standard drag and drop methods of List-based controls such as
hideDropFeedback() and showDropFeedback(). These methods display indicators under
the mouse pointer to indicate whether drag and drop operations are allowed and where the
items will be dropped.
For more information about drag and drop operations, see Chapter 31, “Using Drag and
Drop,” on page 1195.
Index
H I
HBox container. See Box container icon function, using 455, 496
HDividedBox container. See DividedBox container id property 28
help, ToolTips 1033 identifiers 28
hexadecimal color format 776 IFocusManagerComponent interface 1002
hidden controls, preventing layout 255 Image control 334
hideDataEffect trigger 1901 file path 336
hierarchical data providers 207 in a Canvas container 340
history management, standard 1328 positioning 340
History Manager, about 1328 sizing 337
HistoryManager class visibility 341
methods 1333 Image tag, maintainAspectRatio 338
syntax 1330 ImageButton control 277
HitData object inches, style property 773
findDataPoint() method 1890 include directive 70
using 1883 including ActionScript 68
HLOCChart controls 1669 initialize event 148
horizontalAxis 1605 inline styles, overriding 808
horizontalAxisStyle 1712 inner function 98
horizontalFill 1769 innerRadius 1688
HorizontalList control instance classes 722
examples 460, 981 introspection 77
keyboard navigation 299, 461 ISO-8859-1 encoding 23
user interaction 461 item editors
horizontalStroke 1769 architecture 944
HRule control, about 370 cell editing events 1002
HSlider control creating 948
about 319 creating inline item editors 964
events 324 creating item editor components 972
example 321
V W
validation waterfall charts 1667, 1865
credit cards 1563 web services
data 1473 RPC-oriented, document-oriented 1442
data models 1525 SOAP headers 1443
disabling validator 1557 stateful 1443
e-mail addresses 1568 WSDL 1441
form data 658 Web Services Description Language 135
numbers 1569 web-safe colors 351
standard validators 1562 WebService components
VBox container. See Box container about 135
VDividedBox container. See DividedBox container additional features 135, 1436
verticalAxis 1605 WipeDown effect 728
verticalAxisStyle 1712 WipeLeft effect 728
verticalFill 1769 WipeRight effect 728
verticalStroke 1769 WipeUp effect 728
VGA name color format 776 WorkWeek axis 1810
VideoDisplay control 344 workweek axis 1810
view cursor WSDL 135
bookmarks 193
manipulating 190
view states X
about 1115 x-axis 1605
building applications with 1149 XML data
defining and applying 1125 binding with E4X 1502
ViewStack container encoding 23
Y
y-axis 1605
Z
ZIP codes
formatting 1588
validating 1574
Zoom effect 728