Adobe
Products
Acrobat
Creative Cloud
Creative Suite
Digital Marketing Suite
Digital Publishing Suite
Elements
Photoshop
Touch Apps
Student and Teacher Editions
More products
Solutions
Creative tools for business
Digital marketing
Digital media
Education
Financial services
Government
Web Experience Management
More solutions
Learning Help Downloads Company
Buy
Home use for personal and home office
Education for students, educators, and staff
Business for small and medium businesses
Licensing programs for businesses, schools, and government
Special offers
Search
 
Info Sign in
Welcome,
My cart
My orders My Adobe
My Adobe
My orders
My information
My preferences
My products and services
Sign out
Why sign in? Sign in to manage your account and access trial downloads, product extensions, community areas, and more.
Adobe
Products Sections Buy   Search  
Solutions Company
Help Learning
Sign in Sign out My orders My Adobe
Preorder Estimated Availability Date. Your credit card will not be charged until the product is shipped. Estimated availability date is subject to change. Preorder Estimated Availability Date. Your credit card will not be charged until the product is ready to download. Estimated availability date is subject to change.
Qty:
Purchase requires verification of academic eligibility
Subtotal
Review and Checkout
Adobe Developer Connection / Flex Developer Center /

DigiPri Widgets Sales Dashboard – Part 3: Understanding the dashboard application

by Digital Primates

Digital Primates
  • digitalprimates.net

by Dave Flatley

Dave Flatley
  • pxldesigns.com

Created

28 June 2010

Page tools

Share on Facebook
Share on Twitter
Share on LinkedIn
Bookmark
Print
Flex RIA

Requirements

Prerequisite knowledge

Some knowledge of ActionScript 3, Flex 4, Flash Builder, and object-oriented programming concepts will be helpful. A basic understanding of BlazeDS, Java, and MySQL will also be helpful in understanding the server-side functionality.

User level

Intermediate

Required products

  • Flash Builder (Download trial)

Sample files

  • AdobeCRM_files_pt_2-3.zip (8004 KB)

This article is Part 3 of a series of articles and tutorials centered on a sales dashboard application built using Flex and the Adobe Flash Platform. The individual articles in the series are designed to stand on their own, so you can read all of them or just the ones that interest you, in whatever order you like.

This part first reviews the basic layout of the application's user interface, and then explains how many of the main building blocks of the application work:

  • How the application connects with the server
  • How reports are configured using XML files
  • How users can interact with reports and charts in the report area
  • How users can rearrange reports using drag-and-drop
  • How users can add, remove, and maximize reports

For an overview of the application, see Part 1: Overview. For a more in-depth look at the code, see Part 4: Exploring the code in Flash Builder.

The UI layout

The DigiPri Widgets sales dashboard is comprised of a header at the top of the application, which contains the logo and navigation tabs, and a central reports area below it. When the application starts, the Regional Sales tab is selected, and the corresponding reports are shown below (see Figure 1).

The DigiPri Widgets sales dashboard
Figure 1. The DigiPri Widgets sales dashboard

The report area consists of a TabBar and a ViewStack component, which can display any one of the report groups at a time. The header area contains the tabs that enable the user to select the views shown in the report area. Report groups can be configured as customizable. By default, the My Dashboard group is customizable, so it includes a report list, from which  the user may add reports to the view. This is shown as a drop-down list on the top right-hand side of the reports area (see Figure 2).

The list of reports that can be added to a customized view
Figure 2. The list of reports that can be added to a customized view

All the text shown in the application is stored in resource bundles (or stored in the database itself), so the application can be more easily translated to other languages.

Server-side connectivity

The DigiPri Widgets dashboard application makes use of an ultra-lightweight services framework, which embraces the use of the Responder pattern, as it is implemented in Flex with the IResponder interface. This pattern is the basis for all asynchronous data access in the application.

The conduit between the Flex application and the services layer is the command, which implements the IResponder interface. Any data needed by a command is passed to its constructor upon instantiation. The execute method of the command is called with no arguments to tell the command to request the specified data. The IResponder interface requires that the implementing classes have public result and fault methods, which will be called accordingly based on the response from the server.

