Author Archive: Matthew J. Horn

Spark skinning doc updated

The Spark skinning docs have been updated. They include sections on the skinning contract between Spark components and their skins, how to skin Spark components and containers, and how to package your custom skins as a library for distribution.

Please check out the new docs below and send feedback to me:

spark_skinning.pdf

Stupid Flex tricks: undocumented fcsh commands

I just recently discovered that there are several undocumented commands for fcsh, the command line compiler shell.

If you don’t know what fcsh is… it’s a simple shell environment for compiling Flex apps and libraries from the command line. Basically, it speeds up the compilation significantly. You can read more about it here:

http://livedocs.adobe.com/flex/3/html/help.html?content=compilers_32.html

The undocumented commands (and by “undocumented”, I mean they aren’t in the help system’s doc on fcsh or listed in the fcsh online “help” command output) are:

  • cp (copy)
  • mv (move)
  • touch (change timestamp)
  • rm (delete/remove)

The syntax is pretty straightforward, but if you want to spend a few minutes documenting them, we’ll happily add a link to your blog or web site from the Adobe help.

matt

New doc: Text controls

Below is the latest documentation on using text controls in Flex 4.

This PDF includes information on creating and maniupating TextFlows, a powerful new class for working with text in the TLF-based text controls.

The topic also includes documentation on using the following new Spark text controls:

  • Spark Label, TextInput, and TextArea
  • RichText
  • RichEditableText

Please let me know if you have any questions, comments, or updates.

Here’s the new documentation: Text controls

Scaling Label text size to fit available area

Working with text in Flex 3 can be difficult. Especially if you want to scale text to fit an area (a task I recently discovered was not intuitive at all). Should you scale the text control? Convert the contents to a bitmap and resize it? Set the fontSize and test it’s width against the parent container?

The cleanest solution I found was to use was to compare the textWidth property of the Label against the parent container’s width (the available area), and then scale the Label component based on that comparison.

Here’s the running example (the default font size is 36 pts, but you can see that the second and third labels are scaled according to how much text is in the Label):

There’s a bit of a caveat to this, which is that in general, this will not be a “UI best practice”. A list of text items, where the text varies in size for each item in the list, is not the most readable or user friendly way to present information.

The main app and custom component files are below, but here’s a few lines to show you how it’s done.

In the Label tag, trigger a function on the creationComplete event:

<mx:Label id="myLabel"
x="101" y="22"
fontSize="36"
text="{title}"
width="100%" truncateToFit="false"
creationComplete="scaleLabelToFit()"
/>

You should also set truncateToFit to false so that a Label whose text comes close to the edge does not get truncated.

The scaleLabelToFit() function calculates the ratio of the main component’s width to the width of the Label’s text (textWidth):

var ratio:Number = ((this.width - myImage.width) - 10) / myLabel.textWidth;

This line subtracts the width of the image and an additional 10 pixels to account for padding.

Then, if the ratio is less than 1, scale the text control. If the ratio were greater than 1, you would not want to scale the text up, so just ignore that case.

if (ratio < 1) {
myLabel.scaleX = ratio;
myLabel.scaleY = ratio;
}

That’s it. Here’s a ZIP of the entire app, including images:

ScaleLabelSizes.zip

Flex 4 Beta 2 documentation live

NOTE: Flex 4 shipped on March 22, 2010. Click here to read a blog post that describes the documentation set. Also, I suggest that you bookmark the Flex Developer Center Documentation tab for quick access to all Flex Learning Resources.
-Randy

Using Fonts in Flex 4

The chapter on using fonts in Flex 4 has been updated. This chapter discusses embedding fonts, setting character ranges, and troubleshooting among other things.

While there aren’t any new features for fonts in Flex 4, there are some significant changes you should be aware of. For example:

  • Support for TLF is on by default (all Spark components use this new library of text manipulation)
  • Using embedded fonts with Halo/MX controls might require you to set some style properties to ensure that the right font is used
  • Font fallback substitutes a character from a device font that might not be available in an embedded font

One of the biggest changes you’ll notice is that all the examples now specify a property when embedding fonts: embedAsCFF. This property determines how a font is embedded: with DefineFont4 or DefineFont3. When embedded with DefineFont4, an embedded font can use the features of TLF. All Spark controls support DefineFont4. Some Halo controls support it, if you set their text renderers to use the new TLFTextField and TLFTextInput classes. This is all described in the doc.

One further note: For Beta 2, this document is accurate. However, for the final release, the following class names will be changed:

  • TLFTextField will become FTETextField
  • UITLFTextField will become UIFTETextField
  • TLFTextInput will become FTETextInput

Click here to download the latest Fonts documentation:

fonts.pdf

Date range selection for Flex charts

Charting applications that have user interaction are great. They can take advantage of the built-in charting effects, and also take advantage of users’ needs to look at data differently, and drill down into data. One of the most interesting ways to experience time-based data is by using a date range selector.

There are some examples of date range selectors out there, such as the fantastic one used by Google finance. I wanted to do something simpler so I wrote this example, which is loosely based on Ely’s Custom Annotation example in his Chart Sampler.

Try it out. Just click and drag a range for the chart:

This app consists of a main application file (DateSelectionExample.mxml) and a single ActionScript class file, RangeSelector.as.

The RangeSelector extends the ChartElement class. As a result, you add it to your chart as an annotationElement:

<mx:annotationElements>
<custom:RangeSelector/>
</mx:annotationElements>

The meat of the RangeSelector class is in the updateDisplayList() method. Here, it does several things:

  1. Draws a transparent rectangle over the entire chart. This rectangle allows the mouse events to be handled in the RangeSelector rather than be passed to the chart.
  2. Draws the selected region if the mouse is being held down and dragged over the chart.
  3. Transforms the screen coordinates of the selected region into data coordinates that the chart “understands”.
  4. Positions the region’s labels as it expands and contracts due to mouse movement.
  5. Resets the selection region and hide the labels when the mouse is not drawing a new area.

In the constructor, the RangeSelector added labels that show the current date as you drag a selection out and in:

_labelLeft = new Label();
_labelRight = new Label();
addChild(_labelLeft);
addChild(_labelRight);

The startTracking() and endTracking() methods keep track of the mouse when it is clicked and dragged. This rectangular region is what defines the new dates to show on the chart.

I used the parentApplication property to access objects and properties on the main application. It’s not the cleanest or most portable code, but it works, and you could easily write a class that handles the access methods.

The width of the selection area is determined by where the user drags the mouse. But to get the height, I wanted to use the entire height of the chart. To do this, I use the parentApplication property to reach up to the parent app and get the height of the chart itself:

g.drawRect(c[0].x,0,rectWidth, parentApplication.myChart.height);

Later, in the commitProperties() method, the RangeSelector extracts the date information (day, date, and year) to build the label’s text:

leftDate = new Date(dLeft);
rightDate = new Date(dRight);
_labelLeft.text = (leftDate.getMonth()+1) + "/" + leftDate.getDate() + "/" + leftDate.getFullYear();
_labelRight.text = (rightDate.getMonth()+1) + "/" + rightDate.getDate() + "/" + rightDate.getFullYear();

Note that the Date class’s month property is zero-based, so I added 1 to make sure I had the right month in the label.

Finally, when you finish dragging, the RangeSelector modifies the chart’s data in the parent application:

parentApplication.minDate = new Date(dLeft);
parentApplication.maxDate = new Date(dRight);

The minDate and maxDate properties in the parent application are bound to the chart’s DateTimeAxis. By changing these values, the chart’s axis changes. As a result, the data shown on the chart changes.

<mx:horizontalAxis>
<mx:DateTimeAxis id="hAxis"
dataUnits="days"
minimum="{minDate}"
maximum="{maxDate}"/>
</mx:horizontalAxis>

When the chart data changes, the RangeSelector also adjusts the size of the plot points. In this case, I adjust the size of the plot points at the same ratio as the size of the selection is to the chart area. For example, if you drew a selection area half the size of the chart, the plot points increase 50% in size. The smaller the selection, the greater the increase in size of the plot points.

var plotPointRatio:Number = rectWidth/parentApplication.myChart.width;
var curRadius:int = parentApplication.series1.getStyle("radius");
parentApplication.series1.setStyle("radius", curRadius *(1 - plotPointRatio + 1));
parentApplication.series2.setStyle("radius", curRadius *(1 - plotPointRatio + 1));
parentApplication.series3.setStyle("radius", curRadius *(1 - plotPointRatio + 1));

In the main app, when you hit reset, the radii of the plot points are reset to their defaults, and the minDate and maxDate properties are reset. The chart’s axis returns to its original range:

minDate = null;
maxDate = null;
...
series1.setStyle("radius", 5);
series2.setStyle("radius", 5);
series3.setStyle("radius", 5);

You can download the source here:

DateSelectionExample.mxml
RangeSelector.as

Writing secure Flex apps with help from SWFScan

Slashdot has an interesting entry on Flash security today. It features HP’s SWFScan utility that decompiles and scans SWF files, and reports any vulnerabilities that it finds.