In the execute method of the command, a reference to the service is retrieved through a call to the ServiceFactory. For example, the command that fetches client deals calls the service factory's getClientDealService method, and passes itself as a responder:

public override function execute() : void { serviceFactory.getClientDealService( this ).getAllClientDeals(); }

Internal to the ServiceFactory, a RemoteObject instance is created, and given a reference to the destination that matches the destination in the server's remoting-conf.xml file. The newly created RemoteObject and the responder (the command) are passed to the constructor of the ClientDealServiceRemote class.

RPC services

The ClientDealServiceRemote ActionScript class has methods that mirror the methods of the ClientDealServiceImpl Java class on the server. Each of these methods is capable of calling the correspondingly named method on the server. For example, a call to getAllClientDeals() Flex in turn uses the remote object to call that method (implemented in Java) on the server:

public function getAllClientDeals() : AsyncToken { var abstractOp : AbstractOperation = service.getOperation( "getAllClientDeals" ); var token : AsyncToken = abstractOp.send(); token.addResponder( resp ); return token; }

In Flex, a call to a method on a remote object returns an instance of the AsyncToken class, and a responder can be added to the AsyncToken, so that any responses will be heard by the result or fault method of that responder. In this application, the command, which initiated the call, is that responder.

XML services

Server-side XML configuration files are also loaded through the use of commands, the ServiceFactory, and the remote service implementation. The commands work in the same way as the commands for invoking remote methods, calling the ServiceFactory, which finds the URL for the XML file to load. The ServiceFactory creates an instance of the HTTPService class for calling the XML file, specifies the URL of the service, and passes the HTTPService and Responder (the command) to a remote implementation. The methods in the remote implementation call the send method of the HTTPService, which instructs the service to load the specified file, and applies the responder to the returned token.

The commands that load the XML files handle all of the XML parsing in their result method. An example of this functionality can be seen in the GetNavItems ActionScript class. The execute() method invokes the getNavService() of the ServiceFactory class, which makes the call to XMLDataLoaderRemote() and returns an instance of the IXMLHttpLoader class. The result() method is the responder for the call and handles the XML parsing:

public override function result( data : Object ) : void { var appModel : ApplicationModel = ApplicationModel.getInstance(); var navItems : ArrayCollection = new ArrayCollection(); for each( var item : XML in data.result.report ) { var reportItem : ReportItem = appModel.getReportDataById( item.@id ); navItems.addItem( reportItem ); } appModel.navItems = navItems; }

Configuring the dashboard application

The DigiPri Widgets sales dashboard uses four XML configuration files: nav.xml reports.xml, reportGroups.xml, and services.xml. The services.xml file contains nodes listing the URLs of the XML files to be loaded by the application. The other XML files define reports and their relationships to the application.

How reports are defined

As described in the previous section, commands are used to retrieve the data from the XML configuration models. The result methods of the command parse that data into strongly typed beans, which are stored in the ApplicationModel. The ApplicationModel can be accessed as a singleton, allowing consumers of this data to retrieve it whenever needed.

This approach makes the sales dashboard a dynamic application. By simply defining new reports in the associated XML file, a new report is created that can be instantiated in the application. With a few simple lines of XML, new reports can be defined for use in the application, and since these XML files are not embedded within the application, there is no need to recompile to add the new reports. Likewise, new report groups can be created by editing XML, without having to rebuild the application itself.

Configuring reports in reports.xml

The reports.xml file defines each of the individual reports that can be used in the application. Each report node represents a single report and is parsed into a ReportItem bean.

For example, reports.xml includes the following node:

<report id="201" name="salesForecastsChart" type="components.reports.ColumnChartReportView" command="commands.GetAllSalesForecastsCommand" . . . </report>

The id property is a unique identifier for each report and is the property that the application uses to specify which report to instantiate. The type property specifies the class of report to instantiate; for example, to use a column chart, the type value would be components.reports.ColumnChartReportView. This also contributes to the dynamic capabilities of the application, because it enables developers to add a report of a new class definition  to change how data is represented by simply changing that property.

Among the other optional elements that can be specified for each report in the reports.xml file are the series and axis details for each report. This makes it easy to change existing reports from one type of chart to another. For example, a ColumnChart can easily become a BarChart by changing <cartesianSeries type="mx.charts.series.ColumnSeries"... to <cartesianSeries type="mx.charts.series.BarSeries."...

The data used to populate each chart within the report is specified by providing the name of a command class to use to retrieve that data. This command will be called automatically when the report is instantiated.

Configuring report groups in reportgroups.xml

Each reportGroup node in the reportgroups.xml file specifies one or more report IDs to be associated with that group. The file is parsed and made into an array of ReportGroup beans, which is used to create the views for the ViewStack.

Here is the default reportgroups.xml file:

<?xml version="1.0" encoding="UTF-8"?> <reportGroups> <reportGroup id="101" label="Regional Sales"> <report id="221" /> <report id="207" /> <report id="222" /> <report id="205" /> <report id="220" /> </reportGroup> <reportGroup id="102" label="Client Deals" rearrangeable="true"> <report id="222" /> <report id="205" /> <report id="215" /> <report id="216" /> <report id="217" /> <report id="218" /> </reportGroup> <reportGroup id="103" label="My Dashboard" rearrangeable="true" addRemoveEnabled="true"> </reportGroup> </reportGroups>

In addition to containing the IDs for the reports to be contained in each report group (and therefore view), each of these XML nodes and associated beans may contain two additional properties for the view: addRemoveEnabled and rearrangeable . These properties are used in the ExtendedDragDropTileGroup container to determine if reports can be added or removed from the view or if they can be moved around.

Nav.xml

The navigation XML file contains the ID of reports to be displayed in the ReportsDrawer—that is, the list of reports that can be added to customizable report groups (see Figure 2). The bean created by parsing this data is used as the data provider for the ReportsDrawer. By separating the list of reports that can be added from the list of all available reports, developers can set up two general classes of reports: those that can be seen only in specific report groups, and those that can be added to the application in a customizable view.

The report area

The container that tiles the report components and lays them out accordingly is a custom-built component named ExtendedDragDropTileGroup (which is covered in detail in The ExtendedDragDropTileGroup container). The properties set on the container from the ReportGroup bean control what the user is allowed to do with the reports. If the rearrangeable property is true , then the user can reposition the report components within the container. (The application will provide  visual feedback to show where the chart currently will be placed relative to the other charts.)

Reports

The reports are designed to facilitate access to the information at a glance, as well as the ability to focus on a specific report for more clarity.

To see a larger view of each report, the user can maximize it. Reports can also optionally be configured to allow users to drill down on data points within them, thus narrowing the scope and focusing on a specific aspect of the chart. As an example, a user can drill down on the sales forecast for a year, and see the forecast for individual months. The user can then return to the yearly forecast chart by clicking on the back button.

Charts

The charts in the component are created by passing in a ReportItem bean. As described earlier, this bean is created by parsing report nodes from the reports.xml file. Whenever the reportBean property is changed, invalidateProperties() is called, which ultimately results in a call to the createNewChart() method.

The createNewChart method in the DrillDownReport class removes any existing chart from the component, and then calls getDefinitionByName with the type property of the ReportItem bean to get the class implementation of the chart. A new instance of this class, a chart implementation, is created and the ReportItem is passed to it to instantiate it. The chart object is then added to the component and set as the currently selected view in report's the ViewStack.

Tabular view

If the report has both a tabular column as well as a reportSeries defined, the report will be instantiated with a ViewStack that contains both a chart and a data grid, and buttons to allow the user to toggle between the two views of the data (see Figure 3).

A report with a chart, a data grid, and buttons to switch between the two
Figure 3. A report with a chart, a data grid, and buttons to switch between the two

The DrillDownReport component displays the two buttons for the tabular view toggle. Clicking either button selects that chart implementation in the ViewStack and displays it.

The tabular view is a tabular representation of the top-level data in the component.

Drill down

The drill-down feature in DrillDownReport takes advantage of the reportBean changed event to drill down to the next chart in the series. Setting the reportBean property in the component triggers the creation of the chart component(s). In this case, when a user clicks one of the hit points on the chart, the current chart's drillDown property is passed into the command to retrieve the report associated with the ID of the hit point. The getDefinitionByName method is called and the new chart implementation is instantiated. The new chart is passed as the new report, which consequently invokes the createNewChart method.

Drill-down history

The back button enables the user to return to a previous chart after drilling down. When no history is available, the button is disabled. Once a user drills down into a chart, the previous chart data is stored in an array, and the back button is enabled. Clicking this button restores the previous chart's data, thereby returning the user a level up from the current chart. The history is maintained regardless of whether the chart is in a normal or maximized state.

The DragDropTileGroup container

To allow the user to freely drag and drop the reports within the application, additional functionality above and beyond the layout of the TileGroup was required. As such, the TileGroup component was subclassed to create DragDropTileGroup, which contains logic to allow users to reorder reports via drag and drop operations.

Dragging within the container

The DragDropTileGroup container allows a child to be repositioned after checking to see if dragging is enabled for that container. When the child is dropped at a specific point in the container, the children are reindexed.

The findIndex method

The findIndex method is used to figure out the new index of the dragged child. This method is passed the current location of the mouse relative to the content pane of the container.

The method assigns bounded areas to each tile (and therefore each index) based on the calculated maximum number of rows and columns given the size of the container and its tiles. Using the X and Y positions of the mouse pointer, findIndex then calculates the associated row and column position and the index is found. As a visual representation of the dragging operation, a glowing outlined rectangle of the same size as the component being dragged is created in the showFeedback method that calls drawFeedback. This method then either adds the child (or sets the index of the child) at the index returned by the findIndex method. The effect can be changed simply by overriding the drawFeedback method. This also applies to the dragProxy with the createDragProxy method.

Handling child mouse events

The application must be able to discern a drag operation from a simple mouse click. On the mouse down event, listeners for the mouse up and mouse move events are added to the child. When the user depresses the mouse button without a move of the mouse, the application assumes a mouse  click occurred. A mouse move, on the other hand, before releasing the button, is considered to be a drag operation.

Note, however, that these events are ignored in certain areas because mouse clicks and mouse drags on a child are only acted on when they occur on the chrome of the child.

The ExtendedDragDropTileGroup container

The DragDropTileGroup is a generic component that enables users to perform drag and drop reordering of children of any TileGroup. The My Dashboard report group in the DigiPri Widgets sales dashboard needed additional functionality including support for maximizing reports, as well as adding and removing reports. This functionality was implemented in a new subclass, ExtendedDragDropTileGroup.

Rearrangeable flag

The rearrangeable flag is set from the ReportGroup bean when the container is created. This flag enables or disables the dragging of children within the container. If this property is set to true in reportGroups.xml, an arrow image is visible in the chrome, and hovering the mouse over the chrome of one of the children will display a tooltip, indicating that the component can be dragged. If, however, the property is not set, the  tooltip and arrow image will not appear and the drag will not register on the component.

The ExtendedDragDropTileGroup uses the rearrangeable flag specifically to determine if a child object can be repositioned on screen. The actual drag functionality is handled in the DragDropTileGroup class.

By default, in the DigiPri Widgets sales dashboard the Client Deals report group is rearrangeable.

AddRemoveEnabled flag

The addRemoveEnabled flag, much like the rearrangeable flag, is read from the ReportGroup bean when this container is instantiated. The addRemoveEnabled flag specifies whether users can add and remove reports from the reports area (that is, the container).

If the flag is set to true , then the close button on non-maximized reports is enabled. This allows the reports to be removed from the container, and thus, the view. In addition, when set, this flag results in the ReportsDrawer component being added to the ViewStack (and the view).

Maximizing

Upon receipt of a reportViewEvent event, the ExtendedDragDropTileGroup resizes all of its children for a 3D zoom effect, so the report that generated the event is maximized. The other child elements in the view are moved out of the way during the effect and have their alpha properties set lower to fade them out. The gap properties of the container also increase horizontally and vertically to enhance the 3D effect.

In its maximized state, the handler method for the report's maximize button will dispatch a ReportViewEvent.MINIMIZE event telling the application to return its original view and minimize the chosen report. The child elements of the ExtendedDragDropTileGroup will return to their original coordinates and the gaps between them will resize to normal.

setupAndPlayMoveEffect

The setupAndPlayMoveEffect method performs the transitions that occur when the mouse is moved around in the container during a drag.

The move effect is called whenever there is a change to the index of the mouse location. A visual representation of the location relative to the children in the container is displayed. When the location of this representation changes, the effect plays to show the respective change. As a result, the you will see instant visual feedback of the reports switching views while you drag a given report to a new position in the tile layout.

Where to go from here

Part 4 of this series shows you how to set up the DigiPri Widgets sales dashboard sample application in Flash Builder 4, and provides a more in-depth look at the code. If you want to set up a full development environment locally, you'll also want to read Part 2, which explains how to set up the server-side software.

More Like This

  • Using automated tools across the lifecycle to develop higher quality Flex applications
  • Increasing Flex and ActionScript development productivity with Flash Builder 4.5 and SourceMate 3.0
  • Creating a rich buying experience with a data-driven RIA
  • Building a portable RIA with Flex and PDF
  • Flex mobile development tips and tricks – Part 2: Styling your application's tabs and ActionBar
  • What's new in Flex 4.6 SDK and Flash Builder 4.6
  • Flex mobile skins – Part 3: Multiplatform development
  • Flex application testing with RIATest 4
  • Migrating Flex 3 applications to Flex 4 – Part 2: Beginning migration of the Dashboard application to Flex 4
  • Flex mobile skins – Part 1: Optimized skinning basics

Tutorials & Samples

Tutorials

  • Flex mobile performance checklist
  • Flex and Maven with Flexmojos – Part 3: Journeyman
  • Migrating Flex 3 applications to Flex 4.5 – Part 4

Samples

  • Twitter Trends
  • Flex 4.5 reference applications
  • Mobile Trader Flex app on Android Market

Flex User Forum

More
07/25/2011 Flash Player Debug Issues - Safari 5.1 & Chrome 13
04/22/2012 Loader png - wrong color values in BitmapData
04/22/2012 HTTPService and crossdomain.xml doesn't work as expected
04/23/2012 Memory related crashes in Flex application

Flex Cookbook

More
04/06/2012 How to detect screen resize with a SkinnableComponent
02/29/2012 Embed Stage3D content inside Flex application components
02/15/2012 Custom WorkFlow Component
02/09/2012 Using Camera with a MediaContainer instead of VideoDisplay

Products

  • Acrobat
  • Creative Cloud
  • Creative Suite
  • Digital Marketing Suite
  • Digital Publishing Suite
  • Elements
  • Mobile Apps
  • Photoshop
  • Touch Apps
  • Student and Teacher Editions

Solutions

  • Digital marketing
  • Digital media
  • Web Experience Management

Industries

  • Education
  • Financial services
  • Government

Help

  • Product help centers
  • Orders and returns
  • Downloading and installing
  • My Adobe

Learning

  • Adobe Developer Connection
  • Adobe TV
  • Training and certification
  • Forums
  • Design Center

Ways to buy

  • For personal and home office
  • For students, educators, and staff
  • For small and medium businesses
  • For businesses, schools, and government
  • Special offers

Downloads

  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR
  • Adobe Shockwave Player

Company

  • News room
  • Partner programs
  • Corporate social responsibility
  • Career opportunities
  • Investor Relations
  • Events
  • Legal
  • Security
  • Contact Adobe
Choose your region United States (Change)
Choose your region Close

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Österreich - Deutsch
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Hrvatska
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • Suomi
  • France
  • Deutschland
  • Magyarország
  • Ireland
  • Israel - English
  • ישראל - עברית
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • الشرق الأوسط وشمال أفريقيا - اللغة العربية
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Polska
  • Portugal
  • România
  • Россия
  • Srbija
  • Slovensko
  • Slovenija
  • España
  • Sverige
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

Terms of Use | Privacy Policy and Cookies (Updated)

Ad Choices

Reviewed by TRUSTe: site privacy statement