What I found really useful was the list of vulnerabilities that SWFScan looks for. You can read through them (there’s about 50) as sort of a “refresher” on what a secure app should look like. To do that:

  1. Download and install SWFScan from http://www.hp.com/go/swfscan.
  2. Run SWFScan.
  3. Click the Settings button. The Settings dialog box displays.
  4. Select the Checks tab. Then just click on each one of hte items to read about the vulnerability and the potential fix for it.

Good stuff! The tool runs on Windows only, unfortunately.

Simple Twitter client in Flex

There’s been an increase in talk about Twitter lately, so I decided to try my hand at building a simple client that displays Twitter messages in Flex. Turns out, it was even easier than I thought, so I’ll share it in a quick blog entry.

I used an HTTPService with the resultFormat set to e4x to get the status information. In the result handler, I set the result to an XML object. Twitter.com has some very comprehensive documentation that cover all the service call APIs and return types here:
http://apiwiki.twitter.com/REST+API+Documentation

To display the Twitter statuses, I used an inline item renderer inside a List control. Simple to do and it looks good for a minimum amount of effort.

You need a proxy page that requests data from Twitter, since Twitter.com does not have an open crossdomain.xml file. In this case, we have an ASP.NET server available with an open crossdomain file, so my proxy page (twit.aspx) is written in C# and put up on that server. I am more familiar with PHP server-side code, so it was a little tricky to get the C# syntax right.

My ASPX syntax uses the System.Net.WebClient.DownloadData() method to do the same thing that the file_get_contents() PHP function does.

If you have a PHP server, there’s already an example written in PHP that you can also look at:
http://www.blackcj.com/blog/tag/cross-domain-xml/

Twitter statuses are sent out every 60 seconds, so I used a timer that calls send() on the HTTPService every 60 seconds. This is configurable, too, but there’s no point in making the updates shorter than 60 seconds, according to the Twitter documentation.

This example is currently set up so you can use the twit.aspx page on aspexamples.adobe.com as a test page. You just pass a username to it with a GET request, setting the p parameter to the username you want to track. In my example, I hardwired my Twitter address so you can see it running, but you can put any username in there that you want when you build your own client. Please don’t use the service for production reasons, or we’ll have to lock it down.

Download the files mentioned in this article:
Download file (2K)

Enjoy!

Changing chart series color at run time with a ColorPicker

A recent thread in the Flex support forums resulted in a couple of new charting examples. Specifically, a user was trying to use a ColorPicker component to change the color of a series in a chart at run time. Turns out, it was a little tricky, so I figured I should share the examples.

The first example shows a LineChart. You can click on an item in the chart, which brings up a ColorPicker. You select a color and Flex applies that color to the selected series.

The meat of the example is in the itemClick handler. This is where you get a reference to the LineSeries by accessing the LineSeriesItem’s element property. Here’s the code:

private function selectItemHandler(e:ChartItemEvent):void {
var hitData:HitData = e.hitData;
csi = LineSeriesItem(hitData.chartItem);
el = ChartElement(csi.element);

cp = new ColorPicker();
myChart.addChild(cp);
cp.addEventListener(ColorPickerEvent.CHANGE, changeItemColor);
cp.x = e.localX;
cp.y = e.localY;
cp.open();
}

The changeItemColor() method is pretty straightforward. For a LineChart’s series, you define a new Stroke and then apply that Stroke to the series’ lineStroke style. You then remove the ColorPicker from the display list so it doesn’t pollute the chart’s appearance. Here’s the code for that:

private function changeItemColor(e:ColorPickerEvent):void {
var s1:Stroke = new Stroke(cp.selectedColor, 4, 1);
el.setStyle("lineStroke", s1);
myChart.removeChild(cp);
}

Here’s a running example:

To change the color of a series like a ColumnSeries or a BarSeries, you have to apply the style a little bit differently. In this case, you define a SolidColor and then apply that to the series’ fill property.

var c:SolidColor = new SolidColor(cp.selectedColor);
el.setStyle("fill", c);

Here’s the running example:

The final example is a little different in that it applies the color to a single item in the series and not the entire series. I thought it was interesting, so I figure I’d share it.

Instead of applying a style to the series, you set the fill property on the ColumnSeriesItem:

var c:SolidColor = new SolidColor(cp.selectedColor);
csi.fill = c;

In addition, to get it to work requires a little workaround: You have to trigger a call to the series’ updateDisplayList(). To do that, you just set a property on the itemRenderer, like this:

csi.itemRenderer.height = csi.itemRenderer.height;

Here’s the running example:

Here is a ZIP file of the 3 running examples and the source code:
Download file (985KB)

You might notice that these examples also use the live data that I blogged about recently